@webex/webex-core 2.59.2 → 2.59.3-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +6 -6
- package/README.md +79 -79
- package/babel.config.js +3 -3
- package/dist/config.js +24 -24
- package/dist/config.js.map +1 -1
- package/dist/credentials-config.js +56 -56
- package/dist/credentials-config.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/auth.js +28 -28
- package/dist/interceptors/auth.js.map +1 -1
- package/dist/interceptors/default-options.js +24 -24
- package/dist/interceptors/default-options.js.map +1 -1
- package/dist/interceptors/embargo.js +9 -9
- package/dist/interceptors/embargo.js.map +1 -1
- package/dist/interceptors/network-timing.js +19 -19
- package/dist/interceptors/network-timing.js.map +1 -1
- package/dist/interceptors/payload-transformer.js +19 -19
- package/dist/interceptors/payload-transformer.js.map +1 -1
- package/dist/interceptors/rate-limit.js +40 -40
- package/dist/interceptors/rate-limit.js.map +1 -1
- package/dist/interceptors/redirect.js +13 -13
- package/dist/interceptors/redirect.js.map +1 -1
- package/dist/interceptors/request-event.js +23 -23
- package/dist/interceptors/request-event.js.map +1 -1
- package/dist/interceptors/request-logger.js +13 -13
- package/dist/interceptors/request-logger.js.map +1 -1
- package/dist/interceptors/request-timing.js +23 -23
- package/dist/interceptors/request-timing.js.map +1 -1
- package/dist/interceptors/response-logger.js +19 -19
- package/dist/interceptors/response-logger.js.map +1 -1
- package/dist/interceptors/user-agent.js +29 -29
- package/dist/interceptors/user-agent.js.map +1 -1
- package/dist/interceptors/webex-tracking-id.js +15 -15
- package/dist/interceptors/webex-tracking-id.js.map +1 -1
- package/dist/interceptors/webex-user-agent.js +13 -13
- package/dist/interceptors/webex-user-agent.js.map +1 -1
- package/dist/lib/batcher.js +83 -83
- package/dist/lib/batcher.js.map +1 -1
- package/dist/lib/credentials/credentials.js +103 -103
- package/dist/lib/credentials/credentials.js.map +1 -1
- package/dist/lib/credentials/grant-errors.js +17 -17
- package/dist/lib/credentials/grant-errors.js.map +1 -1
- package/dist/lib/credentials/index.js +2 -2
- package/dist/lib/credentials/index.js.map +1 -1
- package/dist/lib/credentials/scope.js +11 -11
- package/dist/lib/credentials/scope.js.map +1 -1
- package/dist/lib/credentials/token-collection.js +2 -2
- package/dist/lib/credentials/token-collection.js.map +1 -1
- package/dist/lib/credentials/token.js +145 -145
- package/dist/lib/credentials/token.js.map +1 -1
- package/dist/lib/page.js +49 -49
- package/dist/lib/page.js.map +1 -1
- package/dist/lib/services/constants.js.map +1 -1
- package/dist/lib/services/index.js +2 -2
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/interceptors/server-error.js +9 -9
- package/dist/lib/services/interceptors/server-error.js.map +1 -1
- package/dist/lib/services/interceptors/service.js +24 -24
- package/dist/lib/services/interceptors/service.js.map +1 -1
- package/dist/lib/services/metrics.js.map +1 -1
- package/dist/lib/services/service-catalog.js +104 -104
- package/dist/lib/services/service-catalog.js.map +1 -1
- package/dist/lib/services/service-fed-ramp.js.map +1 -1
- package/dist/lib/services/service-host.js +134 -134
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +175 -175
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +38 -38
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/service-url.js +31 -31
- package/dist/lib/services/service-url.js.map +1 -1
- package/dist/lib/services/services.js +245 -245
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/stateless-webex-plugin.js +28 -28
- package/dist/lib/stateless-webex-plugin.js.map +1 -1
- package/dist/lib/storage/decorators.js +27 -27
- package/dist/lib/storage/decorators.js.map +1 -1
- package/dist/lib/storage/errors.js +4 -4
- package/dist/lib/storage/errors.js.map +1 -1
- package/dist/lib/storage/index.js.map +1 -1
- package/dist/lib/storage/make-webex-plugin-store.js +44 -44
- package/dist/lib/storage/make-webex-plugin-store.js.map +1 -1
- package/dist/lib/storage/make-webex-store.js +40 -40
- package/dist/lib/storage/make-webex-store.js.map +1 -1
- package/dist/lib/storage/memory-store-adapter.js +9 -9
- package/dist/lib/storage/memory-store-adapter.js.map +1 -1
- package/dist/lib/webex-core-plugin-mixin.js +13 -13
- package/dist/lib/webex-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-http-error.js +9 -9
- package/dist/lib/webex-http-error.js.map +1 -1
- package/dist/lib/webex-internal-core-plugin-mixin.js +13 -13
- package/dist/lib/webex-internal-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-plugin.js +36 -36
- package/dist/lib/webex-plugin.js.map +1 -1
- package/dist/plugins/logger.js +9 -9
- package/dist/plugins/logger.js.map +1 -1
- package/dist/webex-core.js +104 -104
- package/dist/webex-core.js.map +1 -1
- package/dist/webex-internal-core.js +12 -12
- package/dist/webex-internal-core.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +20 -19
- package/process +1 -1
- package/src/config.js +90 -90
- package/src/credentials-config.js +212 -212
- package/src/index.js +62 -62
- package/src/interceptors/auth.js +186 -186
- package/src/interceptors/default-options.js +55 -55
- package/src/interceptors/embargo.js +43 -43
- package/src/interceptors/network-timing.js +54 -54
- package/src/interceptors/payload-transformer.js +55 -55
- package/src/interceptors/rate-limit.js +169 -169
- package/src/interceptors/redirect.js +106 -106
- package/src/interceptors/request-event.js +93 -93
- package/src/interceptors/request-logger.js +78 -78
- package/src/interceptors/request-timing.js +65 -65
- package/src/interceptors/response-logger.js +98 -98
- package/src/interceptors/user-agent.js +77 -77
- package/src/interceptors/webex-tracking-id.js +73 -73
- package/src/interceptors/webex-user-agent.js +79 -79
- package/src/lib/batcher.js +307 -307
- package/src/lib/credentials/credentials.js +552 -552
- package/src/lib/credentials/grant-errors.js +92 -92
- package/src/lib/credentials/index.js +16 -16
- package/src/lib/credentials/scope.js +34 -34
- package/src/lib/credentials/token-collection.js +17 -17
- package/src/lib/credentials/token.js +559 -559
- package/src/lib/page.js +159 -159
- package/src/lib/services/constants.js +9 -9
- package/src/lib/services/index.js +26 -26
- package/src/lib/services/interceptors/server-error.js +48 -48
- package/src/lib/services/interceptors/service.js +101 -101
- package/src/lib/services/metrics.js +4 -4
- package/src/lib/services/service-catalog.js +435 -435
- package/src/lib/services/service-fed-ramp.js +4 -4
- package/src/lib/services/service-host.js +267 -267
- package/src/lib/services/service-registry.js +465 -465
- package/src/lib/services/service-state.js +78 -78
- package/src/lib/services/service-url.js +124 -124
- package/src/lib/services/services.js +1018 -1018
- package/src/lib/stateless-webex-plugin.js +98 -98
- package/src/lib/storage/decorators.js +220 -220
- package/src/lib/storage/errors.js +15 -15
- package/src/lib/storage/index.js +10 -10
- package/src/lib/storage/make-webex-plugin-store.js +211 -211
- package/src/lib/storage/make-webex-store.js +140 -140
- package/src/lib/storage/memory-store-adapter.js +79 -79
- package/src/lib/webex-core-plugin-mixin.js +114 -114
- package/src/lib/webex-http-error.js +61 -61
- package/src/lib/webex-internal-core-plugin-mixin.js +107 -107
- package/src/lib/webex-plugin.js +222 -222
- package/src/plugins/logger.js +60 -60
- package/src/webex-core.js +745 -745
- package/src/webex-internal-core.js +46 -46
- package/test/integration/spec/credentials/credentials.js +139 -139
- package/test/integration/spec/credentials/token.js +102 -102
- package/test/integration/spec/services/service-catalog.js +838 -838
- package/test/integration/spec/services/services.js +1221 -1221
- package/test/integration/spec/webex-core.js +178 -178
- package/test/unit/spec/_setup.js +44 -44
- package/test/unit/spec/credentials/credentials.js +1017 -1017
- package/test/unit/spec/credentials/token.js +441 -441
- package/test/unit/spec/interceptors/auth.js +521 -521
- package/test/unit/spec/interceptors/default-options.js +84 -84
- package/test/unit/spec/interceptors/embargo.js +144 -144
- package/test/unit/spec/interceptors/network-timing.js +49 -49
- package/test/unit/spec/interceptors/payload-transformer.js +155 -155
- package/test/unit/spec/interceptors/rate-limit.js +302 -302
- package/test/unit/spec/interceptors/redirect.js +102 -102
- package/test/unit/spec/interceptors/request-timing.js +92 -92
- package/test/unit/spec/interceptors/user-agent.js +76 -76
- package/test/unit/spec/interceptors/webex-tracking-id.js +76 -76
- package/test/unit/spec/interceptors/webex-user-agent.js +159 -159
- package/test/unit/spec/lib/batcher.js +330 -330
- package/test/unit/spec/lib/page.js +148 -148
- package/test/unit/spec/lib/webex-plugin.js +48 -48
- package/test/unit/spec/services/interceptors/server-error.js +204 -204
- package/test/unit/spec/services/interceptors/service.js +188 -188
- package/test/unit/spec/services/service-catalog.js +194 -194
- package/test/unit/spec/services/service-host.js +260 -260
- package/test/unit/spec/services/service-registry.js +747 -747
- package/test/unit/spec/services/service-state.js +60 -60
- package/test/unit/spec/services/service-url.js +258 -258
- package/test/unit/spec/services/services.js +348 -348
- package/test/unit/spec/storage/persist.js +50 -50
- package/test/unit/spec/storage/storage-adapter.js +12 -12
- package/test/unit/spec/storage/wait-for-value.js +81 -81
- package/test/unit/spec/webex-core.js +253 -253
- package/test/unit/spec/webex-internal-core.js +91 -91
|
@@ -1,1221 +1,1221 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import '@webex/internal-plugin-device';
|
|
6
|
-
|
|
7
|
-
import {assert} from '@webex/test-helper-chai';
|
|
8
|
-
import {flaky} from '@webex/test-helper-mocha';
|
|
9
|
-
import WebexCore, {
|
|
10
|
-
ServiceCatalog,
|
|
11
|
-
ServiceRegistry,
|
|
12
|
-
ServiceState,
|
|
13
|
-
ServiceUrl,
|
|
14
|
-
} from '@webex/webex-core';
|
|
15
|
-
import testUsers from '@webex/test-helper-test-users';
|
|
16
|
-
import uuid from 'uuid';
|
|
17
|
-
import sinon from 'sinon';
|
|
18
|
-
|
|
19
|
-
/* eslint-disable no-underscore-dangle */
|
|
20
|
-
describe('webex-core', () => {
|
|
21
|
-
describe('Services', () => {
|
|
22
|
-
let webexUser;
|
|
23
|
-
let webexUserEU;
|
|
24
|
-
let webex;
|
|
25
|
-
let webexEU;
|
|
26
|
-
let services;
|
|
27
|
-
let servicesEU;
|
|
28
|
-
let catalog;
|
|
29
|
-
|
|
30
|
-
before('create users', () =>
|
|
31
|
-
Promise.all([
|
|
32
|
-
testUsers.create({count: 1}),
|
|
33
|
-
testUsers.create({
|
|
34
|
-
count: 1,
|
|
35
|
-
config: {
|
|
36
|
-
orgId: process.env.EU_PRIMARY_ORG_ID,
|
|
37
|
-
},
|
|
38
|
-
}),
|
|
39
|
-
]).then(([[user], [userEU]]) => {
|
|
40
|
-
webexUser = user;
|
|
41
|
-
webexUserEU = userEU;
|
|
42
|
-
})
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
beforeEach('create webex instance', () => {
|
|
46
|
-
webex = new WebexCore({credentials: {supertoken: webexUser.token}});
|
|
47
|
-
webexEU = new WebexCore({credentials: {supertoken: webexUserEU.token}});
|
|
48
|
-
services = webex.internal.services;
|
|
49
|
-
servicesEU = webexEU.internal.services;
|
|
50
|
-
catalog = services._getCatalog();
|
|
51
|
-
|
|
52
|
-
return Promise.all([
|
|
53
|
-
services.waitForCatalog('postauth', 10),
|
|
54
|
-
servicesEU.waitForCatalog('postauth', 10),
|
|
55
|
-
]).then(() =>
|
|
56
|
-
services.updateServices({
|
|
57
|
-
from: 'limited',
|
|
58
|
-
query: {userId: webexUser.id},
|
|
59
|
-
})
|
|
60
|
-
);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('#_getCatalog()', () => {
|
|
64
|
-
it('returns a catalog', () => {
|
|
65
|
-
const localCatalog = services._getCatalog();
|
|
66
|
-
|
|
67
|
-
assert.equal(localCatalog.namespace, 'ServiceCatalog');
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('#list()', () => {
|
|
72
|
-
it('matches the values in serviceUrl', () => {
|
|
73
|
-
let serviceList = services.list();
|
|
74
|
-
|
|
75
|
-
Object.keys(serviceList).forEach((key) => {
|
|
76
|
-
assert.equal(serviceList[key], catalog._getUrl(key).get());
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
serviceList = services.list(true);
|
|
80
|
-
Object.keys(serviceList).forEach((key) => {
|
|
81
|
-
assert.equal(serviceList[key], catalog._getUrl(key).get(true));
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('#get()', () => {
|
|
87
|
-
let testUrlTemplate;
|
|
88
|
-
let testUrl;
|
|
89
|
-
|
|
90
|
-
beforeEach('load test url', () => {
|
|
91
|
-
testUrlTemplate = {
|
|
92
|
-
defaultUrl: 'https://www.example.com/api/v1',
|
|
93
|
-
hosts: [],
|
|
94
|
-
name: 'exampleValid',
|
|
95
|
-
};
|
|
96
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
97
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
afterEach('unload test url', () => {
|
|
101
|
-
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('returns a valid string when name is specified', () => {
|
|
105
|
-
const url = services.get(testUrlTemplate.name);
|
|
106
|
-
|
|
107
|
-
assert.typeOf(url, 'string');
|
|
108
|
-
assert.equal(url, testUrlTemplate.defaultUrl);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("returns undefined if url doesn't exist", () => {
|
|
112
|
-
const s = services.get('invalidUrl');
|
|
113
|
-
|
|
114
|
-
assert.typeOf(s, 'undefined');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('gets a service from a specific serviceGroup', () => {
|
|
118
|
-
assert.isDefined(services.get(testUrlTemplate.name, false, 'preauth'));
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("fails to get a service if serviceGroup isn't accurate", () => {
|
|
122
|
-
assert.isUndefined(services.get(testUrlTemplate.name, false, 'discovery'));
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('#getClusterId()', () => {
|
|
127
|
-
let testUrlTemplate;
|
|
128
|
-
let testUrl;
|
|
129
|
-
|
|
130
|
-
beforeEach('load test url', () => {
|
|
131
|
-
testUrlTemplate = {
|
|
132
|
-
defaultUrl: 'https://www.example.com/api/v1',
|
|
133
|
-
hosts: [
|
|
134
|
-
{
|
|
135
|
-
homeCluster: true,
|
|
136
|
-
host: 'www.example-p5.com',
|
|
137
|
-
ttl: -1,
|
|
138
|
-
priority: 5,
|
|
139
|
-
id: 'exampleClusterId',
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
host: 'www.example-p3.com',
|
|
143
|
-
ttl: -1,
|
|
144
|
-
priority: 3,
|
|
145
|
-
id: 'exampleClusterId',
|
|
146
|
-
},
|
|
147
|
-
],
|
|
148
|
-
name: 'exampleValid',
|
|
149
|
-
};
|
|
150
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
151
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('returns a clusterId when found with default url', () => {
|
|
155
|
-
assert.equal(
|
|
156
|
-
services.getClusterId(testUrlTemplate.defaultUrl),
|
|
157
|
-
testUrlTemplate.hosts[0].id
|
|
158
|
-
);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('returns a clusterId when found with priority host url', () => {
|
|
162
|
-
assert.equal(services.getClusterId(testUrl.get(true)), testUrlTemplate.hosts[0].id);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('returns a clusterId when found with resource-appended url', () => {
|
|
166
|
-
assert.equal(
|
|
167
|
-
services.getClusterId(`${testUrl.get()}example/resource/value`),
|
|
168
|
-
testUrlTemplate.hosts[0].id
|
|
169
|
-
);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("returns undefined when the url doesn't exist in catalog", () => {
|
|
173
|
-
assert.isUndefined(services.getClusterId('http://not-a-known-url.com/'));
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("returns undefined when the string isn't a url", () => {
|
|
177
|
-
assert.isUndefined(services.getClusterId('not a url'));
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
describe('#getServiceFromClusterId()', () => {
|
|
182
|
-
let testUrlTemplate;
|
|
183
|
-
let testUrl;
|
|
184
|
-
|
|
185
|
-
beforeEach('load test url', () => {
|
|
186
|
-
testUrlTemplate = {
|
|
187
|
-
defaultUrl: 'https://www.example.com/api/v1',
|
|
188
|
-
hosts: [
|
|
189
|
-
{
|
|
190
|
-
homeCluster: true,
|
|
191
|
-
host: 'www.example-p5.com',
|
|
192
|
-
ttl: -1,
|
|
193
|
-
priority: 5,
|
|
194
|
-
id: '0:0:cluster-a:exampleValid',
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
host: 'www.example-p3.com',
|
|
198
|
-
ttl: -1,
|
|
199
|
-
priority: 3,
|
|
200
|
-
id: '0:0:cluster-b:exampleValid',
|
|
201
|
-
},
|
|
202
|
-
],
|
|
203
|
-
name: 'exampleValid',
|
|
204
|
-
};
|
|
205
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
206
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('finds a valid service url from only a clusterId', () => {
|
|
210
|
-
const serviceFound = services.getServiceFromClusterId({
|
|
211
|
-
clusterId: testUrlTemplate.hosts[0].id,
|
|
212
|
-
priorityHost: false,
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
assert.equal(serviceFound.name, testUrl.name);
|
|
216
|
-
assert.equal(serviceFound.url, testUrl.defaultUrl);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it('finds a valid priority service url', () => {
|
|
220
|
-
const serviceFound = services.getServiceFromClusterId({
|
|
221
|
-
clusterId: testUrlTemplate.hosts[0].id,
|
|
222
|
-
priorityHost: true,
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
assert.equal(serviceFound.name, testUrl.name);
|
|
226
|
-
assert.isTrue(
|
|
227
|
-
serviceFound.url.includes(testUrlTemplate.hosts[0].host),
|
|
228
|
-
`'${serviceFound.url}' is not host '${testUrlTemplate.hosts[0].host}'`
|
|
229
|
-
);
|
|
230
|
-
// assert.equal(serviceFound.url, catalog.get('exampleValid', true));
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('finds a valid service when a service group is defined', () => {
|
|
234
|
-
const serviceFound = catalog.findServiceFromClusterId({
|
|
235
|
-
clusterId: testUrlTemplate.hosts[0].id,
|
|
236
|
-
priorityHost: false,
|
|
237
|
-
serviceGroup: 'preauth',
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
assert.equal(serviceFound.name, testUrl.name);
|
|
241
|
-
assert.equal(serviceFound.url, testUrl.defaultUrl);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("fails to find a valid service when it's not in a group", () => {
|
|
245
|
-
assert.isUndefined(
|
|
246
|
-
services.getServiceFromClusterId({
|
|
247
|
-
clusterId: testUrlTemplate.hosts[0].id,
|
|
248
|
-
serviceGroup: 'signin',
|
|
249
|
-
})
|
|
250
|
-
);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it("returns undefined when service doesn't exist", () => {
|
|
254
|
-
assert.isUndefined(services.getServiceFromClusterId({clusterId: 'not a clusterId'}));
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
describe('#getServiceFromUrl()', () => {
|
|
259
|
-
let testUrlTemplate;
|
|
260
|
-
let testUrl;
|
|
261
|
-
|
|
262
|
-
beforeEach('load test url', () => {
|
|
263
|
-
testUrlTemplate = {
|
|
264
|
-
defaultUrl: 'https://www.example.com/api/v1',
|
|
265
|
-
hosts: [
|
|
266
|
-
{
|
|
267
|
-
host: 'www.example-p5.com',
|
|
268
|
-
ttl: -1,
|
|
269
|
-
priority: 5,
|
|
270
|
-
id: 'exampleClusterId',
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
host: 'www.example-p3.com',
|
|
274
|
-
ttl: -1,
|
|
275
|
-
priority: 3,
|
|
276
|
-
id: 'exampleClusterId',
|
|
277
|
-
},
|
|
278
|
-
],
|
|
279
|
-
name: 'exampleValid',
|
|
280
|
-
};
|
|
281
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
282
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
afterEach('unload test url', () => {
|
|
286
|
-
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('gets a valid service object from an existing service', () => {
|
|
290
|
-
const serviceObject = services.getServiceFromUrl(testUrlTemplate.defaultUrl);
|
|
291
|
-
|
|
292
|
-
assert.isDefined(serviceObject);
|
|
293
|
-
assert.hasAllKeys(serviceObject, ['name', 'defaultUrl', 'priorityUrl']);
|
|
294
|
-
|
|
295
|
-
assert.equal(testUrlTemplate.name, serviceObject.name);
|
|
296
|
-
assert.equal(testUrlTemplate.defaultUrl, serviceObject.defaultUrl);
|
|
297
|
-
assert.equal(testUrl.get(true), serviceObject.priorityUrl);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
it("returns undefined when the service url doesn't exist", () => {
|
|
301
|
-
const serviceObject = services.getServiceFromUrl('http://www.not-real.com/');
|
|
302
|
-
|
|
303
|
-
assert.isUndefined(serviceObject);
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
describe('#hasService()', () => {
|
|
308
|
-
it('returns a boolean', () => {
|
|
309
|
-
assert.isBoolean(services.hasService('some-url'));
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
it('validates that a service exists', () => {
|
|
313
|
-
const service = Object.keys(services.list())[0];
|
|
314
|
-
|
|
315
|
-
assert.isTrue(services.hasService(service));
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
describe('#initConfig()', () => {
|
|
320
|
-
it('should set the discovery catalog based on the provided links', () => {
|
|
321
|
-
const key = 'test';
|
|
322
|
-
const url = 'http://www.test.com/';
|
|
323
|
-
|
|
324
|
-
webex.config.services.discovery[key] = url;
|
|
325
|
-
|
|
326
|
-
services.initConfig();
|
|
327
|
-
|
|
328
|
-
assert.equal(services.get(key), url);
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it('should set the override catalog based on the provided links', () => {
|
|
332
|
-
const key = 'testOverride';
|
|
333
|
-
const url = 'http://www.test-override.com/';
|
|
334
|
-
|
|
335
|
-
webex.config.services.override = {};
|
|
336
|
-
webex.config.services.override[key] = url;
|
|
337
|
-
|
|
338
|
-
services.initConfig();
|
|
339
|
-
|
|
340
|
-
assert.equal(services.get(key), url);
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it('should set validate domains to true when provided true', () => {
|
|
344
|
-
webex.config.services.validateDomains = true;
|
|
345
|
-
|
|
346
|
-
services.initConfig();
|
|
347
|
-
|
|
348
|
-
assert.isTrue(services.validateDomains);
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
it('should set validate domains to false when provided false', () => {
|
|
352
|
-
webex.config.services.validateDomains = false;
|
|
353
|
-
|
|
354
|
-
services.initConfig();
|
|
355
|
-
|
|
356
|
-
assert.isFalse(services.validateDomains);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it('should set the allowed domains based on the provided domains', () => {
|
|
360
|
-
const allowedDomains = ['domain'];
|
|
361
|
-
|
|
362
|
-
webex.config.services.allowedDomains = allowedDomains;
|
|
363
|
-
|
|
364
|
-
services.initConfig();
|
|
365
|
-
|
|
366
|
-
assert.deepEqual(allowedDomains, services._getCatalog().allowedDomains);
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
describe('#initialize()', () => {
|
|
371
|
-
it('should create a catalog', () =>
|
|
372
|
-
assert.instanceOf(services._getCatalog(), ServiceCatalog));
|
|
373
|
-
|
|
374
|
-
it('should create a registry', () =>
|
|
375
|
-
assert.instanceOf(services.getRegistry(), ServiceRegistry));
|
|
376
|
-
|
|
377
|
-
it('should create a state', () => assert.instanceOf(services.getState(), ServiceState));
|
|
378
|
-
|
|
379
|
-
it('should call services#initConfig() when webex config changes', () => {
|
|
380
|
-
services.initConfig = sinon.spy();
|
|
381
|
-
services.initialize();
|
|
382
|
-
webex.trigger('change:config');
|
|
383
|
-
assert.called(services.initConfig);
|
|
384
|
-
assert.isTrue(catalog.isReady);
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
it('should call services#initServiceCatalogs() on webex ready', () => {
|
|
388
|
-
services.initServiceCatalogs = sinon.stub().resolves();
|
|
389
|
-
services.initialize();
|
|
390
|
-
webex.trigger('ready');
|
|
391
|
-
assert.called(services.initServiceCatalogs);
|
|
392
|
-
assert.isTrue(catalog.isReady);
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
it('should collect different catalogs based on OrgId region', () =>
|
|
396
|
-
assert.notDeepEqual(services.list(true), servicesEU.list(true)));
|
|
397
|
-
|
|
398
|
-
it('should not attempt to collect catalogs without authorization', (done) => {
|
|
399
|
-
const otherWebex = new WebexCore();
|
|
400
|
-
let {initServiceCatalogs} = otherWebex.internal.services;
|
|
401
|
-
|
|
402
|
-
initServiceCatalogs = sinon.stub();
|
|
403
|
-
|
|
404
|
-
setTimeout(() => {
|
|
405
|
-
assert.notCalled(initServiceCatalogs);
|
|
406
|
-
assert.isFalse(otherWebex.internal.services._getCatalog().isReady);
|
|
407
|
-
done();
|
|
408
|
-
}, 2000);
|
|
409
|
-
});
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
describe('#initServiceCatalogs()', () => {
|
|
413
|
-
it('should reject if a OrgId cannot be retrieved', () => {
|
|
414
|
-
webex.credentials.getOrgId = sinon.stub().throws();
|
|
415
|
-
|
|
416
|
-
return assert.isRejected(services.initServiceCatalogs());
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it('should call services#collectPreauthCatalog with the OrgId', () => {
|
|
420
|
-
services.collectPreauthCatalog = sinon.stub().resolves();
|
|
421
|
-
|
|
422
|
-
return services.initServiceCatalogs().then(() =>
|
|
423
|
-
assert.calledWith(
|
|
424
|
-
services.collectPreauthCatalog,
|
|
425
|
-
sinon.match({
|
|
426
|
-
orgId: webex.credentials.getOrgId(),
|
|
427
|
-
})
|
|
428
|
-
)
|
|
429
|
-
);
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
it('should not call services#updateServices() when not authed', () => {
|
|
433
|
-
services.updateServices = sinon.stub().resolves();
|
|
434
|
-
|
|
435
|
-
// Since credentials uses AmpState, we have to set the derived
|
|
436
|
-
// properties of the dependent properties to undefined.
|
|
437
|
-
webex.credentials.supertoken.access_token = undefined;
|
|
438
|
-
webex.credentials.supertoken.refresh_token = undefined;
|
|
439
|
-
|
|
440
|
-
webex.credentials.getOrgId = sinon.stub().returns(webexUser.orgId);
|
|
441
|
-
|
|
442
|
-
return (
|
|
443
|
-
services
|
|
444
|
-
.initServiceCatalogs()
|
|
445
|
-
// services#updateServices() gets called once by the limited catalog
|
|
446
|
-
// retrieval and should not be called again when not authorized.
|
|
447
|
-
.then(() => assert.calledOnce(services.updateServices))
|
|
448
|
-
);
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
it('should call services#updateServices() when authed', () => {
|
|
452
|
-
services.updateServices = sinon.stub().resolves();
|
|
453
|
-
|
|
454
|
-
return (
|
|
455
|
-
services
|
|
456
|
-
.initServiceCatalogs()
|
|
457
|
-
// services#updateServices() gets called once by the limited catalog
|
|
458
|
-
// retrieval and should get called again when authorized.
|
|
459
|
-
.then(() => assert.calledTwice(services.updateServices))
|
|
460
|
-
);
|
|
461
|
-
});
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
describe('#isServiceUrl()', () => {
|
|
465
|
-
let testUrlTemplate;
|
|
466
|
-
let testUrl;
|
|
467
|
-
|
|
468
|
-
beforeEach('load test url', () => {
|
|
469
|
-
testUrlTemplate = {
|
|
470
|
-
defaultUrl: 'https://www.example.com/api/v1',
|
|
471
|
-
hosts: [
|
|
472
|
-
{
|
|
473
|
-
homeCluster: true,
|
|
474
|
-
host: 'www.example-p5.com',
|
|
475
|
-
ttl: -1,
|
|
476
|
-
priority: 5,
|
|
477
|
-
id: 'exampleClusterId',
|
|
478
|
-
},
|
|
479
|
-
{
|
|
480
|
-
host: 'www.example-p3.com',
|
|
481
|
-
ttl: -1,
|
|
482
|
-
priority: 3,
|
|
483
|
-
id: 'exampleClusterId',
|
|
484
|
-
},
|
|
485
|
-
],
|
|
486
|
-
name: 'exampleValid',
|
|
487
|
-
};
|
|
488
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
489
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
it('returns true if url is a service url', () => {
|
|
493
|
-
assert.isTrue(services.isServiceUrl(testUrlTemplate.defaultUrl));
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
it('returns true for priority host urls', () => {
|
|
497
|
-
assert.isTrue(services.isServiceUrl(testUrl.get(true)));
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it("returns undefined if the url doesn't exist", () => {
|
|
501
|
-
assert.isFalse(services.isServiceUrl('https://na.com/'));
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
it('returns undefined if the param is not a url', () => {
|
|
505
|
-
assert.isFalse(services.isServiceUrl('not a url'));
|
|
506
|
-
});
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
describe('#isAllowedDomainUrl()', () => {
|
|
510
|
-
let list;
|
|
511
|
-
|
|
512
|
-
beforeEach(() => {
|
|
513
|
-
catalog.setAllowedDomains(['some-domain-a', 'some-domain-b']);
|
|
514
|
-
|
|
515
|
-
list = catalog.getAllowedDomains();
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
it('returns a boolean', () => {
|
|
519
|
-
assert.isBoolean(services.isAllowedDomainUrl(''));
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
it('returns true if the url contains an allowed domain', () => {
|
|
523
|
-
assert.isTrue(services.isAllowedDomainUrl(`https://${list[0]}/resource`));
|
|
524
|
-
});
|
|
525
|
-
|
|
526
|
-
it('returns false if the url does not contain an allowed domain', () => {
|
|
527
|
-
assert.isFalse(services.isAllowedDomainUrl('https://bad-domain/resource'));
|
|
528
|
-
});
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
describe('#convertUrlToPriorityUrl', () => {
|
|
532
|
-
let testUrl;
|
|
533
|
-
let testUrlTemplate;
|
|
534
|
-
|
|
535
|
-
beforeEach('load test url', () => {
|
|
536
|
-
testUrlTemplate = {
|
|
537
|
-
defaultUrl: 'https://www.example.com/api/v1',
|
|
538
|
-
hosts: [
|
|
539
|
-
{
|
|
540
|
-
homeCluster: true,
|
|
541
|
-
host: 'www.example-p5.com',
|
|
542
|
-
ttl: -1,
|
|
543
|
-
priority: 5,
|
|
544
|
-
id: '0:0:cluster-a:exampleValid',
|
|
545
|
-
},
|
|
546
|
-
{
|
|
547
|
-
host: 'www.example-p3.com',
|
|
548
|
-
ttl: -1,
|
|
549
|
-
priority: 3,
|
|
550
|
-
id: '0:0:cluster-b:exampleValid',
|
|
551
|
-
},
|
|
552
|
-
],
|
|
553
|
-
name: 'exampleValid',
|
|
554
|
-
};
|
|
555
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
556
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
it('converts the url to a priority host url', () => {
|
|
560
|
-
const resource = 'path/to/resource';
|
|
561
|
-
const url = `${testUrlTemplate.defaultUrl}/${resource}`;
|
|
562
|
-
|
|
563
|
-
const convertUrl = services.convertUrlToPriorityHostUrl(url);
|
|
564
|
-
|
|
565
|
-
assert.isDefined(convertUrl);
|
|
566
|
-
assert.isTrue(convertUrl.includes(testUrlTemplate.hosts[0].host));
|
|
567
|
-
});
|
|
568
|
-
|
|
569
|
-
it('throws an exception if not a valid service', () => {
|
|
570
|
-
assert.throws(services.convertUrlToPriorityHostUrl, Error);
|
|
571
|
-
|
|
572
|
-
assert.throws(
|
|
573
|
-
services.convertUrlToPriorityHostUrl.bind(services, 'not-a-valid-service'),
|
|
574
|
-
Error
|
|
575
|
-
);
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
afterEach('unload test url', () => {
|
|
579
|
-
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
580
|
-
});
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
describe('#markFailedUrl()', () => {
|
|
584
|
-
let testUrlTemplate;
|
|
585
|
-
let testUrl;
|
|
586
|
-
|
|
587
|
-
beforeEach('load test url', () => {
|
|
588
|
-
catalog.clean();
|
|
589
|
-
|
|
590
|
-
testUrlTemplate = {
|
|
591
|
-
defaultUrl: 'https://www.example-phr.com/api/v1',
|
|
592
|
-
hosts: [
|
|
593
|
-
{
|
|
594
|
-
host: 'www.example-phr-p5.com',
|
|
595
|
-
ttl: -1,
|
|
596
|
-
priority: 5,
|
|
597
|
-
homeCluster: true,
|
|
598
|
-
},
|
|
599
|
-
{
|
|
600
|
-
host: 'www.example-phr-p3.com',
|
|
601
|
-
ttl: -1,
|
|
602
|
-
priority: 3,
|
|
603
|
-
homeCluster: true,
|
|
604
|
-
},
|
|
605
|
-
],
|
|
606
|
-
name: 'exampleValid-phr',
|
|
607
|
-
};
|
|
608
|
-
testUrl = new ServiceUrl(testUrlTemplate);
|
|
609
|
-
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
afterEach('unload test url', () => {
|
|
613
|
-
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
it('marks a host as failed', () => {
|
|
617
|
-
const priorityServiceUrl = catalog._getUrl(testUrlTemplate.name);
|
|
618
|
-
const priorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
619
|
-
|
|
620
|
-
services.markFailedUrl(priorityUrl);
|
|
621
|
-
|
|
622
|
-
const failedHost = priorityServiceUrl.hosts.find((host) => host.failed);
|
|
623
|
-
|
|
624
|
-
assert.isTrue(priorityUrl.includes(failedHost.host));
|
|
625
|
-
});
|
|
626
|
-
|
|
627
|
-
it('returns the next priority url', () => {
|
|
628
|
-
const priorityUrl = services.get(testUrlTemplate.name, true);
|
|
629
|
-
|
|
630
|
-
const nextPriorityUrl = services.markFailedUrl(priorityUrl);
|
|
631
|
-
|
|
632
|
-
assert.notEqual(priorityUrl, nextPriorityUrl);
|
|
633
|
-
});
|
|
634
|
-
|
|
635
|
-
it('should reset hosts once all hosts have been marked failed', () => {
|
|
636
|
-
const priorityServiceUrl = catalog._getUrl(testUrlTemplate.name);
|
|
637
|
-
const firstPriorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
638
|
-
|
|
639
|
-
priorityServiceUrl.hosts.forEach(() => {
|
|
640
|
-
const priorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
641
|
-
|
|
642
|
-
services.markFailedUrl(priorityUrl);
|
|
643
|
-
});
|
|
644
|
-
|
|
645
|
-
const lastPriorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
646
|
-
|
|
647
|
-
assert.equal(firstPriorityUrl, lastPriorityUrl);
|
|
648
|
-
});
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
describe('#updateServices()', () => {
|
|
652
|
-
it('returns a Promise that and resolves on success', (done) => {
|
|
653
|
-
const servicesPromise = services.updateServices();
|
|
654
|
-
|
|
655
|
-
assert.typeOf(servicesPromise, 'Promise');
|
|
656
|
-
|
|
657
|
-
servicesPromise.then(() => {
|
|
658
|
-
Object.keys(services.list()).forEach((key) => {
|
|
659
|
-
assert.typeOf(key, 'string');
|
|
660
|
-
assert.typeOf(services.list()[key], 'string');
|
|
661
|
-
});
|
|
662
|
-
|
|
663
|
-
done();
|
|
664
|
-
});
|
|
665
|
-
});
|
|
666
|
-
|
|
667
|
-
it('updates the services list', (done) => {
|
|
668
|
-
catalog.serviceGroups.postauth = [];
|
|
669
|
-
|
|
670
|
-
services.updateServices().then(() => {
|
|
671
|
-
assert.isAbove(catalog.serviceGroups.postauth.length, 0);
|
|
672
|
-
done();
|
|
673
|
-
});
|
|
674
|
-
|
|
675
|
-
services.updateServices();
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
it('updates query.email to be emailhash-ed using SHA256', (done) => {
|
|
679
|
-
catalog.updateServiceUrls = sinon.stub().returns({}); // returns `this`
|
|
680
|
-
services._fetchNewServiceHostmap = sinon.stub().resolves();
|
|
681
|
-
|
|
682
|
-
services
|
|
683
|
-
.updateServices({
|
|
684
|
-
from: 'limited',
|
|
685
|
-
query: {email: webexUser.email},
|
|
686
|
-
})
|
|
687
|
-
.then(() => {
|
|
688
|
-
assert.calledWith(
|
|
689
|
-
services._fetchNewServiceHostmap,
|
|
690
|
-
sinon.match.has('query', {emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)})
|
|
691
|
-
);
|
|
692
|
-
done();
|
|
693
|
-
});
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
it('updates the limited catalog when email is provided', (done) => {
|
|
697
|
-
catalog.serviceGroups.preauth = [];
|
|
698
|
-
|
|
699
|
-
services
|
|
700
|
-
.updateServices({
|
|
701
|
-
from: 'limited',
|
|
702
|
-
query: {email: webexUser.email},
|
|
703
|
-
})
|
|
704
|
-
.then(() => {
|
|
705
|
-
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
706
|
-
done();
|
|
707
|
-
});
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
it('updates the limited catalog when userId is provided', (done) => {
|
|
711
|
-
catalog.serviceGroups.preauth = [];
|
|
712
|
-
|
|
713
|
-
services
|
|
714
|
-
.updateServices({
|
|
715
|
-
from: 'limited',
|
|
716
|
-
query: {userId: webexUser.id},
|
|
717
|
-
})
|
|
718
|
-
.then(() => {
|
|
719
|
-
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
720
|
-
done();
|
|
721
|
-
});
|
|
722
|
-
});
|
|
723
|
-
|
|
724
|
-
it('updates the limited catalog when orgId is provided', (done) => {
|
|
725
|
-
catalog.serviceGroups.preauth = [];
|
|
726
|
-
|
|
727
|
-
services
|
|
728
|
-
.updateServices({
|
|
729
|
-
from: 'limited',
|
|
730
|
-
query: {orgId: webexUser.orgId},
|
|
731
|
-
})
|
|
732
|
-
.then(() => {
|
|
733
|
-
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
734
|
-
done();
|
|
735
|
-
});
|
|
736
|
-
});
|
|
737
|
-
it('updates the limited catalog when query param mode is provided', (done) => {
|
|
738
|
-
catalog.serviceGroups.preauth = [];
|
|
739
|
-
|
|
740
|
-
services
|
|
741
|
-
.updateServices({
|
|
742
|
-
from: 'limited',
|
|
743
|
-
query: {mode: 'DEFAULT_BY_PROXIMITY'},
|
|
744
|
-
})
|
|
745
|
-
.then(() => {
|
|
746
|
-
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
747
|
-
done();
|
|
748
|
-
});
|
|
749
|
-
});
|
|
750
|
-
it('does not update the limited catalog when nothing is provided', () => {
|
|
751
|
-
catalog.serviceGroups.preauth = [];
|
|
752
|
-
|
|
753
|
-
return services
|
|
754
|
-
.updateServices({from: 'limited'})
|
|
755
|
-
.then(() => {
|
|
756
|
-
assert(false, 'resolved, should have thrown');
|
|
757
|
-
})
|
|
758
|
-
.catch(() => {
|
|
759
|
-
assert(true);
|
|
760
|
-
});
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
it('updates limited catalog and calls _fetchNewServiceHostmap with forceRefresh = true', (done) => {
|
|
764
|
-
const forceRefresh = true;
|
|
765
|
-
const fetchNewServiceHostmapSpy = sinon.spy(services, '_fetchNewServiceHostmap');
|
|
766
|
-
|
|
767
|
-
services
|
|
768
|
-
.updateServices({
|
|
769
|
-
from: 'limited',
|
|
770
|
-
query: {email: webexUser.email},
|
|
771
|
-
forceRefresh,
|
|
772
|
-
})
|
|
773
|
-
.then(() => {
|
|
774
|
-
assert.calledOnce(fetchNewServiceHostmapSpy);
|
|
775
|
-
assert.calledWith(
|
|
776
|
-
fetchNewServiceHostmapSpy,
|
|
777
|
-
sinon.match.has(
|
|
778
|
-
'from',
|
|
779
|
-
'limited',
|
|
780
|
-
'query',
|
|
781
|
-
{emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)},
|
|
782
|
-
'forceFresh',
|
|
783
|
-
forceRefresh
|
|
784
|
-
)
|
|
785
|
-
);
|
|
786
|
-
|
|
787
|
-
fetchNewServiceHostmapSpy.returnValues[0].then((res) => {
|
|
788
|
-
assert.isAbove(res.length, 0);
|
|
789
|
-
});
|
|
790
|
-
done();
|
|
791
|
-
});
|
|
792
|
-
});
|
|
793
|
-
});
|
|
794
|
-
|
|
795
|
-
describe('#fetchClientRegionInfo()', () => {
|
|
796
|
-
it('returns client region info', () =>
|
|
797
|
-
services.fetchClientRegionInfo().then((r) => {
|
|
798
|
-
assert.isDefined(r.countryCode);
|
|
799
|
-
assert.isDefined(r.timezone);
|
|
800
|
-
}));
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
describe('#validateUser()', () => {
|
|
804
|
-
const unauthWebex = new WebexCore();
|
|
805
|
-
const unauthServices = unauthWebex.internal.services;
|
|
806
|
-
let sandbox = null;
|
|
807
|
-
|
|
808
|
-
const getActivationRequest = (requestStub) => {
|
|
809
|
-
const requests = requestStub.args.filter(
|
|
810
|
-
([request]) => request.service === 'license' && request.resource === 'users/activations'
|
|
811
|
-
);
|
|
812
|
-
|
|
813
|
-
assert.strictEqual(requests.length, 1);
|
|
814
|
-
|
|
815
|
-
return requests[0][0];
|
|
816
|
-
};
|
|
817
|
-
|
|
818
|
-
beforeEach(() => {
|
|
819
|
-
sandbox = sinon.createSandbox();
|
|
820
|
-
});
|
|
821
|
-
|
|
822
|
-
afterEach(() => {
|
|
823
|
-
sandbox.restore();
|
|
824
|
-
sandbox = null;
|
|
825
|
-
});
|
|
826
|
-
|
|
827
|
-
it('returns a rejected promise when no email is specified', () =>
|
|
828
|
-
unauthServices
|
|
829
|
-
.validateUser({})
|
|
830
|
-
.then(() => {
|
|
831
|
-
assert(false, 'resolved, should have thrown');
|
|
832
|
-
})
|
|
833
|
-
.catch(() => {
|
|
834
|
-
assert(true);
|
|
835
|
-
}));
|
|
836
|
-
|
|
837
|
-
it('validates an authorized user and webex instance', () =>
|
|
838
|
-
services.validateUser({email: webexUser.email}).then((r) => {
|
|
839
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
840
|
-
assert.equal(r.activated, true);
|
|
841
|
-
assert.equal(r.exists, true);
|
|
842
|
-
}));
|
|
843
|
-
|
|
844
|
-
it('validates an authorized EU user and webex instance', () =>
|
|
845
|
-
servicesEU.validateUser({email: webexUserEU.email}).then((r) => {
|
|
846
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
847
|
-
assert.equal(r.activated, true);
|
|
848
|
-
assert.equal(r.exists, true);
|
|
849
|
-
}));
|
|
850
|
-
|
|
851
|
-
it("returns a rejected promise if the provided email isn't valid", () =>
|
|
852
|
-
unauthServices
|
|
853
|
-
.validateUser({email: 'not an email'})
|
|
854
|
-
.then(() => {
|
|
855
|
-
assert(false, 'resolved, should have thrown');
|
|
856
|
-
})
|
|
857
|
-
.catch(() => {
|
|
858
|
-
assert(true);
|
|
859
|
-
}));
|
|
860
|
-
|
|
861
|
-
it('validates a non-existing user', () =>
|
|
862
|
-
unauthServices
|
|
863
|
-
.validateUser({email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`})
|
|
864
|
-
.then((r) => {
|
|
865
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
866
|
-
assert.equal(r.activated, false);
|
|
867
|
-
assert.equal(r.exists, false);
|
|
868
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
869
|
-
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
870
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
871
|
-
}));
|
|
872
|
-
|
|
873
|
-
it('validates new user with activationOptions suppressEmail false', () =>
|
|
874
|
-
unauthServices
|
|
875
|
-
.validateUser({
|
|
876
|
-
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
877
|
-
activationOptions: {suppressEmail: false},
|
|
878
|
-
})
|
|
879
|
-
.then((r) => {
|
|
880
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
881
|
-
assert.equal(r.activated, false);
|
|
882
|
-
assert.equal(r.exists, false);
|
|
883
|
-
assert.equal(r.user.verificationEmailTriggered, true);
|
|
884
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
885
|
-
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
886
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
887
|
-
}));
|
|
888
|
-
|
|
889
|
-
it('validates new user with activationOptions suppressEmail true', () =>
|
|
890
|
-
unauthServices
|
|
891
|
-
.validateUser({
|
|
892
|
-
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
893
|
-
activationOptions: {suppressEmail: true},
|
|
894
|
-
})
|
|
895
|
-
.then((r) => {
|
|
896
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
897
|
-
assert.equal(r.activated, false);
|
|
898
|
-
assert.equal(r.exists, false);
|
|
899
|
-
assert.equal(r.user.verificationEmailTriggered, false);
|
|
900
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
901
|
-
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
902
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
903
|
-
}));
|
|
904
|
-
|
|
905
|
-
it('validates an inactive user', () => {
|
|
906
|
-
const inactive = 'webex.web.client+nonactivated@gmail.com';
|
|
907
|
-
|
|
908
|
-
return unauthServices
|
|
909
|
-
.validateUser({email: inactive, activationOptions: {suppressEmail: true}})
|
|
910
|
-
.then((r) => {
|
|
911
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
912
|
-
assert.equal(r.activated, false, 'activated');
|
|
913
|
-
assert.equal(r.exists, true, 'exists');
|
|
914
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
915
|
-
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
916
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
917
|
-
})
|
|
918
|
-
.catch(() => {
|
|
919
|
-
assert(true);
|
|
920
|
-
});
|
|
921
|
-
});
|
|
922
|
-
|
|
923
|
-
it('validates an existing user', () =>
|
|
924
|
-
unauthServices.validateUser({email: webexUser.email}).then((r) => {
|
|
925
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
926
|
-
assert.equal(r.activated, true);
|
|
927
|
-
assert.equal(r.exists, true);
|
|
928
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
929
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
930
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
931
|
-
}));
|
|
932
|
-
|
|
933
|
-
it('validates an existing EU user', () =>
|
|
934
|
-
unauthServices.validateUser({email: webexUserEU.email}).then((r) => {
|
|
935
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
936
|
-
assert.equal(r.activated, true);
|
|
937
|
-
assert.equal(r.exists, true);
|
|
938
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
939
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
940
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
941
|
-
}));
|
|
942
|
-
|
|
943
|
-
it('sends the prelogin user id as undefined when not specified', () => {
|
|
944
|
-
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
945
|
-
|
|
946
|
-
return unauthServices
|
|
947
|
-
.validateUser({
|
|
948
|
-
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
949
|
-
activationOptions: {suppressEmail: true},
|
|
950
|
-
})
|
|
951
|
-
.then(() => {
|
|
952
|
-
assert.isUndefined(getActivationRequest(requestStub).headers['x-prelogin-userid']);
|
|
953
|
-
});
|
|
954
|
-
});
|
|
955
|
-
|
|
956
|
-
it('sends the prelogin user id as provided when specified', () => {
|
|
957
|
-
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
958
|
-
const preloginUserId = uuid.v4();
|
|
959
|
-
|
|
960
|
-
return unauthServices
|
|
961
|
-
.validateUser({
|
|
962
|
-
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
963
|
-
activationOptions: {suppressEmail: true},
|
|
964
|
-
preloginUserId,
|
|
965
|
-
})
|
|
966
|
-
.then(() => {
|
|
967
|
-
assert.strictEqual(
|
|
968
|
-
getActivationRequest(requestStub).headers['x-prelogin-userid'],
|
|
969
|
-
preloginUserId
|
|
970
|
-
);
|
|
971
|
-
});
|
|
972
|
-
});
|
|
973
|
-
});
|
|
974
|
-
|
|
975
|
-
describe('#waitForService()', () => {
|
|
976
|
-
let name;
|
|
977
|
-
let url;
|
|
978
|
-
|
|
979
|
-
describe('when the service exists', () => {
|
|
980
|
-
beforeEach('collect valid service info', () => {
|
|
981
|
-
name = Object.keys(services.list())[0];
|
|
982
|
-
url = services.list(true)[name];
|
|
983
|
-
});
|
|
984
|
-
|
|
985
|
-
describe('when using the name parameter property', () => {
|
|
986
|
-
it('should resolve to the appropriate url', () =>
|
|
987
|
-
services.waitForService({name}).then((foundUrl) => assert.equal(foundUrl, url)));
|
|
988
|
-
});
|
|
989
|
-
|
|
990
|
-
describe('when using the url parameter property', () => {
|
|
991
|
-
it('should resolve to the appropriate url', () =>
|
|
992
|
-
services.waitForService({url}).then((foundUrl) => assert.equal(foundUrl, url)));
|
|
993
|
-
});
|
|
994
|
-
|
|
995
|
-
describe('when using the url and name parameter properties', () => {
|
|
996
|
-
it('should resolve to the appropriate url', () =>
|
|
997
|
-
services.waitForService({name, url}).then((foundUrl) => assert.equal(foundUrl, url)));
|
|
998
|
-
});
|
|
999
|
-
});
|
|
1000
|
-
|
|
1001
|
-
describe('when the service does not exist', () => {
|
|
1002
|
-
let timeout;
|
|
1003
|
-
|
|
1004
|
-
beforeEach('set up the parameters', () => {
|
|
1005
|
-
name = 'not a service';
|
|
1006
|
-
url = 'http://not-a-service.com/resource';
|
|
1007
|
-
timeout = 1;
|
|
1008
|
-
});
|
|
1009
|
-
|
|
1010
|
-
describe('when using the url parameter property', () => {
|
|
1011
|
-
it('should return a resolve promise', () =>
|
|
1012
|
-
// const waitForService = services.waitForService({url, timeout});
|
|
1013
|
-
|
|
1014
|
-
services.waitForService({url, timeout}).then((foundUrl) => {
|
|
1015
|
-
assert.equal(foundUrl, url);
|
|
1016
|
-
assert.isTrue(catalog.isReady);
|
|
1017
|
-
}));
|
|
1018
|
-
});
|
|
1019
|
-
|
|
1020
|
-
describe('when using the name parameter property', () => {
|
|
1021
|
-
it('should return a rejected promise', () => {
|
|
1022
|
-
const submitMetrics = sinon.stub(webex.internal.metrics, 'submitClientMetrics');
|
|
1023
|
-
const waitForService = services.waitForService({name, timeout});
|
|
1024
|
-
|
|
1025
|
-
assert.called(submitMetrics);
|
|
1026
|
-
assert.isRejected(waitForService);
|
|
1027
|
-
assert.isTrue(catalog.isReady);
|
|
1028
|
-
});
|
|
1029
|
-
});
|
|
1030
|
-
|
|
1031
|
-
describe('when using the name and url parameter properties', () => {
|
|
1032
|
-
it('should return a rejected promise', () => {
|
|
1033
|
-
const waitForService = services.waitForService({
|
|
1034
|
-
name,
|
|
1035
|
-
url,
|
|
1036
|
-
timeout,
|
|
1037
|
-
});
|
|
1038
|
-
|
|
1039
|
-
assert.isRejected(waitForService);
|
|
1040
|
-
assert.isTrue(catalog.isReady);
|
|
1041
|
-
});
|
|
1042
|
-
});
|
|
1043
|
-
|
|
1044
|
-
describe('when the service will exist', () => {
|
|
1045
|
-
beforeEach('collect existing service and clear the catalog', () => {
|
|
1046
|
-
name = 'metrics';
|
|
1047
|
-
url = services.get(name, true);
|
|
1048
|
-
catalog.clean();
|
|
1049
|
-
catalog.isReady = false;
|
|
1050
|
-
});
|
|
1051
|
-
|
|
1052
|
-
describe('when only the preauth (limited) catalog becomes available', () => {
|
|
1053
|
-
describe('when using the name parameter property', () => {
|
|
1054
|
-
it('should resolve to the appropriate url', () =>
|
|
1055
|
-
Promise.all([
|
|
1056
|
-
services.waitForService({name}),
|
|
1057
|
-
services.collectPreauthCatalog(),
|
|
1058
|
-
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1059
|
-
});
|
|
1060
|
-
|
|
1061
|
-
describe('when using the url parameter property', () => {
|
|
1062
|
-
it('should resolve to the appropriate url', () =>
|
|
1063
|
-
Promise.all([
|
|
1064
|
-
services.waitForService({url}),
|
|
1065
|
-
services.collectPreauthCatalog(),
|
|
1066
|
-
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1067
|
-
});
|
|
1068
|
-
|
|
1069
|
-
describe('when using the name and url parameter property', () => {
|
|
1070
|
-
it('should resolve to the appropriate url', () =>
|
|
1071
|
-
Promise.all([
|
|
1072
|
-
services.waitForService({name, url}),
|
|
1073
|
-
services.collectPreauthCatalog(),
|
|
1074
|
-
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1075
|
-
});
|
|
1076
|
-
});
|
|
1077
|
-
|
|
1078
|
-
describe('when all catalogs become available', () => {
|
|
1079
|
-
describe('when using the name parameter property', () => {
|
|
1080
|
-
it('should resolve to the appropriate url', () =>
|
|
1081
|
-
Promise.all([services.waitForService({name}), services.initServiceCatalogs()]).then(
|
|
1082
|
-
([foundUrl]) => assert.equal(foundUrl, url)
|
|
1083
|
-
));
|
|
1084
|
-
});
|
|
1085
|
-
|
|
1086
|
-
describe('when using the url parameter property', () => {
|
|
1087
|
-
it('should resolve to the appropriate url', () =>
|
|
1088
|
-
Promise.all([services.waitForService({url}), services.initServiceCatalogs()]).then(
|
|
1089
|
-
([foundUrl]) => assert.equal(foundUrl, url)
|
|
1090
|
-
));
|
|
1091
|
-
});
|
|
1092
|
-
|
|
1093
|
-
describe('when using the name and url parameter property', () => {
|
|
1094
|
-
it('should resolve to the appropriate url', () =>
|
|
1095
|
-
Promise.all([
|
|
1096
|
-
services.waitForService({name, url}),
|
|
1097
|
-
services.initServiceCatalogs(),
|
|
1098
|
-
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1099
|
-
});
|
|
1100
|
-
});
|
|
1101
|
-
});
|
|
1102
|
-
});
|
|
1103
|
-
});
|
|
1104
|
-
|
|
1105
|
-
describe('#collectPreauthCatalog()', () => {
|
|
1106
|
-
const unauthWebex = new WebexCore({config: {credentials: {federation: true}}});
|
|
1107
|
-
const unauthServices = unauthWebex.internal.services;
|
|
1108
|
-
const forceRefresh = true;
|
|
1109
|
-
|
|
1110
|
-
it('updates the preauth catalog without email', () =>
|
|
1111
|
-
unauthServices.collectPreauthCatalog().then(() => {
|
|
1112
|
-
assert.isAbove(Object.keys(unauthServices.list()).length, 0);
|
|
1113
|
-
}));
|
|
1114
|
-
|
|
1115
|
-
it('updates the preauth catalog with email', () =>
|
|
1116
|
-
unauthServices.collectPreauthCatalog({email: webexUser.email}).then(() => {
|
|
1117
|
-
assert.isAbove(Object.keys(unauthServices.list()).length, 0);
|
|
1118
|
-
}));
|
|
1119
|
-
|
|
1120
|
-
it('updates the preauth catalog with email along with additional timestamp to address cache control', (done) => {
|
|
1121
|
-
const updateServiceSpy = sinon.spy(unauthServices, 'updateServices');
|
|
1122
|
-
const fetchNewServiceHostmapSpy = sinon.spy(unauthServices, '_fetchNewServiceHostmap');
|
|
1123
|
-
|
|
1124
|
-
unauthServices.collectPreauthCatalog({email: webexUser.email}, forceRefresh).then(() => {
|
|
1125
|
-
assert.calledOnce(updateServiceSpy);
|
|
1126
|
-
assert.calledWith(
|
|
1127
|
-
updateServiceSpy,
|
|
1128
|
-
sinon.match.has(
|
|
1129
|
-
'from',
|
|
1130
|
-
'limited',
|
|
1131
|
-
'query',
|
|
1132
|
-
{emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)},
|
|
1133
|
-
'forceRefresh',
|
|
1134
|
-
forceRefresh
|
|
1135
|
-
)
|
|
1136
|
-
);
|
|
1137
|
-
|
|
1138
|
-
assert.calledOnce(fetchNewServiceHostmapSpy);
|
|
1139
|
-
assert.calledWith(
|
|
1140
|
-
fetchNewServiceHostmapSpy,
|
|
1141
|
-
sinon.match.has(
|
|
1142
|
-
'from',
|
|
1143
|
-
'limited',
|
|
1144
|
-
'query',
|
|
1145
|
-
{emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)},
|
|
1146
|
-
'forceRefresh',
|
|
1147
|
-
forceRefresh
|
|
1148
|
-
)
|
|
1149
|
-
);
|
|
1150
|
-
|
|
1151
|
-
fetchNewServiceHostmapSpy.returnValues[0].then((res) => {
|
|
1152
|
-
assert.isAbove(res.length, 0);
|
|
1153
|
-
});
|
|
1154
|
-
done();
|
|
1155
|
-
});
|
|
1156
|
-
});
|
|
1157
|
-
});
|
|
1158
|
-
|
|
1159
|
-
describe('#collectSigninCatalog()', () => {
|
|
1160
|
-
const unauthWebex = new WebexCore({config: {credentials: {federation: true}}});
|
|
1161
|
-
const unauthServices = unauthWebex.internal.services;
|
|
1162
|
-
|
|
1163
|
-
it('requires an email as the parameter', () =>
|
|
1164
|
-
unauthServices.collectPreauthCatalog().catch((e) => {
|
|
1165
|
-
assert(true, e);
|
|
1166
|
-
}));
|
|
1167
|
-
|
|
1168
|
-
it('requires a token as the parameter', () =>
|
|
1169
|
-
unauthServices.collectPreauthCatalog({email: 'email@website.com'}).catch((e) => {
|
|
1170
|
-
assert(true, e);
|
|
1171
|
-
}));
|
|
1172
|
-
|
|
1173
|
-
it('updates the preauth catalog', () =>
|
|
1174
|
-
unauthServices.collectPreauthCatalog({email: webexUser.email}).then(() => {
|
|
1175
|
-
assert.isAbove(Object.keys(unauthServices.list()).length, 0);
|
|
1176
|
-
}));
|
|
1177
|
-
});
|
|
1178
|
-
|
|
1179
|
-
flaky(describe, process.env.SKIP_FLAKY_TESTS)('#_fetchNewServiceHostmap()', () => {
|
|
1180
|
-
let fullRemoteHM;
|
|
1181
|
-
let limitedRemoteHM;
|
|
1182
|
-
|
|
1183
|
-
before('collect remote catalogs', () =>
|
|
1184
|
-
Promise.all([
|
|
1185
|
-
services._fetchNewServiceHostmap(),
|
|
1186
|
-
services._fetchNewServiceHostmap({
|
|
1187
|
-
from: 'limited',
|
|
1188
|
-
query: {userId: webexUser.id},
|
|
1189
|
-
}),
|
|
1190
|
-
]).then(([fRHM, lRHM]) => {
|
|
1191
|
-
fullRemoteHM = fRHM;
|
|
1192
|
-
limitedRemoteHM = lRHM;
|
|
1193
|
-
})
|
|
1194
|
-
);
|
|
1195
|
-
|
|
1196
|
-
it('resolves to an authed u2c hostmap when no params specified', () => {
|
|
1197
|
-
assert.typeOf(fullRemoteHM, 'array');
|
|
1198
|
-
assert.isAbove(fullRemoteHM.length, 0);
|
|
1199
|
-
});
|
|
1200
|
-
|
|
1201
|
-
it('resolves to a limited u2c hostmap when params specified', () => {
|
|
1202
|
-
assert.typeOf(limitedRemoteHM, 'array');
|
|
1203
|
-
assert.isAbove(limitedRemoteHM.length, 0);
|
|
1204
|
-
});
|
|
1205
|
-
|
|
1206
|
-
it('rejects if the params provided are invalid', () =>
|
|
1207
|
-
services
|
|
1208
|
-
._fetchNewServiceHostmap({
|
|
1209
|
-
from: 'limited',
|
|
1210
|
-
query: {userId: 'notValid'},
|
|
1211
|
-
})
|
|
1212
|
-
.then(() => {
|
|
1213
|
-
assert.isTrue(false, 'should have rejected');
|
|
1214
|
-
})
|
|
1215
|
-
.catch((e) => {
|
|
1216
|
-
assert.typeOf(e, 'Error');
|
|
1217
|
-
}));
|
|
1218
|
-
});
|
|
1219
|
-
});
|
|
1220
|
-
});
|
|
1221
|
-
/* eslint-enable no-underscore-dangle */
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import '@webex/internal-plugin-device';
|
|
6
|
+
|
|
7
|
+
import {assert} from '@webex/test-helper-chai';
|
|
8
|
+
import {flaky} from '@webex/test-helper-mocha';
|
|
9
|
+
import WebexCore, {
|
|
10
|
+
ServiceCatalog,
|
|
11
|
+
ServiceRegistry,
|
|
12
|
+
ServiceState,
|
|
13
|
+
ServiceUrl,
|
|
14
|
+
} from '@webex/webex-core';
|
|
15
|
+
import testUsers from '@webex/test-helper-test-users';
|
|
16
|
+
import uuid from 'uuid';
|
|
17
|
+
import sinon from 'sinon';
|
|
18
|
+
|
|
19
|
+
/* eslint-disable no-underscore-dangle */
|
|
20
|
+
describe('webex-core', () => {
|
|
21
|
+
describe('Services', () => {
|
|
22
|
+
let webexUser;
|
|
23
|
+
let webexUserEU;
|
|
24
|
+
let webex;
|
|
25
|
+
let webexEU;
|
|
26
|
+
let services;
|
|
27
|
+
let servicesEU;
|
|
28
|
+
let catalog;
|
|
29
|
+
|
|
30
|
+
before('create users', () =>
|
|
31
|
+
Promise.all([
|
|
32
|
+
testUsers.create({count: 1}),
|
|
33
|
+
testUsers.create({
|
|
34
|
+
count: 1,
|
|
35
|
+
config: {
|
|
36
|
+
orgId: process.env.EU_PRIMARY_ORG_ID,
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
]).then(([[user], [userEU]]) => {
|
|
40
|
+
webexUser = user;
|
|
41
|
+
webexUserEU = userEU;
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
beforeEach('create webex instance', () => {
|
|
46
|
+
webex = new WebexCore({credentials: {supertoken: webexUser.token}});
|
|
47
|
+
webexEU = new WebexCore({credentials: {supertoken: webexUserEU.token}});
|
|
48
|
+
services = webex.internal.services;
|
|
49
|
+
servicesEU = webexEU.internal.services;
|
|
50
|
+
catalog = services._getCatalog();
|
|
51
|
+
|
|
52
|
+
return Promise.all([
|
|
53
|
+
services.waitForCatalog('postauth', 10),
|
|
54
|
+
servicesEU.waitForCatalog('postauth', 10),
|
|
55
|
+
]).then(() =>
|
|
56
|
+
services.updateServices({
|
|
57
|
+
from: 'limited',
|
|
58
|
+
query: {userId: webexUser.id},
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('#_getCatalog()', () => {
|
|
64
|
+
it('returns a catalog', () => {
|
|
65
|
+
const localCatalog = services._getCatalog();
|
|
66
|
+
|
|
67
|
+
assert.equal(localCatalog.namespace, 'ServiceCatalog');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('#list()', () => {
|
|
72
|
+
it('matches the values in serviceUrl', () => {
|
|
73
|
+
let serviceList = services.list();
|
|
74
|
+
|
|
75
|
+
Object.keys(serviceList).forEach((key) => {
|
|
76
|
+
assert.equal(serviceList[key], catalog._getUrl(key).get());
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
serviceList = services.list(true);
|
|
80
|
+
Object.keys(serviceList).forEach((key) => {
|
|
81
|
+
assert.equal(serviceList[key], catalog._getUrl(key).get(true));
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('#get()', () => {
|
|
87
|
+
let testUrlTemplate;
|
|
88
|
+
let testUrl;
|
|
89
|
+
|
|
90
|
+
beforeEach('load test url', () => {
|
|
91
|
+
testUrlTemplate = {
|
|
92
|
+
defaultUrl: 'https://www.example.com/api/v1',
|
|
93
|
+
hosts: [],
|
|
94
|
+
name: 'exampleValid',
|
|
95
|
+
};
|
|
96
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
97
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
afterEach('unload test url', () => {
|
|
101
|
+
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('returns a valid string when name is specified', () => {
|
|
105
|
+
const url = services.get(testUrlTemplate.name);
|
|
106
|
+
|
|
107
|
+
assert.typeOf(url, 'string');
|
|
108
|
+
assert.equal(url, testUrlTemplate.defaultUrl);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("returns undefined if url doesn't exist", () => {
|
|
112
|
+
const s = services.get('invalidUrl');
|
|
113
|
+
|
|
114
|
+
assert.typeOf(s, 'undefined');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('gets a service from a specific serviceGroup', () => {
|
|
118
|
+
assert.isDefined(services.get(testUrlTemplate.name, false, 'preauth'));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("fails to get a service if serviceGroup isn't accurate", () => {
|
|
122
|
+
assert.isUndefined(services.get(testUrlTemplate.name, false, 'discovery'));
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('#getClusterId()', () => {
|
|
127
|
+
let testUrlTemplate;
|
|
128
|
+
let testUrl;
|
|
129
|
+
|
|
130
|
+
beforeEach('load test url', () => {
|
|
131
|
+
testUrlTemplate = {
|
|
132
|
+
defaultUrl: 'https://www.example.com/api/v1',
|
|
133
|
+
hosts: [
|
|
134
|
+
{
|
|
135
|
+
homeCluster: true,
|
|
136
|
+
host: 'www.example-p5.com',
|
|
137
|
+
ttl: -1,
|
|
138
|
+
priority: 5,
|
|
139
|
+
id: 'exampleClusterId',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
host: 'www.example-p3.com',
|
|
143
|
+
ttl: -1,
|
|
144
|
+
priority: 3,
|
|
145
|
+
id: 'exampleClusterId',
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
name: 'exampleValid',
|
|
149
|
+
};
|
|
150
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
151
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('returns a clusterId when found with default url', () => {
|
|
155
|
+
assert.equal(
|
|
156
|
+
services.getClusterId(testUrlTemplate.defaultUrl),
|
|
157
|
+
testUrlTemplate.hosts[0].id
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('returns a clusterId when found with priority host url', () => {
|
|
162
|
+
assert.equal(services.getClusterId(testUrl.get(true)), testUrlTemplate.hosts[0].id);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('returns a clusterId when found with resource-appended url', () => {
|
|
166
|
+
assert.equal(
|
|
167
|
+
services.getClusterId(`${testUrl.get()}example/resource/value`),
|
|
168
|
+
testUrlTemplate.hosts[0].id
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("returns undefined when the url doesn't exist in catalog", () => {
|
|
173
|
+
assert.isUndefined(services.getClusterId('http://not-a-known-url.com/'));
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("returns undefined when the string isn't a url", () => {
|
|
177
|
+
assert.isUndefined(services.getClusterId('not a url'));
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('#getServiceFromClusterId()', () => {
|
|
182
|
+
let testUrlTemplate;
|
|
183
|
+
let testUrl;
|
|
184
|
+
|
|
185
|
+
beforeEach('load test url', () => {
|
|
186
|
+
testUrlTemplate = {
|
|
187
|
+
defaultUrl: 'https://www.example.com/api/v1',
|
|
188
|
+
hosts: [
|
|
189
|
+
{
|
|
190
|
+
homeCluster: true,
|
|
191
|
+
host: 'www.example-p5.com',
|
|
192
|
+
ttl: -1,
|
|
193
|
+
priority: 5,
|
|
194
|
+
id: '0:0:cluster-a:exampleValid',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
host: 'www.example-p3.com',
|
|
198
|
+
ttl: -1,
|
|
199
|
+
priority: 3,
|
|
200
|
+
id: '0:0:cluster-b:exampleValid',
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
name: 'exampleValid',
|
|
204
|
+
};
|
|
205
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
206
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('finds a valid service url from only a clusterId', () => {
|
|
210
|
+
const serviceFound = services.getServiceFromClusterId({
|
|
211
|
+
clusterId: testUrlTemplate.hosts[0].id,
|
|
212
|
+
priorityHost: false,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
assert.equal(serviceFound.name, testUrl.name);
|
|
216
|
+
assert.equal(serviceFound.url, testUrl.defaultUrl);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('finds a valid priority service url', () => {
|
|
220
|
+
const serviceFound = services.getServiceFromClusterId({
|
|
221
|
+
clusterId: testUrlTemplate.hosts[0].id,
|
|
222
|
+
priorityHost: true,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
assert.equal(serviceFound.name, testUrl.name);
|
|
226
|
+
assert.isTrue(
|
|
227
|
+
serviceFound.url.includes(testUrlTemplate.hosts[0].host),
|
|
228
|
+
`'${serviceFound.url}' is not host '${testUrlTemplate.hosts[0].host}'`
|
|
229
|
+
);
|
|
230
|
+
// assert.equal(serviceFound.url, catalog.get('exampleValid', true));
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('finds a valid service when a service group is defined', () => {
|
|
234
|
+
const serviceFound = catalog.findServiceFromClusterId({
|
|
235
|
+
clusterId: testUrlTemplate.hosts[0].id,
|
|
236
|
+
priorityHost: false,
|
|
237
|
+
serviceGroup: 'preauth',
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
assert.equal(serviceFound.name, testUrl.name);
|
|
241
|
+
assert.equal(serviceFound.url, testUrl.defaultUrl);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it("fails to find a valid service when it's not in a group", () => {
|
|
245
|
+
assert.isUndefined(
|
|
246
|
+
services.getServiceFromClusterId({
|
|
247
|
+
clusterId: testUrlTemplate.hosts[0].id,
|
|
248
|
+
serviceGroup: 'signin',
|
|
249
|
+
})
|
|
250
|
+
);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("returns undefined when service doesn't exist", () => {
|
|
254
|
+
assert.isUndefined(services.getServiceFromClusterId({clusterId: 'not a clusterId'}));
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe('#getServiceFromUrl()', () => {
|
|
259
|
+
let testUrlTemplate;
|
|
260
|
+
let testUrl;
|
|
261
|
+
|
|
262
|
+
beforeEach('load test url', () => {
|
|
263
|
+
testUrlTemplate = {
|
|
264
|
+
defaultUrl: 'https://www.example.com/api/v1',
|
|
265
|
+
hosts: [
|
|
266
|
+
{
|
|
267
|
+
host: 'www.example-p5.com',
|
|
268
|
+
ttl: -1,
|
|
269
|
+
priority: 5,
|
|
270
|
+
id: 'exampleClusterId',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
host: 'www.example-p3.com',
|
|
274
|
+
ttl: -1,
|
|
275
|
+
priority: 3,
|
|
276
|
+
id: 'exampleClusterId',
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
name: 'exampleValid',
|
|
280
|
+
};
|
|
281
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
282
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
afterEach('unload test url', () => {
|
|
286
|
+
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('gets a valid service object from an existing service', () => {
|
|
290
|
+
const serviceObject = services.getServiceFromUrl(testUrlTemplate.defaultUrl);
|
|
291
|
+
|
|
292
|
+
assert.isDefined(serviceObject);
|
|
293
|
+
assert.hasAllKeys(serviceObject, ['name', 'defaultUrl', 'priorityUrl']);
|
|
294
|
+
|
|
295
|
+
assert.equal(testUrlTemplate.name, serviceObject.name);
|
|
296
|
+
assert.equal(testUrlTemplate.defaultUrl, serviceObject.defaultUrl);
|
|
297
|
+
assert.equal(testUrl.get(true), serviceObject.priorityUrl);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("returns undefined when the service url doesn't exist", () => {
|
|
301
|
+
const serviceObject = services.getServiceFromUrl('http://www.not-real.com/');
|
|
302
|
+
|
|
303
|
+
assert.isUndefined(serviceObject);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
describe('#hasService()', () => {
|
|
308
|
+
it('returns a boolean', () => {
|
|
309
|
+
assert.isBoolean(services.hasService('some-url'));
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('validates that a service exists', () => {
|
|
313
|
+
const service = Object.keys(services.list())[0];
|
|
314
|
+
|
|
315
|
+
assert.isTrue(services.hasService(service));
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe('#initConfig()', () => {
|
|
320
|
+
it('should set the discovery catalog based on the provided links', () => {
|
|
321
|
+
const key = 'test';
|
|
322
|
+
const url = 'http://www.test.com/';
|
|
323
|
+
|
|
324
|
+
webex.config.services.discovery[key] = url;
|
|
325
|
+
|
|
326
|
+
services.initConfig();
|
|
327
|
+
|
|
328
|
+
assert.equal(services.get(key), url);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('should set the override catalog based on the provided links', () => {
|
|
332
|
+
const key = 'testOverride';
|
|
333
|
+
const url = 'http://www.test-override.com/';
|
|
334
|
+
|
|
335
|
+
webex.config.services.override = {};
|
|
336
|
+
webex.config.services.override[key] = url;
|
|
337
|
+
|
|
338
|
+
services.initConfig();
|
|
339
|
+
|
|
340
|
+
assert.equal(services.get(key), url);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('should set validate domains to true when provided true', () => {
|
|
344
|
+
webex.config.services.validateDomains = true;
|
|
345
|
+
|
|
346
|
+
services.initConfig();
|
|
347
|
+
|
|
348
|
+
assert.isTrue(services.validateDomains);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('should set validate domains to false when provided false', () => {
|
|
352
|
+
webex.config.services.validateDomains = false;
|
|
353
|
+
|
|
354
|
+
services.initConfig();
|
|
355
|
+
|
|
356
|
+
assert.isFalse(services.validateDomains);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should set the allowed domains based on the provided domains', () => {
|
|
360
|
+
const allowedDomains = ['domain'];
|
|
361
|
+
|
|
362
|
+
webex.config.services.allowedDomains = allowedDomains;
|
|
363
|
+
|
|
364
|
+
services.initConfig();
|
|
365
|
+
|
|
366
|
+
assert.deepEqual(allowedDomains, services._getCatalog().allowedDomains);
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
describe('#initialize()', () => {
|
|
371
|
+
it('should create a catalog', () =>
|
|
372
|
+
assert.instanceOf(services._getCatalog(), ServiceCatalog));
|
|
373
|
+
|
|
374
|
+
it('should create a registry', () =>
|
|
375
|
+
assert.instanceOf(services.getRegistry(), ServiceRegistry));
|
|
376
|
+
|
|
377
|
+
it('should create a state', () => assert.instanceOf(services.getState(), ServiceState));
|
|
378
|
+
|
|
379
|
+
it('should call services#initConfig() when webex config changes', () => {
|
|
380
|
+
services.initConfig = sinon.spy();
|
|
381
|
+
services.initialize();
|
|
382
|
+
webex.trigger('change:config');
|
|
383
|
+
assert.called(services.initConfig);
|
|
384
|
+
assert.isTrue(catalog.isReady);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('should call services#initServiceCatalogs() on webex ready', () => {
|
|
388
|
+
services.initServiceCatalogs = sinon.stub().resolves();
|
|
389
|
+
services.initialize();
|
|
390
|
+
webex.trigger('ready');
|
|
391
|
+
assert.called(services.initServiceCatalogs);
|
|
392
|
+
assert.isTrue(catalog.isReady);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('should collect different catalogs based on OrgId region', () =>
|
|
396
|
+
assert.notDeepEqual(services.list(true), servicesEU.list(true)));
|
|
397
|
+
|
|
398
|
+
it('should not attempt to collect catalogs without authorization', (done) => {
|
|
399
|
+
const otherWebex = new WebexCore();
|
|
400
|
+
let {initServiceCatalogs} = otherWebex.internal.services;
|
|
401
|
+
|
|
402
|
+
initServiceCatalogs = sinon.stub();
|
|
403
|
+
|
|
404
|
+
setTimeout(() => {
|
|
405
|
+
assert.notCalled(initServiceCatalogs);
|
|
406
|
+
assert.isFalse(otherWebex.internal.services._getCatalog().isReady);
|
|
407
|
+
done();
|
|
408
|
+
}, 2000);
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
describe('#initServiceCatalogs()', () => {
|
|
413
|
+
it('should reject if a OrgId cannot be retrieved', () => {
|
|
414
|
+
webex.credentials.getOrgId = sinon.stub().throws();
|
|
415
|
+
|
|
416
|
+
return assert.isRejected(services.initServiceCatalogs());
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('should call services#collectPreauthCatalog with the OrgId', () => {
|
|
420
|
+
services.collectPreauthCatalog = sinon.stub().resolves();
|
|
421
|
+
|
|
422
|
+
return services.initServiceCatalogs().then(() =>
|
|
423
|
+
assert.calledWith(
|
|
424
|
+
services.collectPreauthCatalog,
|
|
425
|
+
sinon.match({
|
|
426
|
+
orgId: webex.credentials.getOrgId(),
|
|
427
|
+
})
|
|
428
|
+
)
|
|
429
|
+
);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
it('should not call services#updateServices() when not authed', () => {
|
|
433
|
+
services.updateServices = sinon.stub().resolves();
|
|
434
|
+
|
|
435
|
+
// Since credentials uses AmpState, we have to set the derived
|
|
436
|
+
// properties of the dependent properties to undefined.
|
|
437
|
+
webex.credentials.supertoken.access_token = undefined;
|
|
438
|
+
webex.credentials.supertoken.refresh_token = undefined;
|
|
439
|
+
|
|
440
|
+
webex.credentials.getOrgId = sinon.stub().returns(webexUser.orgId);
|
|
441
|
+
|
|
442
|
+
return (
|
|
443
|
+
services
|
|
444
|
+
.initServiceCatalogs()
|
|
445
|
+
// services#updateServices() gets called once by the limited catalog
|
|
446
|
+
// retrieval and should not be called again when not authorized.
|
|
447
|
+
.then(() => assert.calledOnce(services.updateServices))
|
|
448
|
+
);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should call services#updateServices() when authed', () => {
|
|
452
|
+
services.updateServices = sinon.stub().resolves();
|
|
453
|
+
|
|
454
|
+
return (
|
|
455
|
+
services
|
|
456
|
+
.initServiceCatalogs()
|
|
457
|
+
// services#updateServices() gets called once by the limited catalog
|
|
458
|
+
// retrieval and should get called again when authorized.
|
|
459
|
+
.then(() => assert.calledTwice(services.updateServices))
|
|
460
|
+
);
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
describe('#isServiceUrl()', () => {
|
|
465
|
+
let testUrlTemplate;
|
|
466
|
+
let testUrl;
|
|
467
|
+
|
|
468
|
+
beforeEach('load test url', () => {
|
|
469
|
+
testUrlTemplate = {
|
|
470
|
+
defaultUrl: 'https://www.example.com/api/v1',
|
|
471
|
+
hosts: [
|
|
472
|
+
{
|
|
473
|
+
homeCluster: true,
|
|
474
|
+
host: 'www.example-p5.com',
|
|
475
|
+
ttl: -1,
|
|
476
|
+
priority: 5,
|
|
477
|
+
id: 'exampleClusterId',
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
host: 'www.example-p3.com',
|
|
481
|
+
ttl: -1,
|
|
482
|
+
priority: 3,
|
|
483
|
+
id: 'exampleClusterId',
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
name: 'exampleValid',
|
|
487
|
+
};
|
|
488
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
489
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it('returns true if url is a service url', () => {
|
|
493
|
+
assert.isTrue(services.isServiceUrl(testUrlTemplate.defaultUrl));
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
it('returns true for priority host urls', () => {
|
|
497
|
+
assert.isTrue(services.isServiceUrl(testUrl.get(true)));
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it("returns undefined if the url doesn't exist", () => {
|
|
501
|
+
assert.isFalse(services.isServiceUrl('https://na.com/'));
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('returns undefined if the param is not a url', () => {
|
|
505
|
+
assert.isFalse(services.isServiceUrl('not a url'));
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
describe('#isAllowedDomainUrl()', () => {
|
|
510
|
+
let list;
|
|
511
|
+
|
|
512
|
+
beforeEach(() => {
|
|
513
|
+
catalog.setAllowedDomains(['some-domain-a', 'some-domain-b']);
|
|
514
|
+
|
|
515
|
+
list = catalog.getAllowedDomains();
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it('returns a boolean', () => {
|
|
519
|
+
assert.isBoolean(services.isAllowedDomainUrl(''));
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
it('returns true if the url contains an allowed domain', () => {
|
|
523
|
+
assert.isTrue(services.isAllowedDomainUrl(`https://${list[0]}/resource`));
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
it('returns false if the url does not contain an allowed domain', () => {
|
|
527
|
+
assert.isFalse(services.isAllowedDomainUrl('https://bad-domain/resource'));
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
describe('#convertUrlToPriorityUrl', () => {
|
|
532
|
+
let testUrl;
|
|
533
|
+
let testUrlTemplate;
|
|
534
|
+
|
|
535
|
+
beforeEach('load test url', () => {
|
|
536
|
+
testUrlTemplate = {
|
|
537
|
+
defaultUrl: 'https://www.example.com/api/v1',
|
|
538
|
+
hosts: [
|
|
539
|
+
{
|
|
540
|
+
homeCluster: true,
|
|
541
|
+
host: 'www.example-p5.com',
|
|
542
|
+
ttl: -1,
|
|
543
|
+
priority: 5,
|
|
544
|
+
id: '0:0:cluster-a:exampleValid',
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
host: 'www.example-p3.com',
|
|
548
|
+
ttl: -1,
|
|
549
|
+
priority: 3,
|
|
550
|
+
id: '0:0:cluster-b:exampleValid',
|
|
551
|
+
},
|
|
552
|
+
],
|
|
553
|
+
name: 'exampleValid',
|
|
554
|
+
};
|
|
555
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
556
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('converts the url to a priority host url', () => {
|
|
560
|
+
const resource = 'path/to/resource';
|
|
561
|
+
const url = `${testUrlTemplate.defaultUrl}/${resource}`;
|
|
562
|
+
|
|
563
|
+
const convertUrl = services.convertUrlToPriorityHostUrl(url);
|
|
564
|
+
|
|
565
|
+
assert.isDefined(convertUrl);
|
|
566
|
+
assert.isTrue(convertUrl.includes(testUrlTemplate.hosts[0].host));
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('throws an exception if not a valid service', () => {
|
|
570
|
+
assert.throws(services.convertUrlToPriorityHostUrl, Error);
|
|
571
|
+
|
|
572
|
+
assert.throws(
|
|
573
|
+
services.convertUrlToPriorityHostUrl.bind(services, 'not-a-valid-service'),
|
|
574
|
+
Error
|
|
575
|
+
);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
afterEach('unload test url', () => {
|
|
579
|
+
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
describe('#markFailedUrl()', () => {
|
|
584
|
+
let testUrlTemplate;
|
|
585
|
+
let testUrl;
|
|
586
|
+
|
|
587
|
+
beforeEach('load test url', () => {
|
|
588
|
+
catalog.clean();
|
|
589
|
+
|
|
590
|
+
testUrlTemplate = {
|
|
591
|
+
defaultUrl: 'https://www.example-phr.com/api/v1',
|
|
592
|
+
hosts: [
|
|
593
|
+
{
|
|
594
|
+
host: 'www.example-phr-p5.com',
|
|
595
|
+
ttl: -1,
|
|
596
|
+
priority: 5,
|
|
597
|
+
homeCluster: true,
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
host: 'www.example-phr-p3.com',
|
|
601
|
+
ttl: -1,
|
|
602
|
+
priority: 3,
|
|
603
|
+
homeCluster: true,
|
|
604
|
+
},
|
|
605
|
+
],
|
|
606
|
+
name: 'exampleValid-phr',
|
|
607
|
+
};
|
|
608
|
+
testUrl = new ServiceUrl(testUrlTemplate);
|
|
609
|
+
catalog._loadServiceUrls('preauth', [testUrl]);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
afterEach('unload test url', () => {
|
|
613
|
+
catalog._unloadServiceUrls('preauth', [testUrl]);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it('marks a host as failed', () => {
|
|
617
|
+
const priorityServiceUrl = catalog._getUrl(testUrlTemplate.name);
|
|
618
|
+
const priorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
619
|
+
|
|
620
|
+
services.markFailedUrl(priorityUrl);
|
|
621
|
+
|
|
622
|
+
const failedHost = priorityServiceUrl.hosts.find((host) => host.failed);
|
|
623
|
+
|
|
624
|
+
assert.isTrue(priorityUrl.includes(failedHost.host));
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
it('returns the next priority url', () => {
|
|
628
|
+
const priorityUrl = services.get(testUrlTemplate.name, true);
|
|
629
|
+
|
|
630
|
+
const nextPriorityUrl = services.markFailedUrl(priorityUrl);
|
|
631
|
+
|
|
632
|
+
assert.notEqual(priorityUrl, nextPriorityUrl);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it('should reset hosts once all hosts have been marked failed', () => {
|
|
636
|
+
const priorityServiceUrl = catalog._getUrl(testUrlTemplate.name);
|
|
637
|
+
const firstPriorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
638
|
+
|
|
639
|
+
priorityServiceUrl.hosts.forEach(() => {
|
|
640
|
+
const priorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
641
|
+
|
|
642
|
+
services.markFailedUrl(priorityUrl);
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
const lastPriorityUrl = priorityServiceUrl._getPriorityHostUrl();
|
|
646
|
+
|
|
647
|
+
assert.equal(firstPriorityUrl, lastPriorityUrl);
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
describe('#updateServices()', () => {
|
|
652
|
+
it('returns a Promise that and resolves on success', (done) => {
|
|
653
|
+
const servicesPromise = services.updateServices();
|
|
654
|
+
|
|
655
|
+
assert.typeOf(servicesPromise, 'Promise');
|
|
656
|
+
|
|
657
|
+
servicesPromise.then(() => {
|
|
658
|
+
Object.keys(services.list()).forEach((key) => {
|
|
659
|
+
assert.typeOf(key, 'string');
|
|
660
|
+
assert.typeOf(services.list()[key], 'string');
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
done();
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
it('updates the services list', (done) => {
|
|
668
|
+
catalog.serviceGroups.postauth = [];
|
|
669
|
+
|
|
670
|
+
services.updateServices().then(() => {
|
|
671
|
+
assert.isAbove(catalog.serviceGroups.postauth.length, 0);
|
|
672
|
+
done();
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
services.updateServices();
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
it('updates query.email to be emailhash-ed using SHA256', (done) => {
|
|
679
|
+
catalog.updateServiceUrls = sinon.stub().returns({}); // returns `this`
|
|
680
|
+
services._fetchNewServiceHostmap = sinon.stub().resolves();
|
|
681
|
+
|
|
682
|
+
services
|
|
683
|
+
.updateServices({
|
|
684
|
+
from: 'limited',
|
|
685
|
+
query: {email: webexUser.email},
|
|
686
|
+
})
|
|
687
|
+
.then(() => {
|
|
688
|
+
assert.calledWith(
|
|
689
|
+
services._fetchNewServiceHostmap,
|
|
690
|
+
sinon.match.has('query', {emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)})
|
|
691
|
+
);
|
|
692
|
+
done();
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
it('updates the limited catalog when email is provided', (done) => {
|
|
697
|
+
catalog.serviceGroups.preauth = [];
|
|
698
|
+
|
|
699
|
+
services
|
|
700
|
+
.updateServices({
|
|
701
|
+
from: 'limited',
|
|
702
|
+
query: {email: webexUser.email},
|
|
703
|
+
})
|
|
704
|
+
.then(() => {
|
|
705
|
+
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
706
|
+
done();
|
|
707
|
+
});
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
it('updates the limited catalog when userId is provided', (done) => {
|
|
711
|
+
catalog.serviceGroups.preauth = [];
|
|
712
|
+
|
|
713
|
+
services
|
|
714
|
+
.updateServices({
|
|
715
|
+
from: 'limited',
|
|
716
|
+
query: {userId: webexUser.id},
|
|
717
|
+
})
|
|
718
|
+
.then(() => {
|
|
719
|
+
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
720
|
+
done();
|
|
721
|
+
});
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('updates the limited catalog when orgId is provided', (done) => {
|
|
725
|
+
catalog.serviceGroups.preauth = [];
|
|
726
|
+
|
|
727
|
+
services
|
|
728
|
+
.updateServices({
|
|
729
|
+
from: 'limited',
|
|
730
|
+
query: {orgId: webexUser.orgId},
|
|
731
|
+
})
|
|
732
|
+
.then(() => {
|
|
733
|
+
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
734
|
+
done();
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
it('updates the limited catalog when query param mode is provided', (done) => {
|
|
738
|
+
catalog.serviceGroups.preauth = [];
|
|
739
|
+
|
|
740
|
+
services
|
|
741
|
+
.updateServices({
|
|
742
|
+
from: 'limited',
|
|
743
|
+
query: {mode: 'DEFAULT_BY_PROXIMITY'},
|
|
744
|
+
})
|
|
745
|
+
.then(() => {
|
|
746
|
+
assert.isAbove(catalog.serviceGroups.preauth.length, 0);
|
|
747
|
+
done();
|
|
748
|
+
});
|
|
749
|
+
});
|
|
750
|
+
it('does not update the limited catalog when nothing is provided', () => {
|
|
751
|
+
catalog.serviceGroups.preauth = [];
|
|
752
|
+
|
|
753
|
+
return services
|
|
754
|
+
.updateServices({from: 'limited'})
|
|
755
|
+
.then(() => {
|
|
756
|
+
assert(false, 'resolved, should have thrown');
|
|
757
|
+
})
|
|
758
|
+
.catch(() => {
|
|
759
|
+
assert(true);
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
it('updates limited catalog and calls _fetchNewServiceHostmap with forceRefresh = true', (done) => {
|
|
764
|
+
const forceRefresh = true;
|
|
765
|
+
const fetchNewServiceHostmapSpy = sinon.spy(services, '_fetchNewServiceHostmap');
|
|
766
|
+
|
|
767
|
+
services
|
|
768
|
+
.updateServices({
|
|
769
|
+
from: 'limited',
|
|
770
|
+
query: {email: webexUser.email},
|
|
771
|
+
forceRefresh,
|
|
772
|
+
})
|
|
773
|
+
.then(() => {
|
|
774
|
+
assert.calledOnce(fetchNewServiceHostmapSpy);
|
|
775
|
+
assert.calledWith(
|
|
776
|
+
fetchNewServiceHostmapSpy,
|
|
777
|
+
sinon.match.has(
|
|
778
|
+
'from',
|
|
779
|
+
'limited',
|
|
780
|
+
'query',
|
|
781
|
+
{emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)},
|
|
782
|
+
'forceFresh',
|
|
783
|
+
forceRefresh
|
|
784
|
+
)
|
|
785
|
+
);
|
|
786
|
+
|
|
787
|
+
fetchNewServiceHostmapSpy.returnValues[0].then((res) => {
|
|
788
|
+
assert.isAbove(res.length, 0);
|
|
789
|
+
});
|
|
790
|
+
done();
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
describe('#fetchClientRegionInfo()', () => {
|
|
796
|
+
it('returns client region info', () =>
|
|
797
|
+
services.fetchClientRegionInfo().then((r) => {
|
|
798
|
+
assert.isDefined(r.countryCode);
|
|
799
|
+
assert.isDefined(r.timezone);
|
|
800
|
+
}));
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
describe('#validateUser()', () => {
|
|
804
|
+
const unauthWebex = new WebexCore();
|
|
805
|
+
const unauthServices = unauthWebex.internal.services;
|
|
806
|
+
let sandbox = null;
|
|
807
|
+
|
|
808
|
+
const getActivationRequest = (requestStub) => {
|
|
809
|
+
const requests = requestStub.args.filter(
|
|
810
|
+
([request]) => request.service === 'license' && request.resource === 'users/activations'
|
|
811
|
+
);
|
|
812
|
+
|
|
813
|
+
assert.strictEqual(requests.length, 1);
|
|
814
|
+
|
|
815
|
+
return requests[0][0];
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
beforeEach(() => {
|
|
819
|
+
sandbox = sinon.createSandbox();
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
afterEach(() => {
|
|
823
|
+
sandbox.restore();
|
|
824
|
+
sandbox = null;
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
it('returns a rejected promise when no email is specified', () =>
|
|
828
|
+
unauthServices
|
|
829
|
+
.validateUser({})
|
|
830
|
+
.then(() => {
|
|
831
|
+
assert(false, 'resolved, should have thrown');
|
|
832
|
+
})
|
|
833
|
+
.catch(() => {
|
|
834
|
+
assert(true);
|
|
835
|
+
}));
|
|
836
|
+
|
|
837
|
+
it('validates an authorized user and webex instance', () =>
|
|
838
|
+
services.validateUser({email: webexUser.email}).then((r) => {
|
|
839
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
840
|
+
assert.equal(r.activated, true);
|
|
841
|
+
assert.equal(r.exists, true);
|
|
842
|
+
}));
|
|
843
|
+
|
|
844
|
+
it('validates an authorized EU user and webex instance', () =>
|
|
845
|
+
servicesEU.validateUser({email: webexUserEU.email}).then((r) => {
|
|
846
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
847
|
+
assert.equal(r.activated, true);
|
|
848
|
+
assert.equal(r.exists, true);
|
|
849
|
+
}));
|
|
850
|
+
|
|
851
|
+
it("returns a rejected promise if the provided email isn't valid", () =>
|
|
852
|
+
unauthServices
|
|
853
|
+
.validateUser({email: 'not an email'})
|
|
854
|
+
.then(() => {
|
|
855
|
+
assert(false, 'resolved, should have thrown');
|
|
856
|
+
})
|
|
857
|
+
.catch(() => {
|
|
858
|
+
assert(true);
|
|
859
|
+
}));
|
|
860
|
+
|
|
861
|
+
it('validates a non-existing user', () =>
|
|
862
|
+
unauthServices
|
|
863
|
+
.validateUser({email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`})
|
|
864
|
+
.then((r) => {
|
|
865
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
866
|
+
assert.equal(r.activated, false);
|
|
867
|
+
assert.equal(r.exists, false);
|
|
868
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
869
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
870
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
871
|
+
}));
|
|
872
|
+
|
|
873
|
+
it('validates new user with activationOptions suppressEmail false', () =>
|
|
874
|
+
unauthServices
|
|
875
|
+
.validateUser({
|
|
876
|
+
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
877
|
+
activationOptions: {suppressEmail: false},
|
|
878
|
+
})
|
|
879
|
+
.then((r) => {
|
|
880
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
881
|
+
assert.equal(r.activated, false);
|
|
882
|
+
assert.equal(r.exists, false);
|
|
883
|
+
assert.equal(r.user.verificationEmailTriggered, true);
|
|
884
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
885
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
886
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
887
|
+
}));
|
|
888
|
+
|
|
889
|
+
it('validates new user with activationOptions suppressEmail true', () =>
|
|
890
|
+
unauthServices
|
|
891
|
+
.validateUser({
|
|
892
|
+
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
893
|
+
activationOptions: {suppressEmail: true},
|
|
894
|
+
})
|
|
895
|
+
.then((r) => {
|
|
896
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
897
|
+
assert.equal(r.activated, false);
|
|
898
|
+
assert.equal(r.exists, false);
|
|
899
|
+
assert.equal(r.user.verificationEmailTriggered, false);
|
|
900
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
901
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
902
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
903
|
+
}));
|
|
904
|
+
|
|
905
|
+
it('validates an inactive user', () => {
|
|
906
|
+
const inactive = 'webex.web.client+nonactivated@gmail.com';
|
|
907
|
+
|
|
908
|
+
return unauthServices
|
|
909
|
+
.validateUser({email: inactive, activationOptions: {suppressEmail: true}})
|
|
910
|
+
.then((r) => {
|
|
911
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
912
|
+
assert.equal(r.activated, false, 'activated');
|
|
913
|
+
assert.equal(r.exists, true, 'exists');
|
|
914
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
915
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
916
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
917
|
+
})
|
|
918
|
+
.catch(() => {
|
|
919
|
+
assert(true);
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
it('validates an existing user', () =>
|
|
924
|
+
unauthServices.validateUser({email: webexUser.email}).then((r) => {
|
|
925
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
926
|
+
assert.equal(r.activated, true);
|
|
927
|
+
assert.equal(r.exists, true);
|
|
928
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
929
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
930
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
931
|
+
}));
|
|
932
|
+
|
|
933
|
+
it('validates an existing EU user', () =>
|
|
934
|
+
unauthServices.validateUser({email: webexUserEU.email}).then((r) => {
|
|
935
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
936
|
+
assert.equal(r.activated, true);
|
|
937
|
+
assert.equal(r.exists, true);
|
|
938
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
939
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
940
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
941
|
+
}));
|
|
942
|
+
|
|
943
|
+
it('sends the prelogin user id as undefined when not specified', () => {
|
|
944
|
+
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
945
|
+
|
|
946
|
+
return unauthServices
|
|
947
|
+
.validateUser({
|
|
948
|
+
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
949
|
+
activationOptions: {suppressEmail: true},
|
|
950
|
+
})
|
|
951
|
+
.then(() => {
|
|
952
|
+
assert.isUndefined(getActivationRequest(requestStub).headers['x-prelogin-userid']);
|
|
953
|
+
});
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
it('sends the prelogin user id as provided when specified', () => {
|
|
957
|
+
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
958
|
+
const preloginUserId = uuid.v4();
|
|
959
|
+
|
|
960
|
+
return unauthServices
|
|
961
|
+
.validateUser({
|
|
962
|
+
email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
|
|
963
|
+
activationOptions: {suppressEmail: true},
|
|
964
|
+
preloginUserId,
|
|
965
|
+
})
|
|
966
|
+
.then(() => {
|
|
967
|
+
assert.strictEqual(
|
|
968
|
+
getActivationRequest(requestStub).headers['x-prelogin-userid'],
|
|
969
|
+
preloginUserId
|
|
970
|
+
);
|
|
971
|
+
});
|
|
972
|
+
});
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
describe('#waitForService()', () => {
|
|
976
|
+
let name;
|
|
977
|
+
let url;
|
|
978
|
+
|
|
979
|
+
describe('when the service exists', () => {
|
|
980
|
+
beforeEach('collect valid service info', () => {
|
|
981
|
+
name = Object.keys(services.list())[0];
|
|
982
|
+
url = services.list(true)[name];
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
describe('when using the name parameter property', () => {
|
|
986
|
+
it('should resolve to the appropriate url', () =>
|
|
987
|
+
services.waitForService({name}).then((foundUrl) => assert.equal(foundUrl, url)));
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
describe('when using the url parameter property', () => {
|
|
991
|
+
it('should resolve to the appropriate url', () =>
|
|
992
|
+
services.waitForService({url}).then((foundUrl) => assert.equal(foundUrl, url)));
|
|
993
|
+
});
|
|
994
|
+
|
|
995
|
+
describe('when using the url and name parameter properties', () => {
|
|
996
|
+
it('should resolve to the appropriate url', () =>
|
|
997
|
+
services.waitForService({name, url}).then((foundUrl) => assert.equal(foundUrl, url)));
|
|
998
|
+
});
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
describe('when the service does not exist', () => {
|
|
1002
|
+
let timeout;
|
|
1003
|
+
|
|
1004
|
+
beforeEach('set up the parameters', () => {
|
|
1005
|
+
name = 'not a service';
|
|
1006
|
+
url = 'http://not-a-service.com/resource';
|
|
1007
|
+
timeout = 1;
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
describe('when using the url parameter property', () => {
|
|
1011
|
+
it('should return a resolve promise', () =>
|
|
1012
|
+
// const waitForService = services.waitForService({url, timeout});
|
|
1013
|
+
|
|
1014
|
+
services.waitForService({url, timeout}).then((foundUrl) => {
|
|
1015
|
+
assert.equal(foundUrl, url);
|
|
1016
|
+
assert.isTrue(catalog.isReady);
|
|
1017
|
+
}));
|
|
1018
|
+
});
|
|
1019
|
+
|
|
1020
|
+
describe('when using the name parameter property', () => {
|
|
1021
|
+
it('should return a rejected promise', () => {
|
|
1022
|
+
const submitMetrics = sinon.stub(webex.internal.metrics, 'submitClientMetrics');
|
|
1023
|
+
const waitForService = services.waitForService({name, timeout});
|
|
1024
|
+
|
|
1025
|
+
assert.called(submitMetrics);
|
|
1026
|
+
assert.isRejected(waitForService);
|
|
1027
|
+
assert.isTrue(catalog.isReady);
|
|
1028
|
+
});
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
describe('when using the name and url parameter properties', () => {
|
|
1032
|
+
it('should return a rejected promise', () => {
|
|
1033
|
+
const waitForService = services.waitForService({
|
|
1034
|
+
name,
|
|
1035
|
+
url,
|
|
1036
|
+
timeout,
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
assert.isRejected(waitForService);
|
|
1040
|
+
assert.isTrue(catalog.isReady);
|
|
1041
|
+
});
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
describe('when the service will exist', () => {
|
|
1045
|
+
beforeEach('collect existing service and clear the catalog', () => {
|
|
1046
|
+
name = 'metrics';
|
|
1047
|
+
url = services.get(name, true);
|
|
1048
|
+
catalog.clean();
|
|
1049
|
+
catalog.isReady = false;
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
describe('when only the preauth (limited) catalog becomes available', () => {
|
|
1053
|
+
describe('when using the name parameter property', () => {
|
|
1054
|
+
it('should resolve to the appropriate url', () =>
|
|
1055
|
+
Promise.all([
|
|
1056
|
+
services.waitForService({name}),
|
|
1057
|
+
services.collectPreauthCatalog(),
|
|
1058
|
+
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
describe('when using the url parameter property', () => {
|
|
1062
|
+
it('should resolve to the appropriate url', () =>
|
|
1063
|
+
Promise.all([
|
|
1064
|
+
services.waitForService({url}),
|
|
1065
|
+
services.collectPreauthCatalog(),
|
|
1066
|
+
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
describe('when using the name and url parameter property', () => {
|
|
1070
|
+
it('should resolve to the appropriate url', () =>
|
|
1071
|
+
Promise.all([
|
|
1072
|
+
services.waitForService({name, url}),
|
|
1073
|
+
services.collectPreauthCatalog(),
|
|
1074
|
+
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1075
|
+
});
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
describe('when all catalogs become available', () => {
|
|
1079
|
+
describe('when using the name parameter property', () => {
|
|
1080
|
+
it('should resolve to the appropriate url', () =>
|
|
1081
|
+
Promise.all([services.waitForService({name}), services.initServiceCatalogs()]).then(
|
|
1082
|
+
([foundUrl]) => assert.equal(foundUrl, url)
|
|
1083
|
+
));
|
|
1084
|
+
});
|
|
1085
|
+
|
|
1086
|
+
describe('when using the url parameter property', () => {
|
|
1087
|
+
it('should resolve to the appropriate url', () =>
|
|
1088
|
+
Promise.all([services.waitForService({url}), services.initServiceCatalogs()]).then(
|
|
1089
|
+
([foundUrl]) => assert.equal(foundUrl, url)
|
|
1090
|
+
));
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
describe('when using the name and url parameter property', () => {
|
|
1094
|
+
it('should resolve to the appropriate url', () =>
|
|
1095
|
+
Promise.all([
|
|
1096
|
+
services.waitForService({name, url}),
|
|
1097
|
+
services.initServiceCatalogs(),
|
|
1098
|
+
]).then(([foundUrl]) => assert.equal(foundUrl, url)));
|
|
1099
|
+
});
|
|
1100
|
+
});
|
|
1101
|
+
});
|
|
1102
|
+
});
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
describe('#collectPreauthCatalog()', () => {
|
|
1106
|
+
const unauthWebex = new WebexCore({config: {credentials: {federation: true}}});
|
|
1107
|
+
const unauthServices = unauthWebex.internal.services;
|
|
1108
|
+
const forceRefresh = true;
|
|
1109
|
+
|
|
1110
|
+
it('updates the preauth catalog without email', () =>
|
|
1111
|
+
unauthServices.collectPreauthCatalog().then(() => {
|
|
1112
|
+
assert.isAbove(Object.keys(unauthServices.list()).length, 0);
|
|
1113
|
+
}));
|
|
1114
|
+
|
|
1115
|
+
it('updates the preauth catalog with email', () =>
|
|
1116
|
+
unauthServices.collectPreauthCatalog({email: webexUser.email}).then(() => {
|
|
1117
|
+
assert.isAbove(Object.keys(unauthServices.list()).length, 0);
|
|
1118
|
+
}));
|
|
1119
|
+
|
|
1120
|
+
it('updates the preauth catalog with email along with additional timestamp to address cache control', (done) => {
|
|
1121
|
+
const updateServiceSpy = sinon.spy(unauthServices, 'updateServices');
|
|
1122
|
+
const fetchNewServiceHostmapSpy = sinon.spy(unauthServices, '_fetchNewServiceHostmap');
|
|
1123
|
+
|
|
1124
|
+
unauthServices.collectPreauthCatalog({email: webexUser.email}, forceRefresh).then(() => {
|
|
1125
|
+
assert.calledOnce(updateServiceSpy);
|
|
1126
|
+
assert.calledWith(
|
|
1127
|
+
updateServiceSpy,
|
|
1128
|
+
sinon.match.has(
|
|
1129
|
+
'from',
|
|
1130
|
+
'limited',
|
|
1131
|
+
'query',
|
|
1132
|
+
{emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)},
|
|
1133
|
+
'forceRefresh',
|
|
1134
|
+
forceRefresh
|
|
1135
|
+
)
|
|
1136
|
+
);
|
|
1137
|
+
|
|
1138
|
+
assert.calledOnce(fetchNewServiceHostmapSpy);
|
|
1139
|
+
assert.calledWith(
|
|
1140
|
+
fetchNewServiceHostmapSpy,
|
|
1141
|
+
sinon.match.has(
|
|
1142
|
+
'from',
|
|
1143
|
+
'limited',
|
|
1144
|
+
'query',
|
|
1145
|
+
{emailhash: sinon.match(/\b[A-Fa-f0-9]{64}\b/)},
|
|
1146
|
+
'forceRefresh',
|
|
1147
|
+
forceRefresh
|
|
1148
|
+
)
|
|
1149
|
+
);
|
|
1150
|
+
|
|
1151
|
+
fetchNewServiceHostmapSpy.returnValues[0].then((res) => {
|
|
1152
|
+
assert.isAbove(res.length, 0);
|
|
1153
|
+
});
|
|
1154
|
+
done();
|
|
1155
|
+
});
|
|
1156
|
+
});
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
describe('#collectSigninCatalog()', () => {
|
|
1160
|
+
const unauthWebex = new WebexCore({config: {credentials: {federation: true}}});
|
|
1161
|
+
const unauthServices = unauthWebex.internal.services;
|
|
1162
|
+
|
|
1163
|
+
it('requires an email as the parameter', () =>
|
|
1164
|
+
unauthServices.collectPreauthCatalog().catch((e) => {
|
|
1165
|
+
assert(true, e);
|
|
1166
|
+
}));
|
|
1167
|
+
|
|
1168
|
+
it('requires a token as the parameter', () =>
|
|
1169
|
+
unauthServices.collectPreauthCatalog({email: 'email@website.com'}).catch((e) => {
|
|
1170
|
+
assert(true, e);
|
|
1171
|
+
}));
|
|
1172
|
+
|
|
1173
|
+
it('updates the preauth catalog', () =>
|
|
1174
|
+
unauthServices.collectPreauthCatalog({email: webexUser.email}).then(() => {
|
|
1175
|
+
assert.isAbove(Object.keys(unauthServices.list()).length, 0);
|
|
1176
|
+
}));
|
|
1177
|
+
});
|
|
1178
|
+
|
|
1179
|
+
flaky(describe, process.env.SKIP_FLAKY_TESTS)('#_fetchNewServiceHostmap()', () => {
|
|
1180
|
+
let fullRemoteHM;
|
|
1181
|
+
let limitedRemoteHM;
|
|
1182
|
+
|
|
1183
|
+
before('collect remote catalogs', () =>
|
|
1184
|
+
Promise.all([
|
|
1185
|
+
services._fetchNewServiceHostmap(),
|
|
1186
|
+
services._fetchNewServiceHostmap({
|
|
1187
|
+
from: 'limited',
|
|
1188
|
+
query: {userId: webexUser.id},
|
|
1189
|
+
}),
|
|
1190
|
+
]).then(([fRHM, lRHM]) => {
|
|
1191
|
+
fullRemoteHM = fRHM;
|
|
1192
|
+
limitedRemoteHM = lRHM;
|
|
1193
|
+
})
|
|
1194
|
+
);
|
|
1195
|
+
|
|
1196
|
+
it('resolves to an authed u2c hostmap when no params specified', () => {
|
|
1197
|
+
assert.typeOf(fullRemoteHM, 'array');
|
|
1198
|
+
assert.isAbove(fullRemoteHM.length, 0);
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
it('resolves to a limited u2c hostmap when params specified', () => {
|
|
1202
|
+
assert.typeOf(limitedRemoteHM, 'array');
|
|
1203
|
+
assert.isAbove(limitedRemoteHM.length, 0);
|
|
1204
|
+
});
|
|
1205
|
+
|
|
1206
|
+
it('rejects if the params provided are invalid', () =>
|
|
1207
|
+
services
|
|
1208
|
+
._fetchNewServiceHostmap({
|
|
1209
|
+
from: 'limited',
|
|
1210
|
+
query: {userId: 'notValid'},
|
|
1211
|
+
})
|
|
1212
|
+
.then(() => {
|
|
1213
|
+
assert.isTrue(false, 'should have rejected');
|
|
1214
|
+
})
|
|
1215
|
+
.catch((e) => {
|
|
1216
|
+
assert.typeOf(e, 'Error');
|
|
1217
|
+
}));
|
|
1218
|
+
});
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1221
|
+
/* eslint-enable no-underscore-dangle */
|