Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 (function() { | 5 (function() { |
| 6 | 6 |
| 7 'use strict'; | 7 'use strict'; |
| 8 | 8 |
| 9 /** @type {MockConsent} */ | 9 /** @type {MockConsent} */ |
| 10 var consentDialog = null; | 10 var consentDialog = null; |
| 11 /** @type {sinon.Spy | Function} */ | 11 /** @type {sinon.Spy | Function} */ |
| 12 var promptForConsent = null; | 12 var promptForConsent = null; |
| 13 /** @type {sinon.Spy | Function} */ | 13 /** @type {sinon.Spy | Function} */ |
| 14 var getAuthToken = null; | 14 var getAuthToken = null; |
| 15 /** @type {remoting.Identity} */ | 15 /** @type {remoting.Identity} */ |
| 16 var identity = null; | 16 var identity = null; |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * @param {QUnit.Assert} assert | 19 * @param {QUnit.Assert} assert |
| 20 * @constructor | 20 * @constructor |
| 21 * @implements {remoting.Identity.ConsentDialog} | 21 * @implements {remoting.Identity.ConsentDialog} |
| 22 */ | 22 */ |
| 23 var MockConsent = function(assert) { | 23 var MockConsent = function(assert) { |
| 24 /** @type {boolean} */ | 24 /** @type {boolean} */ |
| 25 this.grantConsent = true; | 25 this.grantConsent = true; |
| 26 /** @type {Array<string> | undefined} */ | |
| 27 this.scopes = undefined; | |
|
Jamie
2015/03/18 01:01:09
This was not being used. It was a hangover from th
| |
| 28 /** @private {QUnit.Assert} */ | 26 /** @private {QUnit.Assert} */ |
| 29 this.assert_ = assert; | 27 this.assert_ = assert; |
| 30 }; | 28 }; |
| 31 | 29 |
| 32 MockConsent.prototype.show = function() { | 30 MockConsent.prototype.show = function() { |
| 33 // The consent dialog should only be shown if a previous call to getAuthToken | 31 // The consent dialog should only be shown if a previous call to getAuthToken |
| 34 // with {interactive: false} failed, and it should occur before any call with | 32 // with {interactive: false} failed, and it should occur before any call with |
| 35 // {interactive: true}. | 33 // {interactive: true}. |
| 36 this.assert_.ok(getAuthToken.calledOnce); | 34 this.assert_.ok(getAuthToken.calledOnce); |
| 37 this.assert_.ok(getAuthToken.calledWith({'interactive': false})); | 35 this.assert_.ok(getAuthToken.calledWith( |
| 36 {'interactive': false, scopes: undefined})); | |
| 38 getAuthToken.reset(); | 37 getAuthToken.reset(); |
| 39 | 38 |
| 40 if (this.grantConsent) { | 39 if (this.grantConsent) { |
| 41 chromeMocks.identity.mock$setToken('token'); | 40 chromeMocks.identity.mock$setToken('token'); |
| 42 } | 41 } |
| 43 return Promise.resolve(); | 42 return Promise.resolve(); |
| 44 }; | 43 }; |
| 45 | 44 |
| 46 QUnit.module('Identity', { | 45 QUnit.module('Identity', { |
| 47 beforeEach: function(/** QUnit.Assert*/ assert) { | 46 beforeEach: function(/** QUnit.Assert*/ assert) { |
| 48 chromeMocks.identity.mock$clearToken(); | 47 chromeMocks.identity.mock$clearToken(); |
| 49 chromeMocks.activate(['identity', 'runtime']); | 48 chromeMocks.activate(['identity', 'runtime']); |
| 50 consentDialog = new MockConsent(assert); | 49 consentDialog = new MockConsent(assert); |
| 51 promptForConsent = sinon.spy(consentDialog, 'show'); | 50 promptForConsent = sinon.spy(consentDialog, 'show'); |
| 52 identity = new remoting.Identity(consentDialog); | 51 identity = new remoting.Identity(consentDialog); |
| 53 getAuthToken = sinon.spy(chromeMocks.identity, 'getAuthToken'); | 52 getAuthToken = sinon.spy(chromeMocks.identity, 'getAuthToken'); |
| 54 }, | 53 }, |
| 55 afterEach: function() { | 54 afterEach: function() { |
| 56 chromeMocks.restore(); | 55 chromeMocks.restore(); |
| 57 getAuthToken.restore(); | 56 getAuthToken.restore(); |
| 58 } | 57 } |
| 59 }); | 58 }); |
| 60 | 59 |
| 61 QUnit.test('consent is requested only on first invocation', function(assert) { | 60 QUnit.test('consent is requested only on first invocation', function(assert) { |
| 62 assert.ok(!promptForConsent.called); | 61 assert.ok(!promptForConsent.called); |
| 63 return identity.getToken().then( | 62 return identity.getToken().then( |
| 64 function(/** string */ token) { | 63 function(/** string */ token) { |
| 65 assert.ok(promptForConsent.called); | 64 assert.ok(promptForConsent.called); |
| 66 assert.ok(getAuthToken.calledOnce); | 65 assert.ok(getAuthToken.calledOnce); |
| 67 assert.ok(getAuthToken.calledWith({'interactive': true})); | 66 assert.ok(getAuthToken.calledWith( |
| 67 {'interactive': true, 'scopes': undefined})); | |
| 68 | 68 |
| 69 // Request another token. | 69 // Request another token. |
| 70 promptForConsent.reset(); | 70 promptForConsent.reset(); |
| 71 getAuthToken.reset(); | 71 getAuthToken.reset(); |
| 72 return identity.getToken(); | 72 return identity.getToken(); |
| 73 | 73 |
| 74 }).then(function(/** string */ token) { | 74 }).then(function(/** string */ token) { |
| 75 assert.ok(!promptForConsent.called); | 75 assert.ok(!promptForConsent.called); |
| 76 assert.ok(getAuthToken.calledOnce); | 76 assert.ok(getAuthToken.calledOnce); |
| 77 assert.ok(getAuthToken.calledWith({'interactive': true})); | 77 assert.ok(getAuthToken.calledWith({ |
| 78 'interactive': true, 'scopes': undefined})); | |
| 78 assert.equal(token, 'token'); | 79 assert.equal(token, 'token'); |
| 79 }); | 80 }); |
| 80 }); | 81 }); |
| 81 | 82 |
| 83 QUnit.test('requesting an explicit scope works', function(assert) { | |
| 84 assert.ok(!promptForConsent.called); | |
| 85 return identity.getToken().then( | |
| 86 function() { | |
| 87 // Request a token with an explicit scope. | |
| 88 promptForConsent.reset(); | |
| 89 getAuthToken.reset(); | |
| 90 return identity.getToken(['scope']); | |
| 91 | |
| 92 }).then(function(/** string */ token) { | |
| 93 assert.ok(!promptForConsent.called); | |
| 94 assert.ok(getAuthToken.calledOnce); | |
| 95 assert.ok(getAuthToken.calledWith({ | |
| 96 'interactive': true, 'scopes': ['scope']})); | |
| 97 assert.equal(token, 'token["scope"]'); | |
| 98 }); | |
| 99 }); | |
| 100 | |
| 101 QUnit.test('multiple concurrent outstanding requests are handled correctly', | |
| 102 function(assert) { | |
| 103 assert.ok(!promptForConsent.called); | |
| 104 return identity.getToken().then( | |
| 105 function() { | |
| 106 // Request a token with an explicit scope and another without. | |
| 107 promptForConsent.reset(); | |
| 108 getAuthToken.reset(); | |
| 109 var withScope = identity.getToken(['scope']); | |
| 110 var withoutScope = identity.getToken(); | |
| 111 return Promise.all([withScope, withoutScope]); | |
| 112 | |
| 113 }).then(function(/** Array<string> */ tokens) { | |
| 114 assert.ok(!promptForConsent.called); | |
| 115 assert.ok(getAuthToken.calledTwice); | |
| 116 assert.ok(getAuthToken.calledWith({ | |
| 117 'interactive': true, 'scopes': ['scope']})); | |
| 118 assert.ok(getAuthToken.calledWith({ | |
| 119 'interactive': true, 'scopes': undefined})); | |
| 120 assert.equal(tokens.length, 2); | |
| 121 assert.equal(tokens[0], 'token["scope"]'); | |
| 122 assert.equal(tokens[1], 'token'); | |
| 123 }); | |
| 124 }); | |
| 125 | |
| 82 QUnit.test('cancellations are reported correctly', function(assert) { | 126 QUnit.test('cancellations are reported correctly', function(assert) { |
| 83 consentDialog.grantConsent = false; | 127 consentDialog.grantConsent = false; |
| 84 chromeMocks.runtime.lastError.message = 'The user did not approve access.'; | 128 chromeMocks.runtime.lastError.message = 'The user did not approve access.'; |
| 85 return identity.getToken().then( | 129 return identity.getToken().then( |
| 86 function(/** string */ token) { | 130 function(/** string */ token) { |
| 87 assert.ok(false, 'expected getToken() to fail'); | 131 assert.ok(false, 'expected getToken() to fail'); |
| 88 }).catch(function(/** remoting.Error */ error) { | 132 }).catch(function(/** remoting.Error */ error) { |
| 89 assert.equal(error.getTag(), remoting.Error.Tag.CANCELLED); | 133 assert.equal(error.getTag(), remoting.Error.Tag.CANCELLED); |
| 90 }); | 134 }); |
| 91 }); | 135 }); |
| 92 | 136 |
| 93 | 137 |
| 94 QUnit.test('other errors are reported correctly', function(assert) { | 138 QUnit.test('other errors are reported correctly', function(assert) { |
| 95 consentDialog.grantConsent = false; | 139 consentDialog.grantConsent = false; |
| 96 chromeMocks.runtime.lastError.message = '<some other error message>'; | 140 chromeMocks.runtime.lastError.message = '<some other error message>'; |
| 97 return identity.getToken().then( | 141 return identity.getToken().then( |
| 98 function(/** string */ token) { | 142 function(/** string */ token) { |
| 99 assert.ok(false, 'expected getToken() to fail'); | 143 assert.ok(false, 'expected getToken() to fail'); |
| 100 }).catch(function(/** remoting.Error */ error) { | 144 }).catch(function(/** remoting.Error */ error) { |
| 101 assert.equal(error.getTag(), remoting.Error.Tag.NOT_AUTHENTICATED); | 145 assert.equal(error.getTag(), remoting.Error.Tag.NOT_AUTHENTICATED); |
| 102 }); | 146 }); |
| 103 }); | 147 }); |
| 104 | 148 |
| 105 }()); | 149 }()); |
| OLD | NEW |