@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
|
@@ -11,7 +11,7 @@ import Mercury, {
|
|
|
11
11
|
// NotFound,
|
|
12
12
|
config as mercuryConfig,
|
|
13
13
|
ConnectionError,
|
|
14
|
-
Socket
|
|
14
|
+
Socket,
|
|
15
15
|
} from '@webex/internal-plugin-mercury';
|
|
16
16
|
import sinon from 'sinon';
|
|
17
17
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
@@ -24,23 +24,19 @@ import promiseTick from '../lib/promise-tick';
|
|
|
24
24
|
|
|
25
25
|
describe('plugin-mercury', () => {
|
|
26
26
|
describe('Mercury', () => {
|
|
27
|
-
let clock,
|
|
28
|
-
mercury,
|
|
29
|
-
mockWebSocket,
|
|
30
|
-
socketOpenStub,
|
|
31
|
-
webex;
|
|
27
|
+
let clock, mercury, mockWebSocket, socketOpenStub, webex;
|
|
32
28
|
|
|
33
29
|
const statusStartTypingMessage = JSON.stringify({
|
|
34
30
|
id: uuid.v4(),
|
|
35
31
|
data: {
|
|
36
32
|
eventType: 'status.start_typing',
|
|
37
33
|
actor: {
|
|
38
|
-
id: 'actorId'
|
|
34
|
+
id: 'actorId',
|
|
39
35
|
},
|
|
40
|
-
conversationId: uuid.v4()
|
|
36
|
+
conversationId: uuid.v4(),
|
|
41
37
|
},
|
|
42
38
|
timestamp: Date.now(),
|
|
43
|
-
trackingId: `suffix_${uuid.v4()}_${Date.now()}
|
|
39
|
+
trackingId: `suffix_${uuid.v4()}_${Date.now()}`,
|
|
44
40
|
});
|
|
45
41
|
|
|
46
42
|
beforeEach(() => {
|
|
@@ -54,27 +50,31 @@ describe('plugin-mercury', () => {
|
|
|
54
50
|
beforeEach(() => {
|
|
55
51
|
webex = new MockWebex({
|
|
56
52
|
children: {
|
|
57
|
-
mercury: Mercury
|
|
58
|
-
}
|
|
53
|
+
mercury: Mercury,
|
|
54
|
+
},
|
|
59
55
|
});
|
|
60
56
|
webex.credentials = {
|
|
61
57
|
refresh: sinon.stub().returns(Promise.resolve()),
|
|
62
|
-
getUserToken: sinon.stub().returns(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
getUserToken: sinon.stub().returns(
|
|
59
|
+
Promise.resolve({
|
|
60
|
+
toString() {
|
|
61
|
+
return 'Bearer FAKE';
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
),
|
|
67
65
|
};
|
|
68
66
|
webex.internal.device = {
|
|
69
67
|
register: sinon.stub().returns(Promise.resolve()),
|
|
70
68
|
refresh: sinon.stub().returns(Promise.resolve()),
|
|
71
69
|
webSocketUrl: 'ws://example.com',
|
|
72
70
|
getWebSocketUrl: sinon.stub().returns(Promise.resolve('ws://example-2.com')),
|
|
73
|
-
useServiceCatalogUrl: sinon
|
|
71
|
+
useServiceCatalogUrl: sinon
|
|
72
|
+
.stub()
|
|
73
|
+
.returns(Promise.resolve('https://service-catalog-url.com')),
|
|
74
74
|
};
|
|
75
75
|
webex.internal.services = {
|
|
76
76
|
convertUrlToPriorityHostUrl: sinon.stub().returns(Promise.resolve('ws://example-2.com')),
|
|
77
|
-
markFailedUrl: sinon.stub().returns(Promise.resolve())
|
|
77
|
+
markFailedUrl: sinon.stub().returns(Promise.resolve()),
|
|
78
78
|
};
|
|
79
79
|
webex.internal.metrics.submitClientMetrics = sinon.stub();
|
|
80
80
|
webex.trackingId = 'fakeTrackingId';
|
|
@@ -132,10 +132,9 @@ describe('plugin-mercury', () => {
|
|
|
132
132
|
|
|
133
133
|
mockWebSocket.open();
|
|
134
134
|
|
|
135
|
-
return promise
|
|
136
|
-
.
|
|
137
|
-
|
|
138
|
-
});
|
|
135
|
+
return promise.then(() => {
|
|
136
|
+
assert.calledOnce(webex.internal.device.register);
|
|
137
|
+
});
|
|
139
138
|
});
|
|
140
139
|
|
|
141
140
|
it('connects to Mercury using default url', () => {
|
|
@@ -145,18 +144,16 @@ describe('plugin-mercury', () => {
|
|
|
145
144
|
assert.isTrue(mercury.connecting, 'Mercury is connecting');
|
|
146
145
|
mockWebSocket.open();
|
|
147
146
|
|
|
148
|
-
return promise
|
|
149
|
-
.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
});
|
|
147
|
+
return promise.then(() => {
|
|
148
|
+
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
149
|
+
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
150
|
+
assert.calledWith(socketOpenStub, sinon.match(/ws:\/\/example.com/), sinon.match.any);
|
|
151
|
+
});
|
|
154
152
|
});
|
|
155
153
|
|
|
156
154
|
describe('when `maxRetries` is set', () => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
mercury.config.maxRetries = 2;
|
|
155
|
+
|
|
156
|
+
const check = () => {
|
|
160
157
|
socketOpenStub.restore();
|
|
161
158
|
socketOpenStub = sinon.stub(Socket.prototype, 'open');
|
|
162
159
|
socketOpenStub.returns(Promise.reject(new ConnectionError()));
|
|
@@ -184,12 +181,42 @@ describe('plugin-mercury', () => {
|
|
|
184
181
|
.then(() => {
|
|
185
182
|
assert.calledThrice(Socket.prototype.open);
|
|
186
183
|
clock.tick(5 * mercury.config.backoffTimeReset);
|
|
187
|
-
|
|
188
184
|
return assert.isRejected(promise);
|
|
189
185
|
})
|
|
190
186
|
.then(() => {
|
|
191
187
|
assert.calledThrice(Socket.prototype.open);
|
|
192
188
|
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// skipping due to apparent bug with lolex in all browsers but Chrome.
|
|
192
|
+
// if initial retries is zero and mercury has never connected max retries is used
|
|
193
|
+
skipInBrowser(it)('fails after `maxRetries` attempts', () => {
|
|
194
|
+
mercury.config.maxRetries = 2;
|
|
195
|
+
mercury.config.initialConnectionMaxRetries = 0;
|
|
196
|
+
|
|
197
|
+
return check();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// initial retries is non-zero so takes precedence over maxRetries when mercury has never connected
|
|
201
|
+
skipInBrowser(it)('fails after `initialConnectionMaxRetries` attempts', () => {
|
|
202
|
+
mercury.config.maxRetries = 0;
|
|
203
|
+
mercury.config.initialConnectionMaxRetries = 2;
|
|
204
|
+
return check();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// initial retries is non-zero so takes precedence over maxRetries when mercury has never connected
|
|
208
|
+
skipInBrowser(it)('fails after `initialConnectionMaxRetries` attempts', () => {
|
|
209
|
+
mercury.config.initialConnectionMaxRetries = 2;
|
|
210
|
+
mercury.config.maxRetries = 5;
|
|
211
|
+
return check();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// when mercury has connected maxRetries is used and the initialConnectionMaxRetries is ignored
|
|
215
|
+
skipInBrowser(it)('fails after `initialConnectionMaxRetries` attempts', () => {
|
|
216
|
+
mercury.config.initialConnectionMaxRetries = 5;
|
|
217
|
+
mercury.config.maxRetries = 2;
|
|
218
|
+
mercury.hasEverConnected = true;
|
|
219
|
+
return check();
|
|
193
220
|
});
|
|
194
221
|
});
|
|
195
222
|
|
|
@@ -198,15 +225,14 @@ describe('plugin-mercury', () => {
|
|
|
198
225
|
mercury.connect(),
|
|
199
226
|
mercury.connect(),
|
|
200
227
|
mercury.connect(),
|
|
201
|
-
mercury.connect()
|
|
228
|
+
mercury.connect(),
|
|
202
229
|
]);
|
|
203
230
|
|
|
204
231
|
mockWebSocket.open();
|
|
205
232
|
|
|
206
|
-
return promise
|
|
207
|
-
.
|
|
208
|
-
|
|
209
|
-
});
|
|
233
|
+
return promise.then(() => {
|
|
234
|
+
assert.calledOnce(Socket.prototype.open);
|
|
235
|
+
});
|
|
210
236
|
});
|
|
211
237
|
|
|
212
238
|
// skipping due to apparent bug with lolex in all browsers but Chrome.
|
|
@@ -261,7 +287,9 @@ describe('plugin-mercury', () => {
|
|
|
261
287
|
it('fails permanently', () => {
|
|
262
288
|
clock.uninstall();
|
|
263
289
|
socketOpenStub.restore();
|
|
264
|
-
socketOpenStub = sinon
|
|
290
|
+
socketOpenStub = sinon
|
|
291
|
+
.stub(Socket.prototype, 'open')
|
|
292
|
+
.returns(Promise.reject(new BadRequest({code: 4400})));
|
|
265
293
|
|
|
266
294
|
return assert.isRejected(mercury.connect());
|
|
267
295
|
});
|
|
@@ -276,18 +304,16 @@ describe('plugin-mercury', () => {
|
|
|
276
304
|
assert.notCalled(webex.internal.device.refresh);
|
|
277
305
|
const promise = mercury.connect();
|
|
278
306
|
|
|
279
|
-
return promiseTick(7)
|
|
280
|
-
.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
clock.tick(1000);
|
|
307
|
+
return promiseTick(7).then(() => {
|
|
308
|
+
assert.notCalled(webex.credentials.refresh);
|
|
309
|
+
assert.called(webex.internal.device.refresh);
|
|
310
|
+
clock.tick(1000);
|
|
284
311
|
|
|
285
|
-
|
|
286
|
-
|
|
312
|
+
return promise;
|
|
313
|
+
});
|
|
287
314
|
});
|
|
288
315
|
});
|
|
289
316
|
|
|
290
|
-
|
|
291
317
|
describe('with `NotAuthorized`', () => {
|
|
292
318
|
it('triggers a token refresh', () => {
|
|
293
319
|
socketOpenStub.restore();
|
|
@@ -297,14 +323,13 @@ describe('plugin-mercury', () => {
|
|
|
297
323
|
assert.notCalled(webex.internal.device.refresh);
|
|
298
324
|
const promise = mercury.connect();
|
|
299
325
|
|
|
300
|
-
return promiseTick(7)
|
|
301
|
-
.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
clock.tick(1000);
|
|
326
|
+
return promiseTick(7).then(() => {
|
|
327
|
+
assert.called(webex.credentials.refresh);
|
|
328
|
+
assert.notCalled(webex.internal.device.refresh);
|
|
329
|
+
clock.tick(1000);
|
|
305
330
|
|
|
306
|
-
|
|
307
|
-
|
|
331
|
+
return promise;
|
|
332
|
+
});
|
|
308
333
|
});
|
|
309
334
|
});
|
|
310
335
|
|
|
@@ -312,7 +337,9 @@ describe('plugin-mercury', () => {
|
|
|
312
337
|
it('fails permanently', () => {
|
|
313
338
|
clock.uninstall();
|
|
314
339
|
socketOpenStub.restore();
|
|
315
|
-
socketOpenStub = sinon
|
|
340
|
+
socketOpenStub = sinon
|
|
341
|
+
.stub(Socket.prototype, 'open')
|
|
342
|
+
.returns(Promise.reject(new Forbidden({code: 4403})));
|
|
316
343
|
|
|
317
344
|
return assert.isRejected(mercury.connect());
|
|
318
345
|
});
|
|
@@ -344,20 +371,19 @@ describe('plugin-mercury', () => {
|
|
|
344
371
|
socketOpenStub.onCall(0).returns(Promise.reject(new ConnectionError({code: 4001})));
|
|
345
372
|
const promise = mercury.connect();
|
|
346
373
|
|
|
347
|
-
return promiseTick(7)
|
|
348
|
-
.
|
|
349
|
-
|
|
350
|
-
clock.tick(1000);
|
|
374
|
+
return promiseTick(7).then(() => {
|
|
375
|
+
assert.calledOnce(webex.internal.services.markFailedUrl);
|
|
376
|
+
clock.tick(1000);
|
|
351
377
|
|
|
352
|
-
|
|
353
|
-
|
|
378
|
+
return promise;
|
|
379
|
+
});
|
|
354
380
|
});
|
|
355
381
|
});
|
|
356
382
|
});
|
|
357
383
|
|
|
358
384
|
describe('when connected', () => {
|
|
359
|
-
it('resolves immediately', () =>
|
|
360
|
-
.then(() => {
|
|
385
|
+
it('resolves immediately', () =>
|
|
386
|
+
mercury.connect().then(() => {
|
|
361
387
|
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
362
388
|
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
363
389
|
const promise = mercury.connect();
|
|
@@ -393,12 +419,15 @@ describe('plugin-mercury', () => {
|
|
|
393
419
|
assert.isTrue(mercury.connecting, 'Mercury is connecting');
|
|
394
420
|
mockWebSocket.open();
|
|
395
421
|
|
|
396
|
-
return promise
|
|
397
|
-
.
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
422
|
+
return promise.then(() => {
|
|
423
|
+
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
424
|
+
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
425
|
+
assert.calledWith(
|
|
426
|
+
Socket.prototype.open,
|
|
427
|
+
sinon.match(/ws:\/\/providedurl.com/),
|
|
428
|
+
sinon.match.any
|
|
429
|
+
);
|
|
430
|
+
});
|
|
402
431
|
});
|
|
403
432
|
});
|
|
404
433
|
});
|
|
@@ -418,13 +447,18 @@ describe('plugin-mercury', () => {
|
|
|
418
447
|
assert.isTrue(mercury.connecting, 'Mercury is connecting');
|
|
419
448
|
mockWebSocket.open();
|
|
420
449
|
|
|
421
|
-
return promise
|
|
422
|
-
.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
450
|
+
return promise.then(() => {
|
|
451
|
+
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
452
|
+
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
453
|
+
assert.calledWith(
|
|
454
|
+
socketOpenStub,
|
|
455
|
+
sinon.match(/ws:\/\/example.com/),
|
|
456
|
+
sinon.match.has(
|
|
457
|
+
'agent',
|
|
458
|
+
sinon.match.has('proxy', sinon.match.has('href', testProxyUrl))
|
|
459
|
+
)
|
|
460
|
+
);
|
|
461
|
+
});
|
|
428
462
|
});
|
|
429
463
|
|
|
430
464
|
it('connects to Mercury without proxy agent', () => {
|
|
@@ -434,41 +468,47 @@ describe('plugin-mercury', () => {
|
|
|
434
468
|
assert.isTrue(mercury.connecting, 'Mercury is connecting');
|
|
435
469
|
mockWebSocket.open();
|
|
436
470
|
|
|
437
|
-
return promise
|
|
438
|
-
.
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
471
|
+
return promise.then(() => {
|
|
472
|
+
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
473
|
+
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
474
|
+
assert.calledWith(
|
|
475
|
+
socketOpenStub,
|
|
476
|
+
sinon.match(/ws:\/\/example.com/),
|
|
477
|
+
sinon.match({agent: undefined})
|
|
478
|
+
);
|
|
479
|
+
});
|
|
443
480
|
});
|
|
444
481
|
});
|
|
445
482
|
|
|
446
483
|
describe('#disconnect()', () => {
|
|
447
|
-
it('disconnects the WebSocket', () =>
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
484
|
+
it('disconnects the WebSocket', () =>
|
|
485
|
+
mercury
|
|
486
|
+
.connect()
|
|
487
|
+
.then(() => {
|
|
488
|
+
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
489
|
+
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
490
|
+
const promise = mercury.disconnect();
|
|
452
491
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
492
|
+
mockWebSocket.emit('close', {
|
|
493
|
+
code: 1000,
|
|
494
|
+
reason: 'Done',
|
|
495
|
+
});
|
|
457
496
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
497
|
+
return promise;
|
|
498
|
+
})
|
|
499
|
+
.then(() => {
|
|
500
|
+
assert.isFalse(mercury.connected, 'Mercury is not connected');
|
|
501
|
+
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
502
|
+
assert.isUndefined(mercury.mockWebSocket, 'Mercury does not have a mockWebSocket');
|
|
503
|
+
}));
|
|
465
504
|
|
|
466
505
|
it('stops emitting message events', () => {
|
|
467
506
|
const spy = sinon.spy();
|
|
468
507
|
|
|
469
508
|
mercury.on('event:status.start_typing', spy);
|
|
470
509
|
|
|
471
|
-
return mercury
|
|
510
|
+
return mercury
|
|
511
|
+
.connect()
|
|
472
512
|
.then(() => {
|
|
473
513
|
assert.isTrue(mercury.connected, 'Mercury is connected');
|
|
474
514
|
assert.isFalse(mercury.connecting, 'Mercury is not connecting');
|
|
@@ -488,7 +528,7 @@ describe('plugin-mercury', () => {
|
|
|
488
528
|
mockWebSocket.emit('message', {data: statusStartTypingMessage});
|
|
489
529
|
mockWebSocket.emit('close', {
|
|
490
530
|
code: 1000,
|
|
491
|
-
reason: 'Done'
|
|
531
|
+
reason: 'Done',
|
|
492
532
|
});
|
|
493
533
|
mockWebSocket.emit('message', {data: statusStartTypingMessage});
|
|
494
534
|
|
|
@@ -511,28 +551,27 @@ describe('plugin-mercury', () => {
|
|
|
511
551
|
// Delay the opening of the socket so that disconnect is called while open
|
|
512
552
|
// is in progress
|
|
513
553
|
promiseTick(2 * webex.internal.mercury.config.backoffTimeReset)
|
|
514
|
-
|
|
515
|
-
|
|
554
|
+
// Pretend the socket opened successfully. Failing should be fine too but
|
|
555
|
+
// it generates more console output.
|
|
516
556
|
.then(() => Promise.resolve())
|
|
517
557
|
);
|
|
518
558
|
const promise = mercury.connect();
|
|
519
559
|
|
|
520
560
|
// Wait for the connect call to setup
|
|
521
|
-
return promiseTick(webex.internal.mercury.config.backoffTimeReset)
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
});
|
|
561
|
+
return promiseTick(webex.internal.mercury.config.backoffTimeReset).then(() => {
|
|
562
|
+
// By this time backoffCall and mercury socket should be defined by the
|
|
563
|
+
// 'connect' call
|
|
564
|
+
assert.isDefined(mercury.backoffCall, 'Mercury backoffCall is not defined');
|
|
565
|
+
assert.isDefined(mercury.socket, 'Mercury socket is not defined');
|
|
566
|
+
// Calling disconnect will abort the backoffCall, close the socket, and
|
|
567
|
+
// reject the connect
|
|
568
|
+
mercury.disconnect();
|
|
569
|
+
assert.isUndefined(mercury.backoffCall, 'Mercury backoffCall is still defined');
|
|
570
|
+
// The socket will never be unset (which seems bad)
|
|
571
|
+
assert.isDefined(mercury.socket, 'Mercury socket is not defined');
|
|
572
|
+
|
|
573
|
+
return assert.isRejected(promise);
|
|
574
|
+
});
|
|
536
575
|
});
|
|
537
576
|
|
|
538
577
|
it('stops the attempt when backoffCall is undefined', () => {
|
|
@@ -547,21 +586,32 @@ describe('plugin-mercury', () => {
|
|
|
547
586
|
reason = _reason;
|
|
548
587
|
});
|
|
549
588
|
|
|
550
|
-
return promiseTick(webex.internal.mercury.config.backoffTimeReset)
|
|
551
|
-
.
|
|
552
|
-
|
|
553
|
-
|
|
589
|
+
return promiseTick(webex.internal.mercury.config.backoffTimeReset).then(() => {
|
|
590
|
+
assert.equal(
|
|
591
|
+
reason.message,
|
|
592
|
+
'Mercury: prevent socket open when backoffCall no longer defined'
|
|
593
|
+
);
|
|
594
|
+
});
|
|
554
595
|
});
|
|
555
596
|
});
|
|
556
597
|
});
|
|
557
598
|
|
|
558
599
|
describe('#_emit()', () => {
|
|
559
|
-
it('emits Error-safe events', () => {
|
|
600
|
+
it('emits Error-safe events and log the error with the call parameters', () => {
|
|
601
|
+
const error = 'error';
|
|
602
|
+
const event = {data: 'some data'};
|
|
560
603
|
mercury.on('break', () => {
|
|
561
|
-
throw
|
|
604
|
+
throw error;
|
|
562
605
|
});
|
|
606
|
+
sinon.stub(mercury.logger, 'error');
|
|
563
607
|
|
|
564
|
-
return Promise.resolve(mercury._emit('break'))
|
|
608
|
+
return Promise.resolve(mercury._emit('break', event)).then((res) => {
|
|
609
|
+
assert.calledWith(mercury.logger.error, 'Mercury: error occurred in event handler', {
|
|
610
|
+
error,
|
|
611
|
+
arguments: ['break', event],
|
|
612
|
+
});
|
|
613
|
+
return res;
|
|
614
|
+
});
|
|
565
615
|
});
|
|
566
616
|
});
|
|
567
617
|
|
|
@@ -572,11 +622,11 @@ describe('plugin-mercury', () => {
|
|
|
572
622
|
it('merges a single header field with data', () => {
|
|
573
623
|
const envelope = {
|
|
574
624
|
headers: {
|
|
575
|
-
'data.activity.target.lastSeenActivityDate': lastSeenActivityDate
|
|
625
|
+
'data.activity.target.lastSeenActivityDate': lastSeenActivityDate,
|
|
576
626
|
},
|
|
577
627
|
data: {
|
|
578
|
-
activity: {}
|
|
579
|
-
}
|
|
628
|
+
activity: {},
|
|
629
|
+
},
|
|
580
630
|
};
|
|
581
631
|
|
|
582
632
|
mercury._applyOverrides(envelope);
|
|
@@ -588,27 +638,30 @@ describe('plugin-mercury', () => {
|
|
|
588
638
|
const envelope = {
|
|
589
639
|
headers: {
|
|
590
640
|
'data.activity.target.lastSeenActivityDate': lastSeenActivityDate,
|
|
591
|
-
'data.activity.target.lastReadableActivityDate': lastReadableActivityDate
|
|
641
|
+
'data.activity.target.lastReadableActivityDate': lastReadableActivityDate,
|
|
592
642
|
},
|
|
593
643
|
data: {
|
|
594
|
-
activity: {}
|
|
595
|
-
}
|
|
644
|
+
activity: {},
|
|
645
|
+
},
|
|
596
646
|
};
|
|
597
647
|
|
|
598
648
|
mercury._applyOverrides(envelope);
|
|
599
649
|
|
|
600
650
|
assert.equal(envelope.data.activity.target.lastSeenActivityDate, lastSeenActivityDate);
|
|
601
|
-
assert.equal(
|
|
651
|
+
assert.equal(
|
|
652
|
+
envelope.data.activity.target.lastReadableActivityDate,
|
|
653
|
+
lastReadableActivityDate
|
|
654
|
+
);
|
|
602
655
|
});
|
|
603
656
|
|
|
604
657
|
it('merges headers when Mercury messages arrive', () => {
|
|
605
658
|
const envelope = {
|
|
606
659
|
headers: {
|
|
607
|
-
'data.activity.target.lastSeenActivityDate': lastSeenActivityDate
|
|
660
|
+
'data.activity.target.lastSeenActivityDate': lastSeenActivityDate,
|
|
608
661
|
},
|
|
609
662
|
data: {
|
|
610
|
-
activity: {}
|
|
611
|
-
}
|
|
663
|
+
activity: {},
|
|
664
|
+
},
|
|
612
665
|
};
|
|
613
666
|
|
|
614
667
|
mercury._applyOverrides(envelope);
|
|
@@ -622,19 +675,24 @@ describe('plugin-mercury', () => {
|
|
|
622
675
|
webex.internal.device.webSocketUrl = 'ws://example.com';
|
|
623
676
|
});
|
|
624
677
|
|
|
625
|
-
it('uses device default webSocketUrl', () =>
|
|
626
|
-
.then((wsUrl) => assert.match(wsUrl, /example.com/)));
|
|
627
|
-
it('uses provided webSocketUrl', () =>
|
|
628
|
-
.
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
it('
|
|
637
|
-
.
|
|
678
|
+
it('uses device default webSocketUrl', () =>
|
|
679
|
+
webex.internal.mercury._prepareUrl().then((wsUrl) => assert.match(wsUrl, /example.com/)));
|
|
680
|
+
it('uses provided webSocketUrl', () =>
|
|
681
|
+
webex.internal.mercury
|
|
682
|
+
._prepareUrl('ws://provided.com')
|
|
683
|
+
.then((wsUrl) => assert.match(wsUrl, /provided.com/)));
|
|
684
|
+
it('requests text-mode WebSockets', () =>
|
|
685
|
+
webex.internal.mercury
|
|
686
|
+
._prepareUrl()
|
|
687
|
+
.then((wsUrl) => assert.match(wsUrl, /outboundWireFormat=text/)));
|
|
688
|
+
|
|
689
|
+
it('requests the buffer state message', () =>
|
|
690
|
+
webex.internal.mercury
|
|
691
|
+
._prepareUrl()
|
|
692
|
+
.then((wsUrl) => assert.match(wsUrl, /bufferStates=true/)));
|
|
693
|
+
|
|
694
|
+
it('does not add conditional properties', () =>
|
|
695
|
+
webex.internal.mercury._prepareUrl().then((wsUrl) => {
|
|
638
696
|
assert.notMatch(wsUrl, /mercuryRegistrationStatus/);
|
|
639
697
|
assert.notMatch(wsUrl, /mercuryRegistrationStatus/);
|
|
640
698
|
assert.notMatch(wsUrl, /isRegistrationRefreshEnabled/);
|
|
@@ -643,27 +701,34 @@ describe('plugin-mercury', () => {
|
|
|
643
701
|
|
|
644
702
|
describe('when web-high-availability is enabled', () => {
|
|
645
703
|
it('uses webSocketUrl provided by device', () => {
|
|
646
|
-
webex.internal.device.useServiceCatalogUrl = sinon
|
|
704
|
+
webex.internal.device.useServiceCatalogUrl = sinon
|
|
705
|
+
.stub()
|
|
706
|
+
.returns(Promise.resolve('ws://example-2.com'));
|
|
647
707
|
webex.internal.feature.getFeature.onCall(0).returns(Promise.resolve(true));
|
|
648
708
|
|
|
649
|
-
return webex.internal.mercury
|
|
709
|
+
return webex.internal.mercury
|
|
710
|
+
._prepareUrl()
|
|
650
711
|
.then((wsUrl) => assert.match(wsUrl, /example-2.com/));
|
|
651
712
|
});
|
|
652
713
|
});
|
|
653
714
|
|
|
654
|
-
describe(
|
|
715
|
+
describe("when 'web-shared-socket' is enabled", () => {
|
|
655
716
|
beforeEach(() => {
|
|
656
717
|
webex.internal.feature.getFeature.returns(Promise.resolve(true));
|
|
657
718
|
});
|
|
658
719
|
|
|
659
|
-
it('requests shared socket support', () =>
|
|
660
|
-
.
|
|
720
|
+
it('requests shared socket support', () =>
|
|
721
|
+
webex.internal.mercury
|
|
722
|
+
._prepareUrl()
|
|
723
|
+
.then((wsUrl) => assert.match(wsUrl, /isRegistrationRefreshEnabled=true/)));
|
|
661
724
|
|
|
662
|
-
it('requests the registration banner', () =>
|
|
663
|
-
.
|
|
725
|
+
it('requests the registration banner', () =>
|
|
726
|
+
webex.internal.mercury
|
|
727
|
+
._prepareUrl()
|
|
728
|
+
.then((wsUrl) => assert.match(wsUrl, /mercuryRegistrationStatus=true/)));
|
|
664
729
|
|
|
665
|
-
it('does not request the buffer state message', () =>
|
|
666
|
-
.then((wsUrl) => {
|
|
730
|
+
it('does not request the buffer state message', () =>
|
|
731
|
+
webex.internal.mercury._prepareUrl().then((wsUrl) => {
|
|
667
732
|
assert.match(wsUrl, /mercuryRegistrationStatus=true/);
|
|
668
733
|
assert.notMatch(wsUrl, /bufferStates/);
|
|
669
734
|
}));
|
|
@@ -674,8 +739,23 @@ describe('plugin-mercury', () => {
|
|
|
674
739
|
webex.config.device.ephemeral = true;
|
|
675
740
|
});
|
|
676
741
|
|
|
677
|
-
it('indicates multiple connections may be coming from this user', () =>
|
|
678
|
-
.
|
|
742
|
+
it('indicates multiple connections may be coming from this user', () =>
|
|
743
|
+
webex.internal.mercury
|
|
744
|
+
._prepareUrl()
|
|
745
|
+
.then((wsUrl) => assert.match(wsUrl, /multipleConnections/)));
|
|
746
|
+
});
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
describe('ping pong latency event is forwarded', () => {
|
|
750
|
+
it('should forward ping pong latency event', () => {
|
|
751
|
+
const spy = sinon.spy();
|
|
752
|
+
|
|
753
|
+
mercury.on('ping-pong-latency', spy);
|
|
754
|
+
|
|
755
|
+
return mercury.connect().then(() => {
|
|
756
|
+
assert.calledWith(spy, 0);
|
|
757
|
+
assert.calledOnce(spy);
|
|
758
|
+
});
|
|
679
759
|
});
|
|
680
760
|
});
|
|
681
761
|
});
|