OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 (function() { | |
6 | |
7 'use strict'; | |
8 | |
9 /** @type {MockConsent} */ | |
10 var consentDialog = null; | |
11 /** @type {sinon.Spy | Function} */ | |
12 var promptForConsent = null; | |
13 /** @type {sinon.Spy | Function} */ | |
14 var getAuthToken = null; | |
15 /** @type {remoting.Identity} */ | |
16 var identity = null; | |
17 | |
18 /** | |
19 * @param {QUnit.Assert} assert | |
20 * @constructor | |
21 * @implements {remoting.Identity.ConsentDialog} | |
22 */ | |
23 var MockConsent = function(assert) { | |
24 /** @type {boolean} */ | |
25 this.grantConsent = true; | |
26 /** @private {QUnit.Assert} */ | |
27 this.assert_ = assert; | |
28 }; | |
29 | |
30 MockConsent.prototype.show = function() { | |
31 // The consent dialog should only be shown if a previous call to getAuthToken | |
32 // with {interactive: false} failed, and it should occur before any call with | |
33 // {interactive: true}. | |
34 this.assert_.ok(getAuthToken.calledOnce); | |
35 this.assert_.ok(getAuthToken.calledWith( | |
36 {'interactive': false, scopes: undefined})); | |
37 getAuthToken.reset(); | |
38 | |
39 if (this.grantConsent) { | |
40 chromeMocks.identity.mock$setToken('token'); | |
41 } | |
42 return Promise.resolve(); | |
43 }; | |
44 | |
45 QUnit.module('Identity', { | |
46 beforeEach: function(/** QUnit.Assert*/ assert) { | |
47 chromeMocks.identity.mock$clearToken(); | |
48 chromeMocks.activate(['identity', 'runtime']); | |
49 consentDialog = new MockConsent(assert); | |
50 promptForConsent = sinon.spy(consentDialog, 'show'); | |
51 identity = new remoting.Identity(consentDialog); | |
52 getAuthToken = sinon.spy(chromeMocks.identity, 'getAuthToken'); | |
53 }, | |
54 afterEach: function() { | |
55 chromeMocks.restore(); | |
56 getAuthToken.restore(); | |
57 } | |
58 }); | |
59 | |
60 QUnit.test('consent is requested only on first invocation', function(assert) { | |
61 assert.ok(!promptForConsent.called); | |
62 return identity.getToken().then( | |
63 function(/** string */ token) { | |
64 assert.ok(promptForConsent.called); | |
65 assert.ok(getAuthToken.calledOnce); | |
66 assert.ok(getAuthToken.calledWith( | |
67 {'interactive': true, 'scopes': undefined})); | |
68 | |
69 // Request another token. | |
70 promptForConsent.reset(); | |
71 getAuthToken.reset(); | |
72 return identity.getToken(); | |
73 | |
74 }).then(function(/** string */ token) { | |
75 assert.ok(!promptForConsent.called); | |
76 assert.ok(getAuthToken.calledOnce); | |
77 assert.ok(getAuthToken.calledWith({ | |
78 'interactive': true, 'scopes': undefined})); | |
79 assert.equal(token, 'token'); | |
80 }); | |
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 | |
126 QUnit.test('cancellations are reported correctly', function(assert) { | |
127 consentDialog.grantConsent = false; | |
128 chromeMocks.runtime.lastError.message = 'The user did not approve access.'; | |
129 return identity.getToken().then( | |
130 function(/** string */ token) { | |
131 assert.ok(false, 'expected getToken() to fail'); | |
132 }).catch(function(/** remoting.Error */ error) { | |
133 assert.equal(error.getTag(), remoting.Error.Tag.CANCELLED); | |
134 }); | |
135 }); | |
136 | |
137 | |
138 QUnit.test('other errors are reported correctly', function(assert) { | |
139 consentDialog.grantConsent = false; | |
140 chromeMocks.runtime.lastError.message = '<some other error message>'; | |
141 return identity.getToken().then( | |
142 function(/** string */ token) { | |
143 assert.ok(false, 'expected getToken() to fail'); | |
144 }).catch(function(/** remoting.Error */ error) { | |
145 assert.equal(error.getTag(), remoting.Error.Tag.NOT_AUTHENTICATED); | |
146 }); | |
147 }); | |
148 | |
149 }()); | |
OLD | NEW |