@webex/internal-plugin-mercury 3.0.0-beta.4 → 3.0.0-beta.400
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/README.md +15 -4
- package/dist/config.js +0 -7
- package/dist/config.js.map +1 -1
- package/dist/errors.js +0 -44
- package/dist/errors.js.map +1 -1
- package/dist/index.js +1 -20
- package/dist/index.js.map +1 -1
- package/dist/mercury.js +80 -198
- package/dist/mercury.js.map +1 -1
- package/dist/socket/index.js +0 -4
- package/dist/socket/index.js.map +1 -1
- package/dist/socket/socket-base.js +68 -143
- package/dist/socket/socket-base.js.map +1 -1
- package/dist/socket/socket.js +1 -7
- package/dist/socket/socket.js.map +1 -1
- package/dist/socket/socket.shim.js +2 -7
- package/dist/socket/socket.shim.js.map +1 -1
- package/package.json +14 -14
- package/src/config.js +2 -2
- package/src/errors.js +7 -5
- package/src/index.js +2 -2
- package/src/mercury.js +112 -98
- package/src/socket/socket-base.js +104 -72
- package/src/socket/socket.shim.js +6 -8
- package/test/integration/spec/mercury.js +49 -39
- package/test/integration/spec/sharable-mercury.js +19 -15
- package/test/integration/spec/webex.js +10 -8
- package/test/unit/spec/mercury-events.js +51 -60
- package/test/unit/spec/mercury.js +237 -157
- package/test/unit/spec/socket.js +263 -202
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
ConnectionError,
|
|
15
15
|
Forbidden,
|
|
16
16
|
NotAuthorized,
|
|
17
|
-
UnknownResponse
|
|
17
|
+
UnknownResponse,
|
|
18
18
|
// NotFound
|
|
19
19
|
} from '../errors';
|
|
20
20
|
|
|
@@ -30,6 +30,7 @@ export default class Socket extends EventEmitter {
|
|
|
30
30
|
*/
|
|
31
31
|
constructor() {
|
|
32
32
|
super();
|
|
33
|
+
this._domain = 'unknown-domain';
|
|
33
34
|
this.onmessage = this.onmessage.bind(this);
|
|
34
35
|
this.onclose = this.onclose.bind(this);
|
|
35
36
|
}
|
|
@@ -88,7 +89,9 @@ export default class Socket extends EventEmitter {
|
|
|
88
89
|
* @returns {WebSocket}
|
|
89
90
|
*/
|
|
90
91
|
static getWebSocketConstructor() {
|
|
91
|
-
throw new Error(
|
|
92
|
+
throw new Error(
|
|
93
|
+
'Socket.getWebSocketConstructor() must be implemented in an environmentally appropriate way'
|
|
94
|
+
);
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
/**
|
|
@@ -109,10 +112,10 @@ export default class Socket extends EventEmitter {
|
|
|
109
112
|
return;
|
|
110
113
|
}
|
|
111
114
|
// logger is defined once open is called
|
|
112
|
-
this.logger.info(
|
|
115
|
+
this.logger.info(`socket,${this._domain}: closing`);
|
|
113
116
|
|
|
114
117
|
if (socket.readyState === 2 || socket.readyState === 3) {
|
|
115
|
-
this.logger.info(
|
|
118
|
+
this.logger.info(`socket,${this._domain}: already closed`);
|
|
116
119
|
resolve();
|
|
117
120
|
|
|
118
121
|
return;
|
|
@@ -127,24 +130,25 @@ export default class Socket extends EventEmitter {
|
|
|
127
130
|
|
|
128
131
|
options = defaults(options, {
|
|
129
132
|
code: 1000,
|
|
130
|
-
reason: 'Done'
|
|
133
|
+
reason: 'Done',
|
|
131
134
|
});
|
|
132
135
|
|
|
133
136
|
const closeTimer = safeSetTimeout(() => {
|
|
134
137
|
try {
|
|
135
|
-
this.logger.info(
|
|
136
|
-
resolve(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
this.logger.info(`socket,${this._domain}: no close event received, forcing closure`);
|
|
139
|
+
resolve(
|
|
140
|
+
this.onclose({
|
|
141
|
+
code: 1000,
|
|
142
|
+
reason: 'Done (forced)',
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
this.logger.warn(`socket,${this._domain}: force-close failed`, error);
|
|
143
147
|
}
|
|
144
148
|
}, this.forceCloseDelay);
|
|
145
149
|
|
|
146
150
|
socket.onclose = (event) => {
|
|
147
|
-
this.logger.info(
|
|
151
|
+
this.logger.info(`socket,${this._domain}: close event fired`, event.code, event.reason);
|
|
148
152
|
clearTimeout(closeTimer);
|
|
149
153
|
this.onclose(event);
|
|
150
154
|
resolve(event);
|
|
@@ -168,6 +172,12 @@ export default class Socket extends EventEmitter {
|
|
|
168
172
|
* @returns {Promise}
|
|
169
173
|
*/
|
|
170
174
|
open(url, options) {
|
|
175
|
+
try {
|
|
176
|
+
this._domain = new URL(url).hostname;
|
|
177
|
+
} catch {
|
|
178
|
+
this._domain = url;
|
|
179
|
+
}
|
|
180
|
+
|
|
171
181
|
return new Promise((resolve, reject) => {
|
|
172
182
|
/* eslint complexity: [0] */
|
|
173
183
|
if (!url) {
|
|
@@ -184,25 +194,21 @@ export default class Socket extends EventEmitter {
|
|
|
184
194
|
|
|
185
195
|
options = options || {};
|
|
186
196
|
|
|
187
|
-
checkRequired(
|
|
188
|
-
'forceCloseDelay',
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
'token',
|
|
192
|
-
'trackingId',
|
|
193
|
-
'logger'
|
|
194
|
-
], options);
|
|
197
|
+
checkRequired(
|
|
198
|
+
['forceCloseDelay', 'pingInterval', 'pongTimeout', 'token', 'trackingId', 'logger'],
|
|
199
|
+
options
|
|
200
|
+
);
|
|
195
201
|
|
|
196
202
|
Object.keys(options).forEach((key) => {
|
|
197
203
|
Reflect.defineProperty(this, key, {
|
|
198
204
|
enumerable: false,
|
|
199
|
-
value: options[key]
|
|
205
|
+
value: options[key],
|
|
200
206
|
});
|
|
201
207
|
});
|
|
202
208
|
|
|
203
209
|
const WebSocket = Socket.getWebSocketConstructor();
|
|
204
210
|
|
|
205
|
-
this.logger.info(
|
|
211
|
+
this.logger.info(`socket,${this._domain}: creating WebSocket`);
|
|
206
212
|
const socket = new WebSocket(url, [], options);
|
|
207
213
|
|
|
208
214
|
socket.binaryType = 'arraybuffer';
|
|
@@ -210,13 +216,13 @@ export default class Socket extends EventEmitter {
|
|
|
210
216
|
|
|
211
217
|
socket.onclose = (event) => {
|
|
212
218
|
event = this._fixCloseCode(event);
|
|
213
|
-
this.logger.info(
|
|
219
|
+
this.logger.info(`socket,${this._domain}: closed before open`, event.code, event.reason);
|
|
214
220
|
switch (event.code) {
|
|
215
221
|
case 1005:
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
222
|
+
// IE 11 doesn't seem to allow 4XXX codes, so if we get a 1005, assume
|
|
223
|
+
// it's a bad websocket url. That'll trigger a device refresh; if it
|
|
224
|
+
// turns out we had a bad token, the device refresh should 401 and
|
|
225
|
+
// trigger a token refresh.
|
|
220
226
|
return reject(new UnknownResponse(event));
|
|
221
227
|
case 4400:
|
|
222
228
|
return reject(new BadRequest(event));
|
|
@@ -224,18 +230,18 @@ export default class Socket extends EventEmitter {
|
|
|
224
230
|
return reject(new NotAuthorized(event));
|
|
225
231
|
case 4403:
|
|
226
232
|
return reject(new Forbidden(event));
|
|
227
|
-
|
|
228
|
-
|
|
233
|
+
// case 4404:
|
|
234
|
+
// return reject(new NotFound(event));
|
|
229
235
|
default:
|
|
230
236
|
return reject(new ConnectionError(event));
|
|
231
237
|
}
|
|
232
238
|
};
|
|
233
239
|
|
|
234
240
|
socket.onopen = () => {
|
|
235
|
-
this.logger.info(
|
|
241
|
+
this.logger.info(`socket,${this._domain}: connected`);
|
|
236
242
|
this._authorize()
|
|
237
243
|
.then(() => {
|
|
238
|
-
this.logger.info(
|
|
244
|
+
this.logger.info(`socket,${this._domain}: authorized`);
|
|
239
245
|
socket.onclose = this.onclose;
|
|
240
246
|
resolve();
|
|
241
247
|
})
|
|
@@ -243,11 +249,11 @@ export default class Socket extends EventEmitter {
|
|
|
243
249
|
};
|
|
244
250
|
|
|
245
251
|
socket.onerror = (event) => {
|
|
246
|
-
this.logger.warn(
|
|
252
|
+
this.logger.warn(`socket,${this._domain}: error event fired`, event);
|
|
247
253
|
};
|
|
248
254
|
|
|
249
255
|
sockets.set(this, socket);
|
|
250
|
-
this.logger.info(
|
|
256
|
+
this.logger.info(`socket,${this._domain}: waiting for server`);
|
|
251
257
|
});
|
|
252
258
|
}
|
|
253
259
|
|
|
@@ -257,7 +263,7 @@ export default class Socket extends EventEmitter {
|
|
|
257
263
|
* @returns {undefined}
|
|
258
264
|
*/
|
|
259
265
|
onclose(event) {
|
|
260
|
-
this.logger.info(
|
|
266
|
+
this.logger.info(`socket,${this._domain}: closed`, event.code, event.reason);
|
|
261
267
|
clearTimeout(this.pongTimer);
|
|
262
268
|
clearTimeout(this.pingTimer);
|
|
263
269
|
|
|
@@ -279,9 +285,11 @@ export default class Socket extends EventEmitter {
|
|
|
279
285
|
const data = JSON.parse(event.data);
|
|
280
286
|
const sequenceNumber = parseInt(data.sequenceNumber, 10);
|
|
281
287
|
|
|
282
|
-
this.logger.debug(
|
|
288
|
+
this.logger.debug(`socket,${this._domain}: sequence number: `, sequenceNumber);
|
|
283
289
|
if (this.expectedSequenceNumber && sequenceNumber !== this.expectedSequenceNumber) {
|
|
284
|
-
this.logger.debug(
|
|
290
|
+
this.logger.debug(
|
|
291
|
+
`socket,${this._domain}: sequence number mismatch indicates lost mercury message. expected: ${this.expectedSequenceNumber}, actual: ${sequenceNumber}`
|
|
292
|
+
);
|
|
285
293
|
this.emit('sequence-mismatch', sequenceNumber, this.expectedSequenceNumber);
|
|
286
294
|
}
|
|
287
295
|
this.expectedSequenceNumber = sequenceNumber + 1;
|
|
@@ -294,17 +302,15 @@ export default class Socket extends EventEmitter {
|
|
|
294
302
|
this._acknowledge(processedEvent);
|
|
295
303
|
if (data.type === 'pong') {
|
|
296
304
|
this.emit('pong', processedEvent);
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
305
|
+
} else {
|
|
299
306
|
this.emit('message', processedEvent);
|
|
300
307
|
}
|
|
301
|
-
}
|
|
302
|
-
catch (error) {
|
|
308
|
+
} catch (error) {
|
|
303
309
|
// The above code should only be able to throw if we receive an unparsable
|
|
304
310
|
// message from Mercury. At this time, the only action we have is to
|
|
305
311
|
// ignore it and move on.
|
|
306
312
|
/* istanbul ignore next */
|
|
307
|
-
this.logger.warn(
|
|
313
|
+
this.logger.warn(`socket,${this._domain}: error while receiving WebSocket message`, error);
|
|
308
314
|
}
|
|
309
315
|
}
|
|
310
316
|
|
|
@@ -347,7 +353,7 @@ export default class Socket extends EventEmitter {
|
|
|
347
353
|
|
|
348
354
|
return this.send({
|
|
349
355
|
messageId: event.data.id,
|
|
350
|
-
type: 'ack'
|
|
356
|
+
type: 'ack',
|
|
351
357
|
});
|
|
352
358
|
}
|
|
353
359
|
|
|
@@ -358,19 +364,23 @@ export default class Socket extends EventEmitter {
|
|
|
358
364
|
*/
|
|
359
365
|
_authorize() {
|
|
360
366
|
return new Promise((resolve) => {
|
|
361
|
-
this.logger.info(
|
|
367
|
+
this.logger.info(`socket,${this._domain}: authorizing`);
|
|
362
368
|
this.send({
|
|
363
369
|
id: uuid.v4(),
|
|
364
370
|
type: 'authorization',
|
|
365
371
|
data: {
|
|
366
|
-
token: this.token
|
|
372
|
+
token: this.token,
|
|
367
373
|
},
|
|
368
374
|
trackingId: this.trackingId,
|
|
369
|
-
logLevelToken: this.logLevelToken
|
|
375
|
+
logLevelToken: this.logLevelToken,
|
|
370
376
|
});
|
|
371
377
|
|
|
372
378
|
const waitForBufferState = (event) => {
|
|
373
|
-
if (
|
|
379
|
+
if (
|
|
380
|
+
!event.data.type &&
|
|
381
|
+
(event.data.data.eventType === 'mercury.buffer_state' ||
|
|
382
|
+
event.data.data.eventType === 'mercury.registration_status')
|
|
383
|
+
) {
|
|
374
384
|
this.removeListener('message', waitForBufferState);
|
|
375
385
|
this._ping();
|
|
376
386
|
resolve();
|
|
@@ -392,12 +402,18 @@ export default class Socket extends EventEmitter {
|
|
|
392
402
|
if (event.code === 1005 && event.reason) {
|
|
393
403
|
switch (event.reason.toLowerCase()) {
|
|
394
404
|
case 'replaced':
|
|
395
|
-
this.logger.info(
|
|
405
|
+
this.logger.info(
|
|
406
|
+
`socket,${this._domain}: fixing CloseEvent code for reason: `,
|
|
407
|
+
event.reason
|
|
408
|
+
);
|
|
396
409
|
event.code = 4000;
|
|
397
410
|
break;
|
|
398
411
|
case 'authentication failed':
|
|
399
412
|
case 'authentication did not happen within the timeout window of 30000 seconds.':
|
|
400
|
-
this.logger.info(
|
|
413
|
+
this.logger.info(
|
|
414
|
+
`socket,${this._domain}: fixing CloseEvent code for reason: `,
|
|
415
|
+
event.reason
|
|
416
|
+
);
|
|
401
417
|
event.code = 1008;
|
|
402
418
|
break;
|
|
403
419
|
default:
|
|
@@ -417,40 +433,44 @@ export default class Socket extends EventEmitter {
|
|
|
417
433
|
_ping(id) {
|
|
418
434
|
const confirmPongId = (event) => {
|
|
419
435
|
try {
|
|
420
|
-
this.logger.debug(
|
|
436
|
+
this.logger.debug(`socket,${this._domain}: pong`, event.data.id);
|
|
421
437
|
if (event.data && event.data.id !== id) {
|
|
422
|
-
this.logger.info(
|
|
423
|
-
|
|
438
|
+
this.logger.info(
|
|
439
|
+
`socket,${this._domain}: received pong for wrong ping id, closing socket`
|
|
440
|
+
);
|
|
441
|
+
this.logger.debug(`socket,${this._domain}: expected`, id, 'received', event.data.id);
|
|
424
442
|
this.close({
|
|
425
443
|
code: 1000,
|
|
426
|
-
reason: 'Pong mismatch'
|
|
444
|
+
reason: 'Pong mismatch',
|
|
427
445
|
});
|
|
428
446
|
}
|
|
429
|
-
}
|
|
430
|
-
catch (error) {
|
|
447
|
+
} catch (error) {
|
|
431
448
|
// This try/catch block was added as a debugging step; to the best of my
|
|
432
449
|
// knowledge, the above can never throw.
|
|
433
450
|
/* istanbul ignore next */
|
|
434
|
-
this.logger.error(
|
|
451
|
+
this.logger.error(`socket,${this._domain}: error occurred in confirmPongId`, error);
|
|
435
452
|
}
|
|
436
453
|
};
|
|
437
454
|
|
|
438
455
|
const onPongNotReceived = () => {
|
|
439
456
|
try {
|
|
440
|
-
this.logger.info(
|
|
457
|
+
this.logger.info(
|
|
458
|
+
`socket,${this._domain}: pong not receive in expected period, closing socket`
|
|
459
|
+
);
|
|
441
460
|
this.close({
|
|
442
461
|
code: 1000,
|
|
443
|
-
reason: 'Pong not received'
|
|
444
|
-
})
|
|
445
|
-
.
|
|
446
|
-
this.
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
462
|
+
reason: 'Pong not received',
|
|
463
|
+
}).catch((reason) => {
|
|
464
|
+
this.logger.warn(
|
|
465
|
+
`socket,${this._domain}: failed to close socket after missed pong`,
|
|
466
|
+
reason
|
|
467
|
+
);
|
|
468
|
+
});
|
|
469
|
+
} catch (error) {
|
|
450
470
|
// This try/catch block was added as a debugging step; to the best of my
|
|
451
471
|
// knowledge, the above can never throw.
|
|
452
472
|
/* istanbul ignore next */
|
|
453
|
-
this.logger.error(
|
|
473
|
+
this.logger.error(`socket,${this._domain}: error occurred in onPongNotReceived`, error);
|
|
454
474
|
}
|
|
455
475
|
};
|
|
456
476
|
|
|
@@ -458,25 +478,37 @@ export default class Socket extends EventEmitter {
|
|
|
458
478
|
try {
|
|
459
479
|
clearTimeout(this.pongTimer);
|
|
460
480
|
this.pingTimer = safeSetTimeout(() => this._ping(), this.pingInterval);
|
|
461
|
-
}
|
|
462
|
-
catch (error) {
|
|
481
|
+
} catch (error) {
|
|
463
482
|
// This try/catch block was added as a debugging step; to the best of my
|
|
464
483
|
// knowledge, the above can never throw.
|
|
465
484
|
/* istanbul ignore next */
|
|
466
|
-
this.logger.error(
|
|
485
|
+
this.logger.error(
|
|
486
|
+
`socket,${this._domain}: error occurred in scheduleNextPingAndCancelPongTimer`,
|
|
487
|
+
error
|
|
488
|
+
);
|
|
467
489
|
}
|
|
468
490
|
};
|
|
469
491
|
|
|
492
|
+
const calculateLatency = (pingTimestamp) => {
|
|
493
|
+
const now = performance.now();
|
|
494
|
+
const latency = now - pingTimestamp;
|
|
495
|
+
|
|
496
|
+
this.logger.debug(`socket,${this._domain}: latency: `, latency);
|
|
497
|
+
this.emit('ping-pong-latency', latency);
|
|
498
|
+
};
|
|
499
|
+
|
|
470
500
|
id = id || uuid.v4();
|
|
501
|
+
const pingTimestamp = performance.now();
|
|
502
|
+
|
|
471
503
|
this.pongTimer = safeSetTimeout(onPongNotReceived, this.pongTimeout);
|
|
472
504
|
this.once('pong', scheduleNextPingAndCancelPongTimer);
|
|
473
505
|
this.once('pong', confirmPongId);
|
|
474
|
-
|
|
475
|
-
this.logger.debug(`socket: ping ${id}`);
|
|
506
|
+
this.once('pong', () => calculateLatency(pingTimestamp));
|
|
507
|
+
this.logger.debug(`socket,${this._domain}: ping ${id}`);
|
|
476
508
|
|
|
477
509
|
return this.send({
|
|
478
510
|
id,
|
|
479
|
-
type: 'ping'
|
|
511
|
+
type: 'ping',
|
|
480
512
|
});
|
|
481
513
|
}
|
|
482
514
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
2
|
+
|
|
1
3
|
/*!
|
|
2
4
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
5
|
*/
|
|
@@ -12,18 +14,14 @@ Socket.getWebSocketConstructor = function getWebSocketConstructor() {
|
|
|
12
14
|
|
|
13
15
|
if (typeof WebSocket !== 'undefined') {
|
|
14
16
|
ws = WebSocket;
|
|
15
|
-
}
|
|
16
|
-
else if (typeof MozWebSocket !== 'undefined') {
|
|
17
|
+
} else if (typeof MozWebSocket !== 'undefined') {
|
|
17
18
|
// eslint-disable-next-line no-undef
|
|
18
19
|
ws = MozWebSocket;
|
|
19
|
-
}
|
|
20
|
-
else if (typeof global !== 'undefined') {
|
|
20
|
+
} else if (typeof global !== 'undefined') {
|
|
21
21
|
ws = global.WebSocket || global.MozWebSocket;
|
|
22
|
-
}
|
|
23
|
-
else if (typeof window !== 'undefined') {
|
|
22
|
+
} else if (typeof window !== 'undefined') {
|
|
24
23
|
ws = window.WebSocket || window.MozWebSocket;
|
|
25
|
-
}
|
|
26
|
-
else if (typeof self !== 'undefined') {
|
|
24
|
+
} else if (typeof self !== 'undefined') {
|
|
27
25
|
ws = self.WebSocket || self.MozWebSocket;
|
|
28
26
|
}
|
|
29
27
|
|
|
@@ -16,34 +16,37 @@ describe('plugin-mercury', function () {
|
|
|
16
16
|
describe('Mercury', () => {
|
|
17
17
|
let webex;
|
|
18
18
|
|
|
19
|
-
beforeEach(() =>
|
|
20
|
-
.then((users) => {
|
|
19
|
+
beforeEach(() =>
|
|
20
|
+
testUsers.create({count: 1}).then((users) => {
|
|
21
21
|
webex = new WebexCore({
|
|
22
22
|
credentials: {
|
|
23
|
-
supertoken: users[0].token
|
|
23
|
+
supertoken: users[0].token,
|
|
24
24
|
},
|
|
25
25
|
config: {
|
|
26
26
|
credentials: {
|
|
27
|
-
refreshCallback
|
|
28
|
-
}
|
|
29
|
-
}
|
|
27
|
+
refreshCallback,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
30
|
});
|
|
31
|
-
})
|
|
31
|
+
})
|
|
32
|
+
);
|
|
32
33
|
|
|
33
34
|
afterEach(() => webex && webex.internal.mercury.disconnect());
|
|
34
35
|
|
|
35
36
|
describe('#connect()', () => {
|
|
36
37
|
it('connects to mercury', () => webex.internal.mercury.connect());
|
|
37
38
|
|
|
38
|
-
it('refreshes the access token when a 4401 is received', () =>
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
it('refreshes the access token when a 4401 is received', () =>
|
|
40
|
+
webex.internal.device
|
|
41
|
+
.register()
|
|
42
|
+
.then(() => {
|
|
43
|
+
// eslint-disable-next-line camelcase
|
|
44
|
+
webex.credentials.supertoken.access_token = 'fake token';
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
return webex.internal.mercury.connect();
|
|
47
|
+
})
|
|
48
|
+
// eslint-disable-next-line camelcase
|
|
49
|
+
.then(() => assert.notEqual(webex.credentials.supertoken.access_token, 'fake token')));
|
|
47
50
|
|
|
48
51
|
// This doesn't work as designed yet. The only way to get a 4404 is to try
|
|
49
52
|
// to connect to someone else's valid registration; the intent was to get
|
|
@@ -70,26 +73,34 @@ describe('plugin-mercury', function () {
|
|
|
70
73
|
});
|
|
71
74
|
|
|
72
75
|
describe('when web-high-availability is enabled', () => {
|
|
73
|
-
flaky(it, process.env.SKIP_FLAKY_TESTS)(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
76
|
+
flaky(it, process.env.SKIP_FLAKY_TESTS)(
|
|
77
|
+
'connects to mercury using service catalog url',
|
|
78
|
+
() => {
|
|
79
|
+
let defaultWebSocketUrl;
|
|
80
|
+
|
|
81
|
+
// we need to ensure the feature is set for user before "registering"
|
|
82
|
+
// the device
|
|
83
|
+
return (
|
|
84
|
+
webex.internal.device
|
|
85
|
+
.register()
|
|
86
|
+
.then(() =>
|
|
87
|
+
webex.internal.feature.setFeature('developer', 'web-high-availability', true)
|
|
88
|
+
)
|
|
89
|
+
.then(() => webex.internal.device.unregister())
|
|
90
|
+
// start the test flow the device list
|
|
91
|
+
.then(() => webex.internal.device.register())
|
|
92
|
+
.then(() => {
|
|
93
|
+
defaultWebSocketUrl = webex.internal.device.webSocketUrl;
|
|
94
|
+
})
|
|
95
|
+
.then(() => webex.internal.mercury.connect())
|
|
96
|
+
.then(() => webex.internal.device.getWebSocketUrl())
|
|
97
|
+
.then((wsUrl) => {
|
|
98
|
+
assert.notEqual(defaultWebSocketUrl, webex.internal.mercury.socket.url);
|
|
99
|
+
assert.include(webex.internal.mercury.socket.url, wsUrl);
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
);
|
|
93
104
|
});
|
|
94
105
|
});
|
|
95
106
|
|
|
@@ -98,10 +109,9 @@ describe('plugin-mercury', function () {
|
|
|
98
109
|
|
|
99
110
|
webex.internal.mercury.on('event:mercury.buffer_state', spy);
|
|
100
111
|
|
|
101
|
-
return webex.internal.mercury.connect()
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
});
|
|
112
|
+
return webex.internal.mercury.connect().then(() => {
|
|
113
|
+
assert.calledOnce(spy);
|
|
114
|
+
});
|
|
105
115
|
});
|
|
106
116
|
});
|
|
107
117
|
});
|
|
@@ -14,17 +14,19 @@ describe('plugin-mercury', function () {
|
|
|
14
14
|
describe('Sharable Mercury', () => {
|
|
15
15
|
let webex;
|
|
16
16
|
|
|
17
|
-
beforeEach(() =>
|
|
18
|
-
.then((users) => {
|
|
17
|
+
beforeEach(() =>
|
|
18
|
+
testUsers.create({count: 1}).then((users) => {
|
|
19
19
|
webex = new WebexCore({
|
|
20
20
|
credentials: {
|
|
21
|
-
supertoken: users[0].token
|
|
22
|
-
}
|
|
21
|
+
supertoken: users[0].token,
|
|
22
|
+
},
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
return webex.internal.device
|
|
25
|
+
return webex.internal.device
|
|
26
|
+
.register()
|
|
26
27
|
.then(() => webex.internal.feature.setFeature('developer', 'web-shared-mercury', true));
|
|
27
|
-
})
|
|
28
|
+
})
|
|
29
|
+
);
|
|
28
30
|
|
|
29
31
|
afterEach(() => webex && webex.internal.mercury.disconnect());
|
|
30
32
|
|
|
@@ -39,17 +41,19 @@ describe('plugin-mercury', function () {
|
|
|
39
41
|
webex.internal.mercury.on('event:mercury.buffer_state', spy1);
|
|
40
42
|
webex.internal.mercury.on('event:mercury.registration_status', spy2);
|
|
41
43
|
|
|
42
|
-
return webex.internal.mercury.connect()
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const {data} = spy2.args[0][0];
|
|
44
|
+
return webex.internal.mercury.connect().then(() => {
|
|
45
|
+
assert.notCalled(spy1);
|
|
46
|
+
assert.calledOnce(spy2);
|
|
47
|
+
const {data} = spy2.args[0][0];
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
assert.property(data, 'bufferState');
|
|
50
|
+
assert.property(data, 'localClusterServiceUrls');
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
assert.deepEqual(
|
|
53
|
+
webex.internal.mercury.localClusterServiceUrls,
|
|
54
|
+
data.localClusterServiceUrls
|
|
55
|
+
);
|
|
56
|
+
});
|
|
53
57
|
});
|
|
54
58
|
});
|
|
55
59
|
});
|
|
@@ -14,29 +14,31 @@ describe('plugin-mercury', function () {
|
|
|
14
14
|
|
|
15
15
|
let webex;
|
|
16
16
|
|
|
17
|
-
beforeEach('create users', () =>
|
|
18
|
-
.then(async (users) => {
|
|
17
|
+
beforeEach('create users', () =>
|
|
18
|
+
testUsers.create({count: 1}).then(async (users) => {
|
|
19
19
|
// Pause for 5 seconds for CI
|
|
20
20
|
await new Promise((done) => setTimeout(done, 5000));
|
|
21
21
|
|
|
22
22
|
webex = new WebexCore({
|
|
23
23
|
credentials: {
|
|
24
|
-
supertoken: users[0].token
|
|
25
|
-
}
|
|
24
|
+
supertoken: users[0].token,
|
|
25
|
+
},
|
|
26
26
|
});
|
|
27
27
|
sinon.spy(webex.internal.mercury, 'disconnect');
|
|
28
28
|
sinon.spy(webex.internal.device, 'unregister');
|
|
29
29
|
|
|
30
30
|
return webex.internal.mercury.connect();
|
|
31
|
-
})
|
|
31
|
+
})
|
|
32
|
+
);
|
|
32
33
|
|
|
33
34
|
describe('onBeforeLogout()', () => {
|
|
34
|
-
it('disconnects the web socket', () =>
|
|
35
|
-
.then(() => {
|
|
35
|
+
it('disconnects the web socket', () => {
|
|
36
|
+
webex.logout({noRedirect: true}).then(() => {
|
|
36
37
|
assert.called(webex.internal.mercury.disconnect);
|
|
37
38
|
assert.isFalse(webex.internal.mercury.connected);
|
|
38
39
|
assert.called(webex.internal.device.unregister);
|
|
39
40
|
assert.isFalse(webex.internal.device.registered);
|
|
40
|
-
})
|
|
41
|
+
});
|
|
42
|
+
});
|
|
41
43
|
});
|
|
42
44
|
});
|