@webex/internal-plugin-device 2.59.3-next.1 → 2.59.4
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 +80 -80
- package/babel.config.js +3 -3
- package/dist/config.js +27 -27
- package/dist/config.js.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/device.js +226 -226
- package/dist/device.js.map +1 -1
- package/dist/features/feature-collection.js +14 -14
- package/dist/features/feature-collection.js.map +1 -1
- package/dist/features/feature-model.js +73 -73
- package/dist/features/feature-model.js.map +1 -1
- package/dist/features/features-model.js +28 -28
- package/dist/features/features-model.js.map +1 -1
- package/dist/features/index.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/interceptors/device-url.js +8 -8
- package/dist/interceptors/device-url.js.map +1 -1
- package/dist/metrics.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +16 -17
- package/process +1 -1
- package/src/config.js +60 -60
- package/src/constants.js +23 -23
- package/src/device.js +835 -835
- package/src/features/feature-collection.js +30 -30
- package/src/features/feature-model.js +189 -189
- package/src/features/features-model.js +96 -96
- package/src/features/index.js +5 -5
- package/src/index.js +29 -29
- package/src/interceptors/device-url.js +61 -61
- package/src/metrics.js +5 -5
- package/test/integration/spec/device.js +904 -904
- package/test/integration/spec/webex.js +42 -42
- package/test/unit/spec/device.js +409 -409
- package/test/unit/spec/features/feature-collection.js +24 -24
- package/test/unit/spec/features/feature-model.js +255 -255
- package/test/unit/spec/features/features-model.js +97 -97
- package/test/unit/spec/interceptors/device-url.js +215 -215
- package/test/unit/spec/wdm-dto.json +104 -104
|
@@ -1,904 +1,904 @@
|
|
|
1
|
-
import {constants} from '@webex/internal-plugin-device';
|
|
2
|
-
import chai from 'chai';
|
|
3
|
-
import chaiAsPromised from 'chai-as-promised';
|
|
4
|
-
import sinon from 'sinon';
|
|
5
|
-
import testUsers from '@webex/test-helper-test-users';
|
|
6
|
-
import WebexCore, {WebexHttpError} from '@webex/webex-core';
|
|
7
|
-
|
|
8
|
-
const {assert} = chai;
|
|
9
|
-
const {DEVICE_EVENT_REGISTRATION_SUCCESS} = constants;
|
|
10
|
-
|
|
11
|
-
chai.use(chaiAsPromised);
|
|
12
|
-
sinon.assert.expose(chai.assert, {prefix: ''});
|
|
13
|
-
|
|
14
|
-
describe('plugin-device', () => {
|
|
15
|
-
describe('Device', () => {
|
|
16
|
-
let device;
|
|
17
|
-
let user;
|
|
18
|
-
let webex;
|
|
19
|
-
|
|
20
|
-
beforeEach('create test users and webex instance', () =>
|
|
21
|
-
testUsers.create({count: 1}).then(([createdUser]) => {
|
|
22
|
-
user = createdUser;
|
|
23
|
-
|
|
24
|
-
webex = new WebexCore({
|
|
25
|
-
credentials: user.token,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
device = webex.internal.device;
|
|
29
|
-
})
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
afterEach('unregister the device and remove test users', () =>
|
|
33
|
-
device.unregister().then(() => testUsers.remove([user]))
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
describe('events', () => {
|
|
37
|
-
describe('when a meeting is started', () => {
|
|
38
|
-
beforeEach('setup sinon', () => {
|
|
39
|
-
device.resetLogoutTimer = sinon.spy();
|
|
40
|
-
webex.trigger('meeting started');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("should set 'isInMeeting' to 'true'", () => {
|
|
44
|
-
assert.isTrue(device.isInMeeting);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("should call 'resetLogoutTimer()'", () => {
|
|
48
|
-
assert.called(device.resetLogoutTimer);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('when a meeting has ended', () => {
|
|
53
|
-
beforeEach('setup sinon', () => {
|
|
54
|
-
device.resetLogoutTimer = sinon.spy();
|
|
55
|
-
device.isInMeeting = false;
|
|
56
|
-
webex.trigger('meeting ended');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should set 'isInMeeting' to 'false'", () => {
|
|
60
|
-
assert.isFalse(device.isInMeeting);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("should call 'resetLogoutTimer()'", () => {
|
|
64
|
-
assert.called(device.resetLogoutTimer);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe('#canRegister()', () => {
|
|
70
|
-
describe('when the `wdm` service is available', () => {
|
|
71
|
-
let services;
|
|
72
|
-
|
|
73
|
-
beforeEach('destructure services plugin and get catalog', () => {
|
|
74
|
-
services = webex.internal.services;
|
|
75
|
-
|
|
76
|
-
return services.waitForCatalog('postauth');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should return a resolved promise', () => {
|
|
80
|
-
assert.isFulfilled(device.canRegister());
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('when the service catalog is not ready', () => {
|
|
85
|
-
let services;
|
|
86
|
-
|
|
87
|
-
beforeEach('setup catalog to be not ready', () => {
|
|
88
|
-
services = webex.internal.services;
|
|
89
|
-
|
|
90
|
-
services.updateServices();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe("when the 'wdm' service does exist after wait", () => {
|
|
94
|
-
it('should return a resolved promise', () => {
|
|
95
|
-
assert.isFulfilled(device.canRegister());
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe("when the 'wdm' service does not exist after wait", () => {
|
|
100
|
-
beforeEach('remove wdm service', () => {
|
|
101
|
-
services.get = sinon.stub().returns(undefined);
|
|
102
|
-
services.waitForCatalog = sinon.stub().resolves();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should return a rejected promise', () => {
|
|
106
|
-
assert.isRejected(device.canRegister());
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
describe('when the `wdm` service is not available', () => {
|
|
112
|
-
let catalog;
|
|
113
|
-
let services;
|
|
114
|
-
|
|
115
|
-
beforeEach('remove wdm service', () => {
|
|
116
|
-
services = webex.internal.services;
|
|
117
|
-
/* eslint-disable-next-line no-underscore-dangle */
|
|
118
|
-
catalog = services._getCatalog();
|
|
119
|
-
|
|
120
|
-
catalog.serviceGroups.postauth = [];
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should return a rejected promise', () => {
|
|
124
|
-
assert.isRejected(device.canRegister());
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe('#clear()', () => {
|
|
130
|
-
beforeEach('append a feature', () => {
|
|
131
|
-
device.features.set({
|
|
132
|
-
developer: [
|
|
133
|
-
{
|
|
134
|
-
key: 'console',
|
|
135
|
-
type: 'boolean',
|
|
136
|
-
val: 'true',
|
|
137
|
-
value: true,
|
|
138
|
-
mutable: true,
|
|
139
|
-
lastModified: '2015-06-29T20:02:48.033Z',
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should clear all features', () => {
|
|
146
|
-
assert.isAbove(device.features.developer.length, 0);
|
|
147
|
-
device.clear();
|
|
148
|
-
assert.lengthOf(device.features.developer, 0);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('should not clear the logger', () => {
|
|
152
|
-
assert.property(device, 'logger');
|
|
153
|
-
assert.isDefined(device.logger);
|
|
154
|
-
device.clear();
|
|
155
|
-
assert.property(device, 'logger');
|
|
156
|
-
assert.isDefined(device.logger);
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('#checkNetworkReachability()', () => {
|
|
161
|
-
describe('when the reachability check has already been completed', () => {
|
|
162
|
-
beforeEach('set reachability checked to true', () => {
|
|
163
|
-
device.isReachabilityChecked = true;
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should return a resolved promise', () => {
|
|
167
|
-
assert.isFulfilled(device.checkNetworkReachability());
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
describe('when there is no intranet inactivity check url', () => {
|
|
172
|
-
beforeEach('set device properties', () => {
|
|
173
|
-
device.intranetInactivityCheckUrl = undefined;
|
|
174
|
-
device.isReachabilityChecked = false;
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('should set the in-network property to false', () =>
|
|
178
|
-
device.checkNetworkReachability().then(() => {
|
|
179
|
-
assert.isFalse(device.isInNetwork);
|
|
180
|
-
}));
|
|
181
|
-
|
|
182
|
-
it('should return a resolved promise', () =>
|
|
183
|
-
assert.isFulfilled(device.checkNetworkReachability()));
|
|
184
|
-
|
|
185
|
-
describe('when the device has inactivity enforcement', () => {
|
|
186
|
-
let logoutTimer;
|
|
187
|
-
|
|
188
|
-
beforeEach('set device to enforce inactivity timers', () => {
|
|
189
|
-
device.config.enableInactivityEnforcement = true;
|
|
190
|
-
logoutTimer = device.logoutTimer;
|
|
191
|
-
device.intranetInactivityCheckUrl = undefined;
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should not reset the logout timer', () =>
|
|
195
|
-
device
|
|
196
|
-
.checkNetworkReachability()
|
|
197
|
-
.then(() => assert.equal(device.logoutTimer, logoutTimer)));
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
describe('when the rechability check is performable', () => {
|
|
202
|
-
beforeEach('setup for reachability check', () => {
|
|
203
|
-
// Due to property overriding, `isReachabilityChecked` must be set
|
|
204
|
-
// within each `it` statement.
|
|
205
|
-
device.isInNetwork = false;
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
describe('when the network is reachabable', () => {
|
|
209
|
-
beforeEach('set inactivity check url and stubs', () => {
|
|
210
|
-
device.intranetInactivityCheckUrl =
|
|
211
|
-
'https://myspark.cisco.com/spark_session_check.json';
|
|
212
|
-
|
|
213
|
-
device.resetLogoutTimer = sinon.spy();
|
|
214
|
-
|
|
215
|
-
device.request = sinon.stub().resolves({});
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("should call 'resetLogoutTimer()'", () => {
|
|
219
|
-
device.isReachabilityChecked = false;
|
|
220
|
-
|
|
221
|
-
return device
|
|
222
|
-
.checkNetworkReachability()
|
|
223
|
-
.then(() => assert.called(device.resetLogoutTimer));
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should set the reachability check to true', () => {
|
|
227
|
-
device.isReachabilityChecked = false;
|
|
228
|
-
|
|
229
|
-
return device
|
|
230
|
-
.checkNetworkReachability()
|
|
231
|
-
.then(() => assert.isTrue(device.isReachabilityChecked));
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('should set the in-network property to true', () => {
|
|
235
|
-
device.isReachabilityChecked = false;
|
|
236
|
-
|
|
237
|
-
assert.isFalse(device.isInNetwork);
|
|
238
|
-
|
|
239
|
-
return device.checkNetworkReachability().then(() => assert.isTrue(device.isInNetwork));
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('should return a resolved promise', () =>
|
|
243
|
-
assert.isFulfilled(device.checkNetworkReachability()));
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
describe('when the network is not reachable', () => {
|
|
247
|
-
beforeEach('set an invalid inactivity check url', () => {
|
|
248
|
-
device.intranetInactivityCheckUrl =
|
|
249
|
-
'https://myspark.cisco.com/bad-spark_session_check.json';
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('should set the reachability check to true', () => {
|
|
253
|
-
device.isReachabilityChecked = false;
|
|
254
|
-
|
|
255
|
-
return device
|
|
256
|
-
.checkNetworkReachability()
|
|
257
|
-
.then(() => assert.isTrue(device.isReachabilityChecked));
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it('should set the in-network property to false', () =>
|
|
261
|
-
device.checkNetworkReachability().then(() => assert.isFalse(device.isInNetwork)));
|
|
262
|
-
|
|
263
|
-
it('should return a resolved promise', () =>
|
|
264
|
-
assert.isFulfilled(device.checkNetworkReachability()));
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
describe('#getWebSocketUrl()', () => {
|
|
270
|
-
let services;
|
|
271
|
-
|
|
272
|
-
beforeEach('destructure services', () => {
|
|
273
|
-
services = webex.internal.services;
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
describe('when wait is truthy', () => {
|
|
277
|
-
let wait;
|
|
278
|
-
|
|
279
|
-
beforeEach('set wait', () => {
|
|
280
|
-
wait = true;
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
describe('when the device is registered', () => {
|
|
284
|
-
beforeEach('register the device', () => device.register());
|
|
285
|
-
|
|
286
|
-
it('should resolve the promise with the websocket url', () =>
|
|
287
|
-
device.getWebSocketUrl(wait).then((url) => {
|
|
288
|
-
assert.isDefined(url);
|
|
289
|
-
assert.isTrue(services.isServiceUrl(url));
|
|
290
|
-
assert.include(url, 'mercury');
|
|
291
|
-
}));
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
describe('when the device is not registered', () => {
|
|
295
|
-
describe('when the device successfully registers', () => {
|
|
296
|
-
it('should resolve the promise with the websocket url', () =>
|
|
297
|
-
Promise.all([device.getWebSocketUrl(wait), device.register()]).then(([url]) => {
|
|
298
|
-
assert.isTrue(services.isServiceUrl(url));
|
|
299
|
-
assert.include(services.getServiceFromUrl(url).name, 'mercury');
|
|
300
|
-
}));
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it('should return a rejected promise if the device never registers', () =>
|
|
304
|
-
assert.isRejected(device.getWebSocketUrl(wait)));
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
describe('when wait is falsy', () => {
|
|
309
|
-
let wait;
|
|
310
|
-
|
|
311
|
-
beforeEach('set wait', () => {
|
|
312
|
-
wait = false;
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
describe('when the device is registered', () => {
|
|
316
|
-
beforeEach('register the device', () => device.register());
|
|
317
|
-
|
|
318
|
-
describe('when the priority host can be mapped', () => {
|
|
319
|
-
it('should resolve the promise with the websocket url', () =>
|
|
320
|
-
device.getWebSocketUrl(wait).then((url) => {
|
|
321
|
-
assert.isDefined(url);
|
|
322
|
-
assert.isTrue(services.isServiceUrl(url));
|
|
323
|
-
assert.include(url, 'mercury');
|
|
324
|
-
}));
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
describe('when the priority host cannot be mapped', () => {
|
|
328
|
-
beforeEach('stub priority host url converting', () => {
|
|
329
|
-
services.convertUrlToPriorityHostUrl = sinon.stub();
|
|
330
|
-
services.convertUrlToPriorityHostUrl.returns(undefined);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
it('should return a rejected promise', () =>
|
|
334
|
-
assert.isRejected(device.getWebSocketUrl(wait)));
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
describe('when the device is not registered', () => {
|
|
339
|
-
it('should return a rejected promise', () =>
|
|
340
|
-
assert.isRejected(device.getWebSocketUrl(wait)));
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
describe('#meetingStarted()', () => {
|
|
346
|
-
let spy;
|
|
347
|
-
|
|
348
|
-
beforeEach('setup instance function', () => {
|
|
349
|
-
spy = sinon.spy();
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
it("should trigger a 'meeting started' event", () => {
|
|
353
|
-
webex.on('meeting started', spy);
|
|
354
|
-
device.meetingStarted();
|
|
355
|
-
assert.called(spy);
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
describe('#markUrlFailedAndGetNew()', () => {
|
|
360
|
-
let markFailedUrl;
|
|
361
|
-
|
|
362
|
-
beforeEach('create stubs', () => {
|
|
363
|
-
markFailedUrl = sinon.stub().returns('a new url');
|
|
364
|
-
webex.internal.services.markFailedUrl = markFailedUrl;
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
it('should return a resolved promise', () =>
|
|
368
|
-
assert.isFulfilled(device.markUrlFailedAndGetNew('a url')));
|
|
369
|
-
|
|
370
|
-
it('should call services#markFailedUrl()', () => {
|
|
371
|
-
const url = 'a sent url';
|
|
372
|
-
|
|
373
|
-
device.markUrlFailedAndGetNew(url);
|
|
374
|
-
|
|
375
|
-
assert.calledWith(markFailedUrl, url);
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
describe('#meetingEnded()', () => {
|
|
380
|
-
let spy;
|
|
381
|
-
|
|
382
|
-
beforeEach('setup instance function', () => {
|
|
383
|
-
spy = sinon.spy();
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
it("should trigger a 'meeting ended' event", () => {
|
|
387
|
-
webex.on('meeting ended', spy);
|
|
388
|
-
device.meetingEnded();
|
|
389
|
-
assert.called(spy);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
describe('#processRegistrationSuccess()', () => {
|
|
394
|
-
let customResponse;
|
|
395
|
-
let spy;
|
|
396
|
-
|
|
397
|
-
beforeEach('setup parameters', () => {
|
|
398
|
-
customResponse = {
|
|
399
|
-
body: {
|
|
400
|
-
exampleKey: 'exampleValue',
|
|
401
|
-
services: [],
|
|
402
|
-
serviceHostMap: [],
|
|
403
|
-
},
|
|
404
|
-
};
|
|
405
|
-
|
|
406
|
-
spy = sinon.spy();
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
it('should set the device properties to the response values', () => {
|
|
410
|
-
device.processRegistrationSuccess(customResponse);
|
|
411
|
-
assert.equal(device.exampleKey, customResponse.body.exampleKey);
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
it("should not set a 'services' property", () => {
|
|
415
|
-
device.processRegistrationSuccess(customResponse);
|
|
416
|
-
assert.isUndefined(device.services);
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it("should not set a 'serviceHostMap' property", () => {
|
|
420
|
-
device.processRegistrationSuccess(customResponse);
|
|
421
|
-
assert.isUndefined(device.serviceHostMap);
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
it(`should trigger '${DEVICE_EVENT_REGISTRATION_SUCCESS}'`, () => {
|
|
425
|
-
device.on(DEVICE_EVENT_REGISTRATION_SUCCESS, spy);
|
|
426
|
-
device.processRegistrationSuccess(customResponse);
|
|
427
|
-
assert.called(spy);
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
describe('when the device is ephemeral', () => {
|
|
431
|
-
beforeEach('set the device to ephemeral', () => {
|
|
432
|
-
device.config.ephemeral = true;
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
it('should create a refresh timer', () => {
|
|
436
|
-
const {refreshTimer} = device;
|
|
437
|
-
|
|
438
|
-
device.processRegistrationSuccess(customResponse);
|
|
439
|
-
assert.notEqual(device.refreshTimer, refreshTimer);
|
|
440
|
-
assert.isDefined(device.refreshTimer);
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
describe('#refresh()', () => {
|
|
446
|
-
describe('when the device can register', () => {
|
|
447
|
-
describe('when the device is not registered', () => {
|
|
448
|
-
beforeEach('setup spy function', () => {
|
|
449
|
-
device.register = sinon.spy();
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
it('should attempt to register', () =>
|
|
453
|
-
device.refresh().then(() => assert.called(device.register)));
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
describe('when the device is registered', () => {
|
|
457
|
-
let exampleResponse;
|
|
458
|
-
|
|
459
|
-
beforeEach('register the device', () => {
|
|
460
|
-
exampleResponse = {
|
|
461
|
-
body: {
|
|
462
|
-
exampleKey: 'example response value',
|
|
463
|
-
},
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
return device.register().then(() => {
|
|
467
|
-
device.request = sinon.stub().returns(Promise.resolve({...exampleResponse}));
|
|
468
|
-
});
|
|
469
|
-
});
|
|
470
|
-
|
|
471
|
-
describe('when the device is ephemeral', () => {
|
|
472
|
-
beforeEach('set device to ephemeral', () => {
|
|
473
|
-
device.config.ephemeral = true;
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
it('should set the ttl property to the config values', () =>
|
|
477
|
-
device
|
|
478
|
-
.refresh()
|
|
479
|
-
.then(() =>
|
|
480
|
-
assert.calledWith(
|
|
481
|
-
device.request,
|
|
482
|
-
sinon.match.hasNested('body.ttl', device.config.ephemeralDeviceTTL)
|
|
483
|
-
)
|
|
484
|
-
));
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
describe('when the refresh request is sent', () => {
|
|
488
|
-
let customHeaders;
|
|
489
|
-
let customBody;
|
|
490
|
-
|
|
491
|
-
beforeEach('configure device plugin', () => {
|
|
492
|
-
customHeaders = {
|
|
493
|
-
testHeader: 'example header value',
|
|
494
|
-
};
|
|
495
|
-
|
|
496
|
-
customBody = {
|
|
497
|
-
testBody: 'example body value',
|
|
498
|
-
};
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
it('should allow for custom header key:values', () => {
|
|
502
|
-
device.config.headers = {...customHeaders};
|
|
503
|
-
|
|
504
|
-
return device
|
|
505
|
-
.refresh()
|
|
506
|
-
.then(() =>
|
|
507
|
-
assert.calledWith(
|
|
508
|
-
device.request,
|
|
509
|
-
sinon.match.hasNested('headers.testHeader', customHeaders.testHeader)
|
|
510
|
-
)
|
|
511
|
-
);
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
it('should allow for custom body key:values', () => {
|
|
515
|
-
device.config.body = {...customBody};
|
|
516
|
-
|
|
517
|
-
return device
|
|
518
|
-
.refresh()
|
|
519
|
-
.then(() =>
|
|
520
|
-
assert.calledWith(
|
|
521
|
-
device.request,
|
|
522
|
-
sinon.match.hasNested('body.testBody', customBody.testBody)
|
|
523
|
-
)
|
|
524
|
-
);
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
it("should use the device's url property", () => {
|
|
528
|
-
device.config.body = {...customBody};
|
|
529
|
-
|
|
530
|
-
return device
|
|
531
|
-
.refresh()
|
|
532
|
-
.then(() => assert.calledWith(device.request, sinon.match.has('uri', device.url)));
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
it('should send a PUT request', () => {
|
|
536
|
-
device.config.body = {...customBody};
|
|
537
|
-
|
|
538
|
-
return device
|
|
539
|
-
.refresh()
|
|
540
|
-
.then(() => assert.calledWith(device.request, sinon.match.has('method', 'PUT')));
|
|
541
|
-
});
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
describe('when the device is successfully refreshes', () => {
|
|
545
|
-
beforeEach('setup stubs', () => {
|
|
546
|
-
device.processRegistrationSuccess = sinon.stub();
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
it('should return a resolved promise', () => assert.isFulfilled(device.refresh()));
|
|
550
|
-
|
|
551
|
-
it("should call 'processRegistrationSuccess()'", () =>
|
|
552
|
-
device.refresh().then(() => assert.called(device.processRegistrationSuccess)));
|
|
553
|
-
});
|
|
554
|
-
|
|
555
|
-
describe('when the device fails to refresh', () => {
|
|
556
|
-
describe('when the device is not found', () => {
|
|
557
|
-
let request;
|
|
558
|
-
|
|
559
|
-
beforeEach('setup request stub to 404', () => {
|
|
560
|
-
request = device.request;
|
|
561
|
-
|
|
562
|
-
device.register = sinon.spy();
|
|
563
|
-
|
|
564
|
-
device.request = sinon.stub().rejects(
|
|
565
|
-
new WebexHttpError({
|
|
566
|
-
statusCode: 404,
|
|
567
|
-
options: {
|
|
568
|
-
url: device.url,
|
|
569
|
-
headers: {
|
|
570
|
-
trackingId: 'tid',
|
|
571
|
-
},
|
|
572
|
-
},
|
|
573
|
-
})
|
|
574
|
-
);
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
afterEach('reset the device request', () => {
|
|
578
|
-
device.request = request;
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
it('should clear the current device', () =>
|
|
582
|
-
device.refresh().then(() => assert.isUndefined(device.url)));
|
|
583
|
-
|
|
584
|
-
it('should attempt to register a new device', () =>
|
|
585
|
-
device.refresh().then(() => assert.called(device.register)));
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
describe('when the device was found', () => {
|
|
589
|
-
let request;
|
|
590
|
-
|
|
591
|
-
beforeEach('setup request stub to 503', () => {
|
|
592
|
-
request = device.request;
|
|
593
|
-
|
|
594
|
-
device.request = sinon.stub().rejects(
|
|
595
|
-
new WebexHttpError({
|
|
596
|
-
statusCode: 503,
|
|
597
|
-
options: {
|
|
598
|
-
url: device.url,
|
|
599
|
-
headers: {
|
|
600
|
-
trackingId: 'tid',
|
|
601
|
-
},
|
|
602
|
-
},
|
|
603
|
-
})
|
|
604
|
-
);
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
afterEach('resest the request method', () => {
|
|
608
|
-
device.request = request;
|
|
609
|
-
});
|
|
610
|
-
|
|
611
|
-
it('should return a rejected promise', () => assert.isRejected(device.refresh()));
|
|
612
|
-
});
|
|
613
|
-
});
|
|
614
|
-
});
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
describe('when the device cannot register', () => {
|
|
618
|
-
beforeEach("setup 'canRegister()' stub", () => {
|
|
619
|
-
device.canRegister = sinon.stub().rejects(new Error());
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
it('should return a rejected promise', () => assert.isRejected(device.refresh()));
|
|
623
|
-
});
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
describe('#register()', () => {
|
|
627
|
-
describe('when the device can register', () => {
|
|
628
|
-
describe('when the device is already registered', () => {
|
|
629
|
-
beforeEach("setup 'register()' spy and register", () => {
|
|
630
|
-
device.refresh = sinon.spy();
|
|
631
|
-
|
|
632
|
-
return device.register();
|
|
633
|
-
});
|
|
634
|
-
|
|
635
|
-
it('should attempt to refresh', () =>
|
|
636
|
-
device.register().then(() => assert.called(device.refresh)));
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
describe('when the device is not already registered', () => {
|
|
640
|
-
let exampleResponse;
|
|
641
|
-
|
|
642
|
-
beforeEach('setup stubs and scoped variables', () => {
|
|
643
|
-
exampleResponse = {
|
|
644
|
-
body: {
|
|
645
|
-
exampleKey: 'example response value',
|
|
646
|
-
},
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
device.request = sinon.stub().returns(Promise.resolve({...exampleResponse}));
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
describe('when the registration request is sent', () => {
|
|
653
|
-
let customHeaders;
|
|
654
|
-
let customBody;
|
|
655
|
-
|
|
656
|
-
beforeEach('configure device plugin', () => {
|
|
657
|
-
customHeaders = {
|
|
658
|
-
testHeader: 'example header value',
|
|
659
|
-
};
|
|
660
|
-
|
|
661
|
-
customBody = {
|
|
662
|
-
testBody: 'example body value',
|
|
663
|
-
};
|
|
664
|
-
});
|
|
665
|
-
|
|
666
|
-
it('should allow for custom header key:values', () => {
|
|
667
|
-
device.config.headers = {...customHeaders};
|
|
668
|
-
|
|
669
|
-
return device
|
|
670
|
-
.register()
|
|
671
|
-
.then(() =>
|
|
672
|
-
assert.calledWith(
|
|
673
|
-
device.request,
|
|
674
|
-
sinon.match.hasNested('headers.testHeader', customHeaders.testHeader)
|
|
675
|
-
)
|
|
676
|
-
);
|
|
677
|
-
});
|
|
678
|
-
|
|
679
|
-
it('should allow for custom body key:values', () => {
|
|
680
|
-
device.config.body = {...customBody};
|
|
681
|
-
|
|
682
|
-
return device
|
|
683
|
-
.register()
|
|
684
|
-
.then(() =>
|
|
685
|
-
assert.calledWith(
|
|
686
|
-
device.request,
|
|
687
|
-
sinon.match.hasNested('body.testBody', customBody.testBody)
|
|
688
|
-
)
|
|
689
|
-
);
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
it("should use the 'wdm' service", () => {
|
|
693
|
-
device.config.body = {...customBody};
|
|
694
|
-
|
|
695
|
-
return device
|
|
696
|
-
.register()
|
|
697
|
-
.then(() => assert.calledWith(device.request, sinon.match.has('service', 'wdm')));
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
it("should use the 'devices' resource", () => {
|
|
701
|
-
device.config.body = {...customBody};
|
|
702
|
-
|
|
703
|
-
return device
|
|
704
|
-
.register()
|
|
705
|
-
.then(() =>
|
|
706
|
-
assert.calledWith(device.request, sinon.match.has('resource', 'devices'))
|
|
707
|
-
);
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
it('should send a POST request', () => {
|
|
711
|
-
device.config.body = {...customBody};
|
|
712
|
-
|
|
713
|
-
return device
|
|
714
|
-
.register()
|
|
715
|
-
.then(() => assert.calledWith(device.request, sinon.match.has('method', 'POST')));
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
it('should set TTL if configured as ephemeral', () => {
|
|
719
|
-
device.config.ephemeral = true;
|
|
720
|
-
device.config.ephemeralDeviceTTL = 3600;
|
|
721
|
-
|
|
722
|
-
return device
|
|
723
|
-
.register()
|
|
724
|
-
.then(() =>
|
|
725
|
-
assert.calledWith(device.request, sinon.match.hasNested('body.ttl', 3600))
|
|
726
|
-
);
|
|
727
|
-
});
|
|
728
|
-
});
|
|
729
|
-
|
|
730
|
-
describe('when the device is successfully registered', () => {
|
|
731
|
-
beforeEach('setup stubs', () => {
|
|
732
|
-
device.processRegistrationSuccess = sinon.stub();
|
|
733
|
-
});
|
|
734
|
-
|
|
735
|
-
it('should return a resolved promise', () => assert.isFulfilled(device.register()));
|
|
736
|
-
|
|
737
|
-
it("should call 'processRegistrationSuccess()'", () =>
|
|
738
|
-
device.register().then(() => assert.called(device.processRegistrationSuccess)));
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
describe('when the device fails to register', () => {
|
|
742
|
-
beforeEach('setup request stub to 503', () => {
|
|
743
|
-
device.request = sinon.stub().rejects(
|
|
744
|
-
new WebexHttpError({
|
|
745
|
-
statusCode: 503,
|
|
746
|
-
options: {
|
|
747
|
-
url: 'http://not-a-url.com/resource',
|
|
748
|
-
headers: {
|
|
749
|
-
trackingId: 'tid',
|
|
750
|
-
},
|
|
751
|
-
},
|
|
752
|
-
})
|
|
753
|
-
);
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
it('should return a rejected promise', () => assert.isRejected(device.register()));
|
|
757
|
-
});
|
|
758
|
-
});
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
describe('when the device cannot register', () => {
|
|
762
|
-
beforeEach("setup 'canRegister()' stub", () => {
|
|
763
|
-
device.canRegister = sinon.stub().rejects(new Error());
|
|
764
|
-
});
|
|
765
|
-
|
|
766
|
-
it('should return a rejected promise', () => assert.isRejected(device.register()));
|
|
767
|
-
});
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
describe('#resetLogoutTimer()', () => {
|
|
771
|
-
describe('when inactivty enforcement is enabled', () => {
|
|
772
|
-
beforeEach('set inactity enforcement and reachability checked', () => {
|
|
773
|
-
device.config.enableInactivityEnforcement = true;
|
|
774
|
-
device.isReachabilityChecked = true;
|
|
775
|
-
});
|
|
776
|
-
|
|
777
|
-
describe('when the user is in a meeting', () => {
|
|
778
|
-
beforeEach('set user to be in a meeting', () => {
|
|
779
|
-
device.isInMeeting = true;
|
|
780
|
-
});
|
|
781
|
-
|
|
782
|
-
it('should not set the logout timer', () => {
|
|
783
|
-
device.resetLogoutTimer();
|
|
784
|
-
|
|
785
|
-
assert.isUndefined(device.logoutTimer);
|
|
786
|
-
});
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
describe('when the user is not in a meeting', () => {
|
|
790
|
-
beforeEach("setup the 'setLogoutTimer()' spy", () => {
|
|
791
|
-
device.setLogoutTimer = sinon.stub();
|
|
792
|
-
});
|
|
793
|
-
|
|
794
|
-
describe('when the user is in network', () => {
|
|
795
|
-
beforeEach('set user to be in network', () => {
|
|
796
|
-
device.isInNetwork = true;
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
it('should set the logout timer to the in-network duration', () => {
|
|
800
|
-
device.resetLogoutTimer();
|
|
801
|
-
|
|
802
|
-
assert.calledWith(device.setLogoutTimer, device.intranetInactivityCheckUrl);
|
|
803
|
-
});
|
|
804
|
-
});
|
|
805
|
-
|
|
806
|
-
describe('when the user is not in network', () => {
|
|
807
|
-
beforeEach('set the user to not be in network', () => {
|
|
808
|
-
device.isInNetwork = false;
|
|
809
|
-
});
|
|
810
|
-
|
|
811
|
-
it('should set the logout timer to the intranet duration', () => {
|
|
812
|
-
device.resetLogoutTimer();
|
|
813
|
-
|
|
814
|
-
assert.calledWith(device.setLogoutTimer, device.intranetInactivityDuration);
|
|
815
|
-
});
|
|
816
|
-
});
|
|
817
|
-
});
|
|
818
|
-
});
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
describe('#unregister()', () => {
|
|
822
|
-
describe('when the device is registered', () => {
|
|
823
|
-
beforeEach('register the device', () => device.register());
|
|
824
|
-
|
|
825
|
-
describe('when the unregistration request is sent', () => {
|
|
826
|
-
let url;
|
|
827
|
-
|
|
828
|
-
beforeEach("setup the 'request()' stub", () => {
|
|
829
|
-
device.request = sinon.stub().resolves();
|
|
830
|
-
url = device.url;
|
|
831
|
-
});
|
|
832
|
-
|
|
833
|
-
it("should use the device's url property", () =>
|
|
834
|
-
device
|
|
835
|
-
.unregister()
|
|
836
|
-
.then(() => assert.calledWith(device.request, sinon.match.has('uri', url))));
|
|
837
|
-
|
|
838
|
-
it('should send a DELETE request', () =>
|
|
839
|
-
device
|
|
840
|
-
.unregister()
|
|
841
|
-
.then(() => assert.calledWith(device.request, sinon.match.has('method', 'DELETE'))));
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
describe('when the device unregistration request is successful', () => {
|
|
845
|
-
it('should clear the device url', () =>
|
|
846
|
-
device.unregister().then(() => assert.isUndefined(device.url)));
|
|
847
|
-
});
|
|
848
|
-
|
|
849
|
-
describe('when the device unregistration request fails', () => {
|
|
850
|
-
let request;
|
|
851
|
-
|
|
852
|
-
beforeEach("setup the 'request' stub", () => {
|
|
853
|
-
request = device.request;
|
|
854
|
-
|
|
855
|
-
device.request = sinon.stub().rejects(
|
|
856
|
-
new WebexHttpError({
|
|
857
|
-
statusCode: 404,
|
|
858
|
-
options: {
|
|
859
|
-
url: device.url,
|
|
860
|
-
headers: {
|
|
861
|
-
trackingId: 'tid',
|
|
862
|
-
},
|
|
863
|
-
},
|
|
864
|
-
})
|
|
865
|
-
);
|
|
866
|
-
});
|
|
867
|
-
|
|
868
|
-
afterEach('reset the request method', () => {
|
|
869
|
-
device.request = request;
|
|
870
|
-
});
|
|
871
|
-
|
|
872
|
-
it('returns a rejected promise', () => assert.isRejected(device.unregister()));
|
|
873
|
-
});
|
|
874
|
-
});
|
|
875
|
-
|
|
876
|
-
describe('when the device is not registered', () => {
|
|
877
|
-
it('should return a resolved promise', () => assert.isFulfilled(device.unregister()));
|
|
878
|
-
});
|
|
879
|
-
});
|
|
880
|
-
|
|
881
|
-
describe('#waitForRegistration()', () => {
|
|
882
|
-
describe('when the device is registered', () => {
|
|
883
|
-
beforeEach('register the device', () => device.register());
|
|
884
|
-
|
|
885
|
-
it('should return a resolved promise', () =>
|
|
886
|
-
assert.isFulfilled(device.waitForRegistration()));
|
|
887
|
-
});
|
|
888
|
-
|
|
889
|
-
describe('when the device is not registered', () => {
|
|
890
|
-
describe('when the device registers', () => {
|
|
891
|
-
it('should return a resolved promise once registered', () =>
|
|
892
|
-
Promise.all([device.waitForRegistration(), device.register()]).then(() =>
|
|
893
|
-
assert.isTrue(device.registered)
|
|
894
|
-
));
|
|
895
|
-
});
|
|
896
|
-
|
|
897
|
-
describe('when the device does not register', () => {
|
|
898
|
-
it('should return a rejected promise', () =>
|
|
899
|
-
assert.isRejected(device.waitForRegistration()));
|
|
900
|
-
});
|
|
901
|
-
});
|
|
902
|
-
});
|
|
903
|
-
});
|
|
904
|
-
});
|
|
1
|
+
import {constants} from '@webex/internal-plugin-device';
|
|
2
|
+
import chai from 'chai';
|
|
3
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
4
|
+
import sinon from 'sinon';
|
|
5
|
+
import testUsers from '@webex/test-helper-test-users';
|
|
6
|
+
import WebexCore, {WebexHttpError} from '@webex/webex-core';
|
|
7
|
+
|
|
8
|
+
const {assert} = chai;
|
|
9
|
+
const {DEVICE_EVENT_REGISTRATION_SUCCESS} = constants;
|
|
10
|
+
|
|
11
|
+
chai.use(chaiAsPromised);
|
|
12
|
+
sinon.assert.expose(chai.assert, {prefix: ''});
|
|
13
|
+
|
|
14
|
+
describe('plugin-device', () => {
|
|
15
|
+
describe('Device', () => {
|
|
16
|
+
let device;
|
|
17
|
+
let user;
|
|
18
|
+
let webex;
|
|
19
|
+
|
|
20
|
+
beforeEach('create test users and webex instance', () =>
|
|
21
|
+
testUsers.create({count: 1}).then(([createdUser]) => {
|
|
22
|
+
user = createdUser;
|
|
23
|
+
|
|
24
|
+
webex = new WebexCore({
|
|
25
|
+
credentials: user.token,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
device = webex.internal.device;
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
afterEach('unregister the device and remove test users', () =>
|
|
33
|
+
device.unregister().then(() => testUsers.remove([user]))
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
describe('events', () => {
|
|
37
|
+
describe('when a meeting is started', () => {
|
|
38
|
+
beforeEach('setup sinon', () => {
|
|
39
|
+
device.resetLogoutTimer = sinon.spy();
|
|
40
|
+
webex.trigger('meeting started');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should set 'isInMeeting' to 'true'", () => {
|
|
44
|
+
assert.isTrue(device.isInMeeting);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should call 'resetLogoutTimer()'", () => {
|
|
48
|
+
assert.called(device.resetLogoutTimer);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('when a meeting has ended', () => {
|
|
53
|
+
beforeEach('setup sinon', () => {
|
|
54
|
+
device.resetLogoutTimer = sinon.spy();
|
|
55
|
+
device.isInMeeting = false;
|
|
56
|
+
webex.trigger('meeting ended');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should set 'isInMeeting' to 'false'", () => {
|
|
60
|
+
assert.isFalse(device.isInMeeting);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("should call 'resetLogoutTimer()'", () => {
|
|
64
|
+
assert.called(device.resetLogoutTimer);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('#canRegister()', () => {
|
|
70
|
+
describe('when the `wdm` service is available', () => {
|
|
71
|
+
let services;
|
|
72
|
+
|
|
73
|
+
beforeEach('destructure services plugin and get catalog', () => {
|
|
74
|
+
services = webex.internal.services;
|
|
75
|
+
|
|
76
|
+
return services.waitForCatalog('postauth');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should return a resolved promise', () => {
|
|
80
|
+
assert.isFulfilled(device.canRegister());
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('when the service catalog is not ready', () => {
|
|
85
|
+
let services;
|
|
86
|
+
|
|
87
|
+
beforeEach('setup catalog to be not ready', () => {
|
|
88
|
+
services = webex.internal.services;
|
|
89
|
+
|
|
90
|
+
services.updateServices();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe("when the 'wdm' service does exist after wait", () => {
|
|
94
|
+
it('should return a resolved promise', () => {
|
|
95
|
+
assert.isFulfilled(device.canRegister());
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("when the 'wdm' service does not exist after wait", () => {
|
|
100
|
+
beforeEach('remove wdm service', () => {
|
|
101
|
+
services.get = sinon.stub().returns(undefined);
|
|
102
|
+
services.waitForCatalog = sinon.stub().resolves();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should return a rejected promise', () => {
|
|
106
|
+
assert.isRejected(device.canRegister());
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('when the `wdm` service is not available', () => {
|
|
112
|
+
let catalog;
|
|
113
|
+
let services;
|
|
114
|
+
|
|
115
|
+
beforeEach('remove wdm service', () => {
|
|
116
|
+
services = webex.internal.services;
|
|
117
|
+
/* eslint-disable-next-line no-underscore-dangle */
|
|
118
|
+
catalog = services._getCatalog();
|
|
119
|
+
|
|
120
|
+
catalog.serviceGroups.postauth = [];
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should return a rejected promise', () => {
|
|
124
|
+
assert.isRejected(device.canRegister());
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('#clear()', () => {
|
|
130
|
+
beforeEach('append a feature', () => {
|
|
131
|
+
device.features.set({
|
|
132
|
+
developer: [
|
|
133
|
+
{
|
|
134
|
+
key: 'console',
|
|
135
|
+
type: 'boolean',
|
|
136
|
+
val: 'true',
|
|
137
|
+
value: true,
|
|
138
|
+
mutable: true,
|
|
139
|
+
lastModified: '2015-06-29T20:02:48.033Z',
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should clear all features', () => {
|
|
146
|
+
assert.isAbove(device.features.developer.length, 0);
|
|
147
|
+
device.clear();
|
|
148
|
+
assert.lengthOf(device.features.developer, 0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should not clear the logger', () => {
|
|
152
|
+
assert.property(device, 'logger');
|
|
153
|
+
assert.isDefined(device.logger);
|
|
154
|
+
device.clear();
|
|
155
|
+
assert.property(device, 'logger');
|
|
156
|
+
assert.isDefined(device.logger);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('#checkNetworkReachability()', () => {
|
|
161
|
+
describe('when the reachability check has already been completed', () => {
|
|
162
|
+
beforeEach('set reachability checked to true', () => {
|
|
163
|
+
device.isReachabilityChecked = true;
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should return a resolved promise', () => {
|
|
167
|
+
assert.isFulfilled(device.checkNetworkReachability());
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('when there is no intranet inactivity check url', () => {
|
|
172
|
+
beforeEach('set device properties', () => {
|
|
173
|
+
device.intranetInactivityCheckUrl = undefined;
|
|
174
|
+
device.isReachabilityChecked = false;
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should set the in-network property to false', () =>
|
|
178
|
+
device.checkNetworkReachability().then(() => {
|
|
179
|
+
assert.isFalse(device.isInNetwork);
|
|
180
|
+
}));
|
|
181
|
+
|
|
182
|
+
it('should return a resolved promise', () =>
|
|
183
|
+
assert.isFulfilled(device.checkNetworkReachability()));
|
|
184
|
+
|
|
185
|
+
describe('when the device has inactivity enforcement', () => {
|
|
186
|
+
let logoutTimer;
|
|
187
|
+
|
|
188
|
+
beforeEach('set device to enforce inactivity timers', () => {
|
|
189
|
+
device.config.enableInactivityEnforcement = true;
|
|
190
|
+
logoutTimer = device.logoutTimer;
|
|
191
|
+
device.intranetInactivityCheckUrl = undefined;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should not reset the logout timer', () =>
|
|
195
|
+
device
|
|
196
|
+
.checkNetworkReachability()
|
|
197
|
+
.then(() => assert.equal(device.logoutTimer, logoutTimer)));
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe('when the rechability check is performable', () => {
|
|
202
|
+
beforeEach('setup for reachability check', () => {
|
|
203
|
+
// Due to property overriding, `isReachabilityChecked` must be set
|
|
204
|
+
// within each `it` statement.
|
|
205
|
+
device.isInNetwork = false;
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('when the network is reachabable', () => {
|
|
209
|
+
beforeEach('set inactivity check url and stubs', () => {
|
|
210
|
+
device.intranetInactivityCheckUrl =
|
|
211
|
+
'https://myspark.cisco.com/spark_session_check.json';
|
|
212
|
+
|
|
213
|
+
device.resetLogoutTimer = sinon.spy();
|
|
214
|
+
|
|
215
|
+
device.request = sinon.stub().resolves({});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("should call 'resetLogoutTimer()'", () => {
|
|
219
|
+
device.isReachabilityChecked = false;
|
|
220
|
+
|
|
221
|
+
return device
|
|
222
|
+
.checkNetworkReachability()
|
|
223
|
+
.then(() => assert.called(device.resetLogoutTimer));
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should set the reachability check to true', () => {
|
|
227
|
+
device.isReachabilityChecked = false;
|
|
228
|
+
|
|
229
|
+
return device
|
|
230
|
+
.checkNetworkReachability()
|
|
231
|
+
.then(() => assert.isTrue(device.isReachabilityChecked));
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should set the in-network property to true', () => {
|
|
235
|
+
device.isReachabilityChecked = false;
|
|
236
|
+
|
|
237
|
+
assert.isFalse(device.isInNetwork);
|
|
238
|
+
|
|
239
|
+
return device.checkNetworkReachability().then(() => assert.isTrue(device.isInNetwork));
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('should return a resolved promise', () =>
|
|
243
|
+
assert.isFulfilled(device.checkNetworkReachability()));
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe('when the network is not reachable', () => {
|
|
247
|
+
beforeEach('set an invalid inactivity check url', () => {
|
|
248
|
+
device.intranetInactivityCheckUrl =
|
|
249
|
+
'https://myspark.cisco.com/bad-spark_session_check.json';
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should set the reachability check to true', () => {
|
|
253
|
+
device.isReachabilityChecked = false;
|
|
254
|
+
|
|
255
|
+
return device
|
|
256
|
+
.checkNetworkReachability()
|
|
257
|
+
.then(() => assert.isTrue(device.isReachabilityChecked));
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('should set the in-network property to false', () =>
|
|
261
|
+
device.checkNetworkReachability().then(() => assert.isFalse(device.isInNetwork)));
|
|
262
|
+
|
|
263
|
+
it('should return a resolved promise', () =>
|
|
264
|
+
assert.isFulfilled(device.checkNetworkReachability()));
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe('#getWebSocketUrl()', () => {
|
|
270
|
+
let services;
|
|
271
|
+
|
|
272
|
+
beforeEach('destructure services', () => {
|
|
273
|
+
services = webex.internal.services;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
describe('when wait is truthy', () => {
|
|
277
|
+
let wait;
|
|
278
|
+
|
|
279
|
+
beforeEach('set wait', () => {
|
|
280
|
+
wait = true;
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
describe('when the device is registered', () => {
|
|
284
|
+
beforeEach('register the device', () => device.register());
|
|
285
|
+
|
|
286
|
+
it('should resolve the promise with the websocket url', () =>
|
|
287
|
+
device.getWebSocketUrl(wait).then((url) => {
|
|
288
|
+
assert.isDefined(url);
|
|
289
|
+
assert.isTrue(services.isServiceUrl(url));
|
|
290
|
+
assert.include(url, 'mercury');
|
|
291
|
+
}));
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe('when the device is not registered', () => {
|
|
295
|
+
describe('when the device successfully registers', () => {
|
|
296
|
+
it('should resolve the promise with the websocket url', () =>
|
|
297
|
+
Promise.all([device.getWebSocketUrl(wait), device.register()]).then(([url]) => {
|
|
298
|
+
assert.isTrue(services.isServiceUrl(url));
|
|
299
|
+
assert.include(services.getServiceFromUrl(url).name, 'mercury');
|
|
300
|
+
}));
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('should return a rejected promise if the device never registers', () =>
|
|
304
|
+
assert.isRejected(device.getWebSocketUrl(wait)));
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe('when wait is falsy', () => {
|
|
309
|
+
let wait;
|
|
310
|
+
|
|
311
|
+
beforeEach('set wait', () => {
|
|
312
|
+
wait = false;
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
describe('when the device is registered', () => {
|
|
316
|
+
beforeEach('register the device', () => device.register());
|
|
317
|
+
|
|
318
|
+
describe('when the priority host can be mapped', () => {
|
|
319
|
+
it('should resolve the promise with the websocket url', () =>
|
|
320
|
+
device.getWebSocketUrl(wait).then((url) => {
|
|
321
|
+
assert.isDefined(url);
|
|
322
|
+
assert.isTrue(services.isServiceUrl(url));
|
|
323
|
+
assert.include(url, 'mercury');
|
|
324
|
+
}));
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
describe('when the priority host cannot be mapped', () => {
|
|
328
|
+
beforeEach('stub priority host url converting', () => {
|
|
329
|
+
services.convertUrlToPriorityHostUrl = sinon.stub();
|
|
330
|
+
services.convertUrlToPriorityHostUrl.returns(undefined);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('should return a rejected promise', () =>
|
|
334
|
+
assert.isRejected(device.getWebSocketUrl(wait)));
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
describe('when the device is not registered', () => {
|
|
339
|
+
it('should return a rejected promise', () =>
|
|
340
|
+
assert.isRejected(device.getWebSocketUrl(wait)));
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
describe('#meetingStarted()', () => {
|
|
346
|
+
let spy;
|
|
347
|
+
|
|
348
|
+
beforeEach('setup instance function', () => {
|
|
349
|
+
spy = sinon.spy();
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it("should trigger a 'meeting started' event", () => {
|
|
353
|
+
webex.on('meeting started', spy);
|
|
354
|
+
device.meetingStarted();
|
|
355
|
+
assert.called(spy);
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
describe('#markUrlFailedAndGetNew()', () => {
|
|
360
|
+
let markFailedUrl;
|
|
361
|
+
|
|
362
|
+
beforeEach('create stubs', () => {
|
|
363
|
+
markFailedUrl = sinon.stub().returns('a new url');
|
|
364
|
+
webex.internal.services.markFailedUrl = markFailedUrl;
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('should return a resolved promise', () =>
|
|
368
|
+
assert.isFulfilled(device.markUrlFailedAndGetNew('a url')));
|
|
369
|
+
|
|
370
|
+
it('should call services#markFailedUrl()', () => {
|
|
371
|
+
const url = 'a sent url';
|
|
372
|
+
|
|
373
|
+
device.markUrlFailedAndGetNew(url);
|
|
374
|
+
|
|
375
|
+
assert.calledWith(markFailedUrl, url);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe('#meetingEnded()', () => {
|
|
380
|
+
let spy;
|
|
381
|
+
|
|
382
|
+
beforeEach('setup instance function', () => {
|
|
383
|
+
spy = sinon.spy();
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it("should trigger a 'meeting ended' event", () => {
|
|
387
|
+
webex.on('meeting ended', spy);
|
|
388
|
+
device.meetingEnded();
|
|
389
|
+
assert.called(spy);
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
describe('#processRegistrationSuccess()', () => {
|
|
394
|
+
let customResponse;
|
|
395
|
+
let spy;
|
|
396
|
+
|
|
397
|
+
beforeEach('setup parameters', () => {
|
|
398
|
+
customResponse = {
|
|
399
|
+
body: {
|
|
400
|
+
exampleKey: 'exampleValue',
|
|
401
|
+
services: [],
|
|
402
|
+
serviceHostMap: [],
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
spy = sinon.spy();
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('should set the device properties to the response values', () => {
|
|
410
|
+
device.processRegistrationSuccess(customResponse);
|
|
411
|
+
assert.equal(device.exampleKey, customResponse.body.exampleKey);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("should not set a 'services' property", () => {
|
|
415
|
+
device.processRegistrationSuccess(customResponse);
|
|
416
|
+
assert.isUndefined(device.services);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it("should not set a 'serviceHostMap' property", () => {
|
|
420
|
+
device.processRegistrationSuccess(customResponse);
|
|
421
|
+
assert.isUndefined(device.serviceHostMap);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it(`should trigger '${DEVICE_EVENT_REGISTRATION_SUCCESS}'`, () => {
|
|
425
|
+
device.on(DEVICE_EVENT_REGISTRATION_SUCCESS, spy);
|
|
426
|
+
device.processRegistrationSuccess(customResponse);
|
|
427
|
+
assert.called(spy);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe('when the device is ephemeral', () => {
|
|
431
|
+
beforeEach('set the device to ephemeral', () => {
|
|
432
|
+
device.config.ephemeral = true;
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it('should create a refresh timer', () => {
|
|
436
|
+
const {refreshTimer} = device;
|
|
437
|
+
|
|
438
|
+
device.processRegistrationSuccess(customResponse);
|
|
439
|
+
assert.notEqual(device.refreshTimer, refreshTimer);
|
|
440
|
+
assert.isDefined(device.refreshTimer);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
describe('#refresh()', () => {
|
|
446
|
+
describe('when the device can register', () => {
|
|
447
|
+
describe('when the device is not registered', () => {
|
|
448
|
+
beforeEach('setup spy function', () => {
|
|
449
|
+
device.register = sinon.spy();
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should attempt to register', () =>
|
|
453
|
+
device.refresh().then(() => assert.called(device.register)));
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
describe('when the device is registered', () => {
|
|
457
|
+
let exampleResponse;
|
|
458
|
+
|
|
459
|
+
beforeEach('register the device', () => {
|
|
460
|
+
exampleResponse = {
|
|
461
|
+
body: {
|
|
462
|
+
exampleKey: 'example response value',
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
return device.register().then(() => {
|
|
467
|
+
device.request = sinon.stub().returns(Promise.resolve({...exampleResponse}));
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
describe('when the device is ephemeral', () => {
|
|
472
|
+
beforeEach('set device to ephemeral', () => {
|
|
473
|
+
device.config.ephemeral = true;
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('should set the ttl property to the config values', () =>
|
|
477
|
+
device
|
|
478
|
+
.refresh()
|
|
479
|
+
.then(() =>
|
|
480
|
+
assert.calledWith(
|
|
481
|
+
device.request,
|
|
482
|
+
sinon.match.hasNested('body.ttl', device.config.ephemeralDeviceTTL)
|
|
483
|
+
)
|
|
484
|
+
));
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
describe('when the refresh request is sent', () => {
|
|
488
|
+
let customHeaders;
|
|
489
|
+
let customBody;
|
|
490
|
+
|
|
491
|
+
beforeEach('configure device plugin', () => {
|
|
492
|
+
customHeaders = {
|
|
493
|
+
testHeader: 'example header value',
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
customBody = {
|
|
497
|
+
testBody: 'example body value',
|
|
498
|
+
};
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('should allow for custom header key:values', () => {
|
|
502
|
+
device.config.headers = {...customHeaders};
|
|
503
|
+
|
|
504
|
+
return device
|
|
505
|
+
.refresh()
|
|
506
|
+
.then(() =>
|
|
507
|
+
assert.calledWith(
|
|
508
|
+
device.request,
|
|
509
|
+
sinon.match.hasNested('headers.testHeader', customHeaders.testHeader)
|
|
510
|
+
)
|
|
511
|
+
);
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
it('should allow for custom body key:values', () => {
|
|
515
|
+
device.config.body = {...customBody};
|
|
516
|
+
|
|
517
|
+
return device
|
|
518
|
+
.refresh()
|
|
519
|
+
.then(() =>
|
|
520
|
+
assert.calledWith(
|
|
521
|
+
device.request,
|
|
522
|
+
sinon.match.hasNested('body.testBody', customBody.testBody)
|
|
523
|
+
)
|
|
524
|
+
);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it("should use the device's url property", () => {
|
|
528
|
+
device.config.body = {...customBody};
|
|
529
|
+
|
|
530
|
+
return device
|
|
531
|
+
.refresh()
|
|
532
|
+
.then(() => assert.calledWith(device.request, sinon.match.has('uri', device.url)));
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it('should send a PUT request', () => {
|
|
536
|
+
device.config.body = {...customBody};
|
|
537
|
+
|
|
538
|
+
return device
|
|
539
|
+
.refresh()
|
|
540
|
+
.then(() => assert.calledWith(device.request, sinon.match.has('method', 'PUT')));
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
describe('when the device is successfully refreshes', () => {
|
|
545
|
+
beforeEach('setup stubs', () => {
|
|
546
|
+
device.processRegistrationSuccess = sinon.stub();
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
it('should return a resolved promise', () => assert.isFulfilled(device.refresh()));
|
|
550
|
+
|
|
551
|
+
it("should call 'processRegistrationSuccess()'", () =>
|
|
552
|
+
device.refresh().then(() => assert.called(device.processRegistrationSuccess)));
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
describe('when the device fails to refresh', () => {
|
|
556
|
+
describe('when the device is not found', () => {
|
|
557
|
+
let request;
|
|
558
|
+
|
|
559
|
+
beforeEach('setup request stub to 404', () => {
|
|
560
|
+
request = device.request;
|
|
561
|
+
|
|
562
|
+
device.register = sinon.spy();
|
|
563
|
+
|
|
564
|
+
device.request = sinon.stub().rejects(
|
|
565
|
+
new WebexHttpError({
|
|
566
|
+
statusCode: 404,
|
|
567
|
+
options: {
|
|
568
|
+
url: device.url,
|
|
569
|
+
headers: {
|
|
570
|
+
trackingId: 'tid',
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
})
|
|
574
|
+
);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
afterEach('reset the device request', () => {
|
|
578
|
+
device.request = request;
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it('should clear the current device', () =>
|
|
582
|
+
device.refresh().then(() => assert.isUndefined(device.url)));
|
|
583
|
+
|
|
584
|
+
it('should attempt to register a new device', () =>
|
|
585
|
+
device.refresh().then(() => assert.called(device.register)));
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
describe('when the device was found', () => {
|
|
589
|
+
let request;
|
|
590
|
+
|
|
591
|
+
beforeEach('setup request stub to 503', () => {
|
|
592
|
+
request = device.request;
|
|
593
|
+
|
|
594
|
+
device.request = sinon.stub().rejects(
|
|
595
|
+
new WebexHttpError({
|
|
596
|
+
statusCode: 503,
|
|
597
|
+
options: {
|
|
598
|
+
url: device.url,
|
|
599
|
+
headers: {
|
|
600
|
+
trackingId: 'tid',
|
|
601
|
+
},
|
|
602
|
+
},
|
|
603
|
+
})
|
|
604
|
+
);
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
afterEach('resest the request method', () => {
|
|
608
|
+
device.request = request;
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it('should return a rejected promise', () => assert.isRejected(device.refresh()));
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
describe('when the device cannot register', () => {
|
|
618
|
+
beforeEach("setup 'canRegister()' stub", () => {
|
|
619
|
+
device.canRegister = sinon.stub().rejects(new Error());
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('should return a rejected promise', () => assert.isRejected(device.refresh()));
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
describe('#register()', () => {
|
|
627
|
+
describe('when the device can register', () => {
|
|
628
|
+
describe('when the device is already registered', () => {
|
|
629
|
+
beforeEach("setup 'register()' spy and register", () => {
|
|
630
|
+
device.refresh = sinon.spy();
|
|
631
|
+
|
|
632
|
+
return device.register();
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it('should attempt to refresh', () =>
|
|
636
|
+
device.register().then(() => assert.called(device.refresh)));
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
describe('when the device is not already registered', () => {
|
|
640
|
+
let exampleResponse;
|
|
641
|
+
|
|
642
|
+
beforeEach('setup stubs and scoped variables', () => {
|
|
643
|
+
exampleResponse = {
|
|
644
|
+
body: {
|
|
645
|
+
exampleKey: 'example response value',
|
|
646
|
+
},
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
device.request = sinon.stub().returns(Promise.resolve({...exampleResponse}));
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
describe('when the registration request is sent', () => {
|
|
653
|
+
let customHeaders;
|
|
654
|
+
let customBody;
|
|
655
|
+
|
|
656
|
+
beforeEach('configure device plugin', () => {
|
|
657
|
+
customHeaders = {
|
|
658
|
+
testHeader: 'example header value',
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
customBody = {
|
|
662
|
+
testBody: 'example body value',
|
|
663
|
+
};
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it('should allow for custom header key:values', () => {
|
|
667
|
+
device.config.headers = {...customHeaders};
|
|
668
|
+
|
|
669
|
+
return device
|
|
670
|
+
.register()
|
|
671
|
+
.then(() =>
|
|
672
|
+
assert.calledWith(
|
|
673
|
+
device.request,
|
|
674
|
+
sinon.match.hasNested('headers.testHeader', customHeaders.testHeader)
|
|
675
|
+
)
|
|
676
|
+
);
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('should allow for custom body key:values', () => {
|
|
680
|
+
device.config.body = {...customBody};
|
|
681
|
+
|
|
682
|
+
return device
|
|
683
|
+
.register()
|
|
684
|
+
.then(() =>
|
|
685
|
+
assert.calledWith(
|
|
686
|
+
device.request,
|
|
687
|
+
sinon.match.hasNested('body.testBody', customBody.testBody)
|
|
688
|
+
)
|
|
689
|
+
);
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
it("should use the 'wdm' service", () => {
|
|
693
|
+
device.config.body = {...customBody};
|
|
694
|
+
|
|
695
|
+
return device
|
|
696
|
+
.register()
|
|
697
|
+
.then(() => assert.calledWith(device.request, sinon.match.has('service', 'wdm')));
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
it("should use the 'devices' resource", () => {
|
|
701
|
+
device.config.body = {...customBody};
|
|
702
|
+
|
|
703
|
+
return device
|
|
704
|
+
.register()
|
|
705
|
+
.then(() =>
|
|
706
|
+
assert.calledWith(device.request, sinon.match.has('resource', 'devices'))
|
|
707
|
+
);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
it('should send a POST request', () => {
|
|
711
|
+
device.config.body = {...customBody};
|
|
712
|
+
|
|
713
|
+
return device
|
|
714
|
+
.register()
|
|
715
|
+
.then(() => assert.calledWith(device.request, sinon.match.has('method', 'POST')));
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
it('should set TTL if configured as ephemeral', () => {
|
|
719
|
+
device.config.ephemeral = true;
|
|
720
|
+
device.config.ephemeralDeviceTTL = 3600;
|
|
721
|
+
|
|
722
|
+
return device
|
|
723
|
+
.register()
|
|
724
|
+
.then(() =>
|
|
725
|
+
assert.calledWith(device.request, sinon.match.hasNested('body.ttl', 3600))
|
|
726
|
+
);
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
describe('when the device is successfully registered', () => {
|
|
731
|
+
beforeEach('setup stubs', () => {
|
|
732
|
+
device.processRegistrationSuccess = sinon.stub();
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
it('should return a resolved promise', () => assert.isFulfilled(device.register()));
|
|
736
|
+
|
|
737
|
+
it("should call 'processRegistrationSuccess()'", () =>
|
|
738
|
+
device.register().then(() => assert.called(device.processRegistrationSuccess)));
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
describe('when the device fails to register', () => {
|
|
742
|
+
beforeEach('setup request stub to 503', () => {
|
|
743
|
+
device.request = sinon.stub().rejects(
|
|
744
|
+
new WebexHttpError({
|
|
745
|
+
statusCode: 503,
|
|
746
|
+
options: {
|
|
747
|
+
url: 'http://not-a-url.com/resource',
|
|
748
|
+
headers: {
|
|
749
|
+
trackingId: 'tid',
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
})
|
|
753
|
+
);
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
it('should return a rejected promise', () => assert.isRejected(device.register()));
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
describe('when the device cannot register', () => {
|
|
762
|
+
beforeEach("setup 'canRegister()' stub", () => {
|
|
763
|
+
device.canRegister = sinon.stub().rejects(new Error());
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
it('should return a rejected promise', () => assert.isRejected(device.register()));
|
|
767
|
+
});
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
describe('#resetLogoutTimer()', () => {
|
|
771
|
+
describe('when inactivty enforcement is enabled', () => {
|
|
772
|
+
beforeEach('set inactity enforcement and reachability checked', () => {
|
|
773
|
+
device.config.enableInactivityEnforcement = true;
|
|
774
|
+
device.isReachabilityChecked = true;
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
describe('when the user is in a meeting', () => {
|
|
778
|
+
beforeEach('set user to be in a meeting', () => {
|
|
779
|
+
device.isInMeeting = true;
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
it('should not set the logout timer', () => {
|
|
783
|
+
device.resetLogoutTimer();
|
|
784
|
+
|
|
785
|
+
assert.isUndefined(device.logoutTimer);
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
describe('when the user is not in a meeting', () => {
|
|
790
|
+
beforeEach("setup the 'setLogoutTimer()' spy", () => {
|
|
791
|
+
device.setLogoutTimer = sinon.stub();
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
describe('when the user is in network', () => {
|
|
795
|
+
beforeEach('set user to be in network', () => {
|
|
796
|
+
device.isInNetwork = true;
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
it('should set the logout timer to the in-network duration', () => {
|
|
800
|
+
device.resetLogoutTimer();
|
|
801
|
+
|
|
802
|
+
assert.calledWith(device.setLogoutTimer, device.intranetInactivityCheckUrl);
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
describe('when the user is not in network', () => {
|
|
807
|
+
beforeEach('set the user to not be in network', () => {
|
|
808
|
+
device.isInNetwork = false;
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
it('should set the logout timer to the intranet duration', () => {
|
|
812
|
+
device.resetLogoutTimer();
|
|
813
|
+
|
|
814
|
+
assert.calledWith(device.setLogoutTimer, device.intranetInactivityDuration);
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
});
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
describe('#unregister()', () => {
|
|
822
|
+
describe('when the device is registered', () => {
|
|
823
|
+
beforeEach('register the device', () => device.register());
|
|
824
|
+
|
|
825
|
+
describe('when the unregistration request is sent', () => {
|
|
826
|
+
let url;
|
|
827
|
+
|
|
828
|
+
beforeEach("setup the 'request()' stub", () => {
|
|
829
|
+
device.request = sinon.stub().resolves();
|
|
830
|
+
url = device.url;
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
it("should use the device's url property", () =>
|
|
834
|
+
device
|
|
835
|
+
.unregister()
|
|
836
|
+
.then(() => assert.calledWith(device.request, sinon.match.has('uri', url))));
|
|
837
|
+
|
|
838
|
+
it('should send a DELETE request', () =>
|
|
839
|
+
device
|
|
840
|
+
.unregister()
|
|
841
|
+
.then(() => assert.calledWith(device.request, sinon.match.has('method', 'DELETE'))));
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
describe('when the device unregistration request is successful', () => {
|
|
845
|
+
it('should clear the device url', () =>
|
|
846
|
+
device.unregister().then(() => assert.isUndefined(device.url)));
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
describe('when the device unregistration request fails', () => {
|
|
850
|
+
let request;
|
|
851
|
+
|
|
852
|
+
beforeEach("setup the 'request' stub", () => {
|
|
853
|
+
request = device.request;
|
|
854
|
+
|
|
855
|
+
device.request = sinon.stub().rejects(
|
|
856
|
+
new WebexHttpError({
|
|
857
|
+
statusCode: 404,
|
|
858
|
+
options: {
|
|
859
|
+
url: device.url,
|
|
860
|
+
headers: {
|
|
861
|
+
trackingId: 'tid',
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
})
|
|
865
|
+
);
|
|
866
|
+
});
|
|
867
|
+
|
|
868
|
+
afterEach('reset the request method', () => {
|
|
869
|
+
device.request = request;
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
it('returns a rejected promise', () => assert.isRejected(device.unregister()));
|
|
873
|
+
});
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
describe('when the device is not registered', () => {
|
|
877
|
+
it('should return a resolved promise', () => assert.isFulfilled(device.unregister()));
|
|
878
|
+
});
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
describe('#waitForRegistration()', () => {
|
|
882
|
+
describe('when the device is registered', () => {
|
|
883
|
+
beforeEach('register the device', () => device.register());
|
|
884
|
+
|
|
885
|
+
it('should return a resolved promise', () =>
|
|
886
|
+
assert.isFulfilled(device.waitForRegistration()));
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
describe('when the device is not registered', () => {
|
|
890
|
+
describe('when the device registers', () => {
|
|
891
|
+
it('should return a resolved promise once registered', () =>
|
|
892
|
+
Promise.all([device.waitForRegistration(), device.register()]).then(() =>
|
|
893
|
+
assert.isTrue(device.registered)
|
|
894
|
+
));
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
describe('when the device does not register', () => {
|
|
898
|
+
it('should return a rejected promise', () =>
|
|
899
|
+
assert.isRejected(device.waitForRegistration()));
|
|
900
|
+
});
|
|
901
|
+
});
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
});
|