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.
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} */
19 * @param {QUnit.Assert} assert
21 * @implements {remoting.Identity.ConsentDialog}
23 var MockConsent = function(assert
) {
24 /** @type {boolean} */
25 this.grantConsent
= true;
26 /** @private {QUnit.Assert} */
27 this.assert_
= assert
;
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}));
39 if (this.grantConsent
) {
40 chromeMocks
.identity
.mock
$setToken('token');
42 return Promise
.resolve();
45 QUnit
.module('Identity', {
46 beforeEach: function(/** QUnit.Assert*/ assert
) {
47 chromeMocks
.identity
.mock
$clearToken();
48 consentDialog
= new MockConsent(assert
);
49 promptForConsent
= sinon
.spy(consentDialog
, 'show');
50 identity
= new remoting
.Identity(consentDialog
);
51 getAuthToken
= sinon
.spy(chromeMocks
.identity
, 'getAuthToken');
53 afterEach: function() {
54 getAuthToken
.restore();
58 QUnit
.test('consent is requested only on first invocation', function(assert
) {
59 assert
.ok(!promptForConsent
.called
);
60 return identity
.getToken().then(
61 function(/** string */ token
) {
62 assert
.ok(promptForConsent
.called
);
63 assert
.ok(getAuthToken
.calledOnce
);
64 assert
.ok(getAuthToken
.calledWith(
65 {'interactive': true, 'scopes': undefined}));
67 // Request another token.
68 promptForConsent
.reset();
70 return identity
.getToken();
72 }).then(function(/** string */ token
) {
73 assert
.ok(!promptForConsent
.called
);
74 assert
.ok(getAuthToken
.calledOnce
);
75 assert
.ok(getAuthToken
.calledWith({
76 'interactive': true, 'scopes': undefined}));
77 assert
.equal(token
, 'token');
81 QUnit
.test('requesting an explicit scope works', function(assert
) {
82 assert
.ok(!promptForConsent
.called
);
83 return identity
.getToken().then(
85 // Request a token with an explicit scope.
86 promptForConsent
.reset();
88 return identity
.getToken(['scope']);
90 }).then(function(/** string */ token
) {
91 assert
.ok(!promptForConsent
.called
);
92 assert
.ok(getAuthToken
.calledOnce
);
93 assert
.ok(getAuthToken
.calledWith({
94 'interactive': true, 'scopes': ['scope']}));
95 assert
.equal(token
, 'token["scope"]');
99 QUnit
.test('multiple concurrent outstanding requests are handled correctly',
101 assert
.ok(!promptForConsent
.called
);
102 return identity
.getToken().then(
104 // Request a token with an explicit scope and another without.
105 promptForConsent
.reset();
106 getAuthToken
.reset();
107 var withScope
= identity
.getToken(['scope']);
108 var withoutScope
= identity
.getToken();
109 return Promise
.all([withScope
, withoutScope
]);
111 }).then(function(/** Array<string> */ tokens
) {
112 assert
.ok(!promptForConsent
.called
);
113 assert
.ok(getAuthToken
.calledTwice
);
114 assert
.ok(getAuthToken
.calledWith({
115 'interactive': true, 'scopes': ['scope']}));
116 assert
.ok(getAuthToken
.calledWith({
117 'interactive': true, 'scopes': undefined}));
118 assert
.equal(tokens
.length
, 2);
119 assert
.equal(tokens
[0], 'token["scope"]');
120 assert
.equal(tokens
[1], 'token');
124 QUnit
.test('cancellations are reported correctly', function(assert
) {
125 consentDialog
.grantConsent
= false;
126 chromeMocks
.runtime
.lastError
.message
= 'The user did not approve access.';
127 return identity
.getToken().then(
128 function(/** string */ token
) {
129 assert
.ok(false, 'expected getToken() to fail');
130 }).catch(function(/** remoting.Error */ error
) {
131 assert
.equal(error
.getTag(), remoting
.Error
.Tag
.CANCELLED
);
136 QUnit
.test('other errors are reported correctly', function(assert
) {
137 consentDialog
.grantConsent
= false;
138 chromeMocks
.runtime
.lastError
.message
= '<some other error message>';
139 return identity
.getToken().then(
140 function(/** string */ token
) {
141 assert
.ok(false, 'expected getToken() to fail');
142 }).catch(function(/** remoting.Error */ error
) {
143 assert
.equal(error
.getTag(), remoting
.Error
.Tag
.NOT_AUTHENTICATED
);