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);