@webex/plugin-meetings 3.1.0-next.2 → 3.1.0-next.20

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.
Files changed (85) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
  4. package/dist/common/errors/reconnection-not-started.js.map +1 -0
  5. package/dist/constants.js +16 -5
  6. package/dist/constants.js.map +1 -1
  7. package/dist/interpretation/index.js +1 -1
  8. package/dist/interpretation/siLanguage.js +1 -1
  9. package/dist/locus-info/controlsUtils.js +7 -1
  10. package/dist/locus-info/controlsUtils.js.map +1 -1
  11. package/dist/locus-info/index.js +10 -0
  12. package/dist/locus-info/index.js.map +1 -1
  13. package/dist/media/properties.js +102 -57
  14. package/dist/media/properties.js.map +1 -1
  15. package/dist/mediaQualityMetrics/config.js +10 -10
  16. package/dist/mediaQualityMetrics/config.js.map +1 -1
  17. package/dist/meeting/in-meeting-actions.js +6 -0
  18. package/dist/meeting/in-meeting-actions.js.map +1 -1
  19. package/dist/meeting/index.js +543 -467
  20. package/dist/meeting/index.js.map +1 -1
  21. package/dist/meeting/locusMediaRequest.js +27 -0
  22. package/dist/meeting/locusMediaRequest.js.map +1 -1
  23. package/dist/meeting/util.js +9 -16
  24. package/dist/meeting/util.js.map +1 -1
  25. package/dist/meeting/voicea-meeting.js +37 -49
  26. package/dist/meeting/voicea-meeting.js.map +1 -1
  27. package/dist/meetings/index.js +12 -28
  28. package/dist/meetings/index.js.map +1 -1
  29. package/dist/reachability/index.js +88 -9
  30. package/dist/reachability/index.js.map +1 -1
  31. package/dist/reconnection-manager/index.js +138 -109
  32. package/dist/reconnection-manager/index.js.map +1 -1
  33. package/dist/roap/request.js +3 -27
  34. package/dist/roap/request.js.map +1 -1
  35. package/dist/statsAnalyzer/index.js +4 -0
  36. package/dist/statsAnalyzer/index.js.map +1 -1
  37. package/dist/statsAnalyzer/mqaUtil.js +3 -0
  38. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  39. package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
  40. package/dist/types/constants.d.ts +13 -3
  41. package/dist/types/media/properties.d.ts +26 -2
  42. package/dist/types/mediaQualityMetrics/config.d.ts +8 -2
  43. package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
  44. package/dist/types/meeting/index.d.ts +5 -6
  45. package/dist/types/meeting/locusMediaRequest.d.ts +1 -0
  46. package/dist/types/meeting/util.d.ts +3 -0
  47. package/dist/types/meeting/voicea-meeting.d.ts +3 -2
  48. package/dist/types/meetings/index.d.ts +1 -16
  49. package/dist/types/reachability/index.d.ts +11 -0
  50. package/dist/types/reconnection-manager/index.d.ts +4 -14
  51. package/dist/webinar/index.js +1 -1
  52. package/package.json +21 -21
  53. package/src/common/errors/reconnection-not-started.ts +25 -0
  54. package/src/constants.ts +14 -5
  55. package/src/locus-info/controlsUtils.ts +11 -0
  56. package/src/locus-info/index.ts +16 -0
  57. package/src/media/properties.ts +67 -15
  58. package/src/mediaQualityMetrics/config.ts +13 -7
  59. package/src/meeting/in-meeting-actions.ts +12 -0
  60. package/src/meeting/index.ts +121 -98
  61. package/src/meeting/locusMediaRequest.ts +31 -0
  62. package/src/meeting/util.ts +9 -16
  63. package/src/meeting/voicea-meeting.ts +44 -46
  64. package/src/meetings/index.ts +15 -27
  65. package/src/reachability/index.ts +60 -0
  66. package/src/reconnection-manager/index.ts +128 -105
  67. package/src/roap/request.ts +1 -24
  68. package/src/statsAnalyzer/index.ts +4 -0
  69. package/src/statsAnalyzer/mqaUtil.ts +5 -0
  70. package/test/unit/spec/locus-info/controlsUtils.js +20 -0
  71. package/test/unit/spec/locus-info/index.js +21 -0
  72. package/test/unit/spec/media/properties.ts +145 -140
  73. package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
  74. package/test/unit/spec/meeting/index.js +243 -97
  75. package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
  76. package/test/unit/spec/meeting/utils.js +3 -10
  77. package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
  78. package/test/unit/spec/meetings/index.js +59 -17
  79. package/test/unit/spec/reachability/index.ts +266 -0
  80. package/test/unit/spec/reconnection-manager/index.js +127 -39
  81. package/test/unit/spec/roap/request.ts +0 -37
  82. package/test/unit/spec/stats-analyzer/index.js +11 -0
  83. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  84. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  85. package/src/common/errors/reconnection-in-progress.ts +0 -8
@@ -141,6 +141,272 @@ describe('isAnyPublicClusterReachable', () => {
141
141
  });
142
142
  });
143
143
 
144
+
145
+ describe('isWebexMediaBackendUnreachable', () => {
146
+ let webex;
147
+
148
+ beforeEach(() => {
149
+ webex = new MockWebex();
150
+
151
+ sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
152
+ });
153
+
154
+ afterEach(() => {
155
+ sinon.restore();
156
+ });
157
+
158
+ const runCheck = async (mockStorage: any, expectedValue: boolean) => {
159
+ if (mockStorage) {
160
+ await webex.boundedStorage.put(
161
+ 'Reachability',
162
+ 'reachability.result',
163
+ JSON.stringify(mockStorage)
164
+ );
165
+ }
166
+ const reachability = new Reachability(webex);
167
+
168
+ const result = await reachability.isWebexMediaBackendUnreachable();
169
+
170
+ assert.equal(result, expectedValue);
171
+ };
172
+
173
+ [
174
+ {
175
+ title: 'no clusters at all',
176
+ mockStorage: {},
177
+ expectedResult: false,
178
+ },
179
+ {
180
+ title: 'clusters without results',
181
+ mockStorage: {a: {}, b: {}},
182
+ expectedResult: false,
183
+ },
184
+ {
185
+ title: 'all clusters untested',
186
+ mockStorage: {
187
+ a: {udp: 'untested'},
188
+ b: {udp: 'untested', tcp: 'untested'},
189
+ },
190
+ expectedResult: false,
191
+ },
192
+ {
193
+ title: 'one cluster with udp reachable',
194
+ mockStorage: {x: {udp: {result: 'reachable'}, tcp: {result: 'unreachable'}}},
195
+ expectedResult: false,
196
+ },
197
+ {
198
+ title: 'one cluster with tcp reachable',
199
+ mockStorage: {x: {tcp: {result: 'reachable'}}},
200
+ expectedResult: false,
201
+ },
202
+ {
203
+ title: 'one cluster with xtls reachable',
204
+ mockStorage: {x: {xtls: {result: 'reachable'}}, y: {xtls: {result: 'unreachable'}}},
205
+ expectedResult: false,
206
+ },
207
+ {
208
+ title: 'multiple clusters with various protocols reachable',
209
+ mockStorage: {
210
+ a: {udp: {result: 'reachable'}, tcp: {result: 'reachable'}},
211
+ b: {udp: {result: 'unreachable'}, tcp: {result: 'reachable'}},
212
+ c: {tcp: {result: 'reachable'}},
213
+ d: {xtls: {result: 'reachable'}},
214
+ },
215
+ expectedResult: false,
216
+ },
217
+ {
218
+ title: 'multiple clusters with all protocols unreachable',
219
+ mockStorage: {
220
+ a: {
221
+ udp: {result: 'unreachable'},
222
+ tcp: {result: 'unreachable'},
223
+ xtls: {result: 'unreachable'},
224
+ },
225
+ b: {
226
+ udp: {result: 'unreachable'},
227
+ tcp: {result: 'unreachable'},
228
+ xtls: {result: 'unreachable'},
229
+ },
230
+ c: {
231
+ udp: {result: 'unreachable'},
232
+ tcp: {result: 'unreachable'},
233
+ xtls: {result: 'unreachable'},
234
+ },
235
+ },
236
+ expectedResult: true,
237
+ },
238
+ {
239
+ title: 'multiple clusters with UDP and TCP protocols unreachable, but TLS not tested',
240
+ mockStorage: {
241
+ a: {
242
+ udp: {result: 'unreachable'},
243
+ tcp: {result: 'unreachable'},
244
+ xtls: {result: 'untested'},
245
+ },
246
+ b: {
247
+ udp: {result: 'unreachable'},
248
+ tcp: {result: 'unreachable'},
249
+ xtls: {result: 'untested'},
250
+ },
251
+ c: {
252
+ udp: {result: 'unreachable'},
253
+ tcp: {result: 'unreachable'},
254
+ xtls: {result: 'untested'},
255
+ },
256
+ },
257
+ expectedResult: false,
258
+ },
259
+ {
260
+ title: 'multiple clusters with UDP and TCP protocols unreachable, but TLS missing',
261
+ mockStorage: {
262
+ a: {
263
+ udp: {result: 'unreachable'},
264
+ tcp: {result: 'unreachable'},
265
+ },
266
+ b: {
267
+ udp: {result: 'unreachable'},
268
+ tcp: {result: 'unreachable'},
269
+ },
270
+ c: {
271
+ udp: {result: 'unreachable'},
272
+ tcp: {result: 'unreachable'},
273
+ },
274
+ },
275
+ expectedResult: false,
276
+ },
277
+ {
278
+ title: 'multiple clusters with UDP and TLS protocols unreachable, but TCP not tested',
279
+ mockStorage: {
280
+ a: {
281
+ udp: {result: 'unreachable'},
282
+ tcp: {result: 'untested'},
283
+ xtls: {result: 'unreachable'},
284
+ },
285
+ b: {
286
+ udp: {result: 'unreachable'},
287
+ tcp: {result: 'untested'},
288
+ xtls: {result: 'unreachable'},
289
+ },
290
+ c: {
291
+ udp: {result: 'unreachable'},
292
+ tcp: {result: 'untested'},
293
+ xtls: {result: 'unreachable'},
294
+ },
295
+ },
296
+ expectedResult: false,
297
+ },
298
+ {
299
+ title: 'multiple clusters with UDP and TLS protocols unreachable, but TCP missing',
300
+ mockStorage: {
301
+ a: {
302
+ udp: {result: 'unreachable'},
303
+ xtls: {result: 'unreachable'},
304
+ },
305
+ b: {
306
+ udp: {result: 'unreachable'},
307
+ xtls: {result: 'unreachable'},
308
+ },
309
+ c: {
310
+ udp: {result: 'unreachable'},
311
+ xtls: {result: 'unreachable'},
312
+ },
313
+ },
314
+ expectedResult: false,
315
+ },
316
+ {
317
+ title: 'multiple clusters with all protocols unreachable, some untested',
318
+ mockStorage: {
319
+ a: {
320
+ udp: {result: 'unreachable'},
321
+ tcp: {result: 'unreachable'},
322
+ xtls: {result: 'unreachable'},
323
+ },
324
+ b: {udp: {result: 'unreachable'}, tcp: {result: 'untested'}, xtls: {result: 'unreachable'}},
325
+ c: {udp: {result: 'unreachable'}, tcp: {result: 'unreachable'}, xtls: {result: 'untested'}},
326
+ },
327
+ expectedResult: true,
328
+ },
329
+ {
330
+ title: 'multiple clusters with all protocols unreachable, except for 1 reachable on udp',
331
+ mockStorage: {
332
+ a: {
333
+ udp: {result: 'reachable'},
334
+ tcp: {result: 'unreachable'},
335
+ xtls: {result: 'unreachable'},
336
+ },
337
+ b: {
338
+ udp: {result: 'unreachable'},
339
+ tcp: {result: 'unreachable'},
340
+ xtls: {result: 'unreachable'},
341
+ },
342
+ c: {
343
+ udp: {result: 'unreachable'},
344
+ tcp: {result: 'unreachable'},
345
+ xtls: {result: 'unreachable'},
346
+ },
347
+ },
348
+ expectedResult: false,
349
+ },
350
+ {
351
+ title: 'multiple clusters with all protocols unreachable, except for 1 reachable on tcp',
352
+ mockStorage: {
353
+ a: {
354
+ udp: {result: 'unreachable'},
355
+ tcp: {result: 'unreachable'},
356
+ xtls: {result: 'unreachable'},
357
+ },
358
+ b: {
359
+ udp: {result: 'unreachable'},
360
+ tcp: {result: 'unreachable'},
361
+ xtls: {result: 'unreachable'},
362
+ },
363
+ c: {
364
+ udp: {result: 'unreachable'},
365
+ tcp: {result: 'reachable'},
366
+ xtls: {result: 'unreachable'},
367
+ },
368
+ },
369
+ expectedResult: false,
370
+ },
371
+ {
372
+ title: 'multiple clusters with all protocols unreachable, except for 1 reachable on xtls',
373
+ mockStorage: {
374
+ a: {
375
+ udp: {result: 'unreachable'},
376
+ tcp: {result: 'unreachable'},
377
+ xtls: {result: 'unreachable'},
378
+ },
379
+ b: {
380
+ udp: {result: 'unreachable'},
381
+ tcp: {result: 'unreachable'},
382
+ xtls: {result: 'reachable'},
383
+ },
384
+ c: {
385
+ udp: {result: 'unreachable'},
386
+ tcp: {result: 'unreachable'},
387
+ xtls: {result: 'unreachable'},
388
+ },
389
+ },
390
+ expectedResult: false,
391
+ },
392
+ {
393
+ title: 'multiple clusters with some missing results',
394
+ mockStorage: {
395
+ a: {udp: {result: 'unreachable'}},
396
+ b: {tcp: {result: 'unreachable'}},
397
+ c: {xtls: {result: 'unreachable'}},
398
+ d: {},
399
+ },
400
+ expectedResult: true,
401
+ },
402
+ ].forEach(({mockStorage, expectedResult, title}) => {
403
+ it(`returns ${expectedResult} when ${title}`, async () => {
404
+ await runCheck(mockStorage, expectedResult);
405
+ });
406
+ });
407
+ });
408
+
409
+
144
410
  describe('gatherReachability', () => {
145
411
  let webex;
146
412
 
@@ -2,11 +2,14 @@ import 'jsdom-global/register';
2
2
  import chai from 'chai';
3
3
  import chaiAsPromised from 'chai-as-promised';
4
4
  import sinon from 'sinon';
5
+ import {Defer} from '@webex/common';
5
6
  import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
7
+ import ReconnectionNotStartedError from '@webex/plugin-meetings/src/common/errors/reconnection-not-started';
8
+ import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
9
+ import Metrics from '@webex/plugin-meetings/src/metrics';
6
10
  import { RECONNECTION } from '../../../../src/constants';
7
11
  import LoggerProxy from '../../../../src/common/logs/logger-proxy';
8
12
  import LoggerConfig from '../../../../src/common/logs/logger-config';
9
-
10
13
  const {assert} = chai;
11
14
 
12
15
  chai.use(chaiAsPromised);
@@ -14,18 +17,15 @@ sinon.assert.expose(chai.assert, {prefix: ''});
14
17
 
15
18
  describe('plugin-meetings', () => {
16
19
  describe('ReconnectionManager.reconnect', () => {
17
- const sandbox = sinon.createSandbox();
18
20
  let fakeMediaConnection;
19
21
  let fakeMeeting;
20
22
  let loggerSpy;
21
23
 
22
- before(() => {
24
+ beforeEach(() => {
23
25
  LoggerConfig.set({ enable: false });
24
26
  LoggerProxy.set();
25
- loggerSpy = sandbox.spy(LoggerProxy.logger, 'info');
26
- });
27
+ loggerSpy = sinon.spy(LoggerProxy.logger, 'info');
27
28
 
28
- beforeEach(() => {
29
29
  fakeMediaConnection = {
30
30
  initiateOffer: sinon.stub().resolves({}),
31
31
  reconnect: sinon.stub().resolves({}),
@@ -33,6 +33,7 @@ describe('plugin-meetings', () => {
33
33
  fakeMeeting = {
34
34
  closePeerConnections: sinon.stub().resolves({}),
35
35
  createMediaConnection: sinon.stub().returns(fakeMediaConnection),
36
+ correlationId: 'correlationId',
36
37
  config: {
37
38
  reconnection: {
38
39
  enabled: true,
@@ -47,6 +48,7 @@ describe('plugin-meetings', () => {
47
48
  },
48
49
  },
49
50
  },
51
+ locusUrl: 'test/id',
50
52
  mediaProperties: {
51
53
  unsetPeerConnection: sinon.stub(),
52
54
  webrtcMediaConnection: fakeMediaConnection,
@@ -83,11 +85,16 @@ describe('plugin-meetings', () => {
83
85
  }
84
86
  }
85
87
  },
88
+ trigger: sinon.stub(),
86
89
  };
90
+
91
+ sinon.stub(TriggerProxy, 'trigger').returns(true);
92
+ sinon.stub(Metrics, 'sendBehavioralMetric');
87
93
  });
88
94
 
89
95
  afterEach(() => {
90
- sandbox.reset();
96
+ sinon.reset();
97
+ sinon.restore();
91
98
  });
92
99
 
93
100
  it('calls syncMeetings', async () => {
@@ -223,6 +230,99 @@ describe('plugin-meetings', () => {
223
230
  });
224
231
  }
225
232
  });
233
+
234
+ it('sends the right metrics and events when succeeds', async () => {
235
+ const rm = new ReconnectionManager(fakeMeeting);
236
+
237
+ await rm.reconnect();
238
+
239
+ assert.calledWith(
240
+ TriggerProxy.trigger,
241
+ fakeMeeting,
242
+ {file: 'reconnection-manager/index', function: 'reconnect'},
243
+ 'meeting:reconnectionSuccess'
244
+ );
245
+ assert.calledWithMatch(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
246
+ name: 'client.media.recovered',
247
+ payload: {
248
+ recoveredBy: 'new',
249
+ },
250
+ options: {
251
+ meetingId: fakeMeeting.id,
252
+ },
253
+ });
254
+ assert.equal(rm.status, RECONNECTION.STATE.DEFAULT_STATUS);
255
+ });
256
+
257
+ it('sends the right metrics and events when fails', async () => {
258
+ const rm = new ReconnectionManager(fakeMeeting);
259
+
260
+ sinon.stub(rm, 'executeReconnection').rejects(new Error('fake error'));
261
+
262
+ await assert.isRejected(rm.reconnect());
263
+
264
+ assert.calledWith(
265
+ TriggerProxy.trigger,
266
+ fakeMeeting,
267
+ {file: 'reconnection-manager/index', function: 'reconnect'},
268
+ 'meeting:reconnectionFailure'
269
+ );
270
+ assert.calledWithMatch(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
271
+ name: 'client.call.aborted',
272
+ payload: {
273
+ errors: [
274
+ {
275
+ category: 'expected',
276
+ errorCode: 2008,
277
+ fatal: true,
278
+ name: 'media-engine',
279
+ shownToUser: false,
280
+ },
281
+ ],
282
+ },
283
+ options: {
284
+ meetingId: fakeMeeting.id,
285
+ },
286
+ });
287
+ assert.calledWith(Metrics.sendBehavioralMetric, 'js_sdk_meeting_reconnect_failures', {
288
+ correlation_id: fakeMeeting.correlationId,
289
+ locus_id: 'id',
290
+ reason: 'fake error',
291
+ stack: sinon.match.any,
292
+ });
293
+ assert.equal(rm.status, RECONNECTION.STATE.DEFAULT_STATUS);
294
+ });
295
+
296
+ it('throws ReconnectionNotStartedError if reconnection is already in progress', async () => {
297
+ const rm = new ReconnectionManager(fakeMeeting);
298
+ const defer = new Defer();
299
+
300
+ sinon.stub(rm, 'executeReconnection').returns(defer.promise);
301
+
302
+ rm.reconnect();
303
+
304
+ try {
305
+ await rm.reconnect();
306
+
307
+ fail("rm.reconnect() should have thrown, but it hasn't");
308
+ } catch (e) {
309
+ assert.instanceOf(e, ReconnectionNotStartedError);
310
+ }
311
+ });
312
+
313
+ it('throws ReconnectionNotStartedError if reconnection is disabled in config', async () => {
314
+ fakeMeeting.config.reconnection.enabled = false;
315
+
316
+ const rm = new ReconnectionManager(fakeMeeting);
317
+
318
+ try {
319
+ await rm.reconnect();
320
+
321
+ fail("rm.reconnect() should have thrown, but it hasn't");
322
+ } catch (e) {
323
+ assert.instanceOf(e, ReconnectionNotStartedError);
324
+ }
325
+ });
226
326
  });
227
327
 
228
328
  /**
@@ -316,29 +416,41 @@ describe('plugin-meetings', () => {
316
416
 
317
417
  describe('waitForIceReconnect()', () => {
318
418
  describe('when ice is marked as not disconnected', () => {
419
+ let clock;
420
+
319
421
  beforeEach(() => {
422
+ clock = sinon.useFakeTimers();
320
423
  reconnectionManager.iceState.disconnected = false;
321
424
  });
322
425
 
426
+ afterEach(() => {
427
+ clock.restore();
428
+ });
429
+
323
430
  it('should set the disconnected state to true', () => {
324
- reconnectionManager.waitForIceReconnect();
431
+ const promise = reconnectionManager.waitForIceReconnect();
325
432
 
326
433
  assert.isTrue(reconnectionManager.iceState.disconnected);
434
+
435
+ // we let the timer expire
436
+ clock.tick(reconnectionManager.iceState.timeoutDuration);
437
+ assert.isRejected(promise);
327
438
  });
328
439
 
329
- it('should return a promise that rejects after a duration', (done) => {
330
- reconnectionManager.iceState.timeoutDuration = 100;
440
+ it('should return a promise that rejects after a duration', async () => {
441
+ const promise = reconnectionManager.waitForIceReconnect();
331
442
 
332
- assert.isRejected(reconnectionManager.waitForIceReconnect());
333
- done();
443
+ // we let the timer expire
444
+ clock.tick(reconnectionManager.iceState.timeoutDuration);
445
+ assert.isRejected(promise);
334
446
  });
335
447
 
336
- it('should resolve return a resolved promise when triggered', () => {
448
+ it('should resolve when ICE is reconnected', async () => {
337
449
  const promise = reconnectionManager.waitForIceReconnect();
338
450
 
339
- reconnectionManager.iceState.resolve();
451
+ reconnectionManager.iceReconnected();
340
452
 
341
- assert.isFulfilled(promise);
453
+ await promise;
342
454
  });
343
455
  });
344
456
 
@@ -359,30 +471,6 @@ describe('plugin-meetings', () => {
359
471
  });
360
472
  });
361
473
 
362
- describe('setStatus()', () => {
363
- beforeEach(() => {
364
- reconnectionManager.status = RECONNECTION.STATE.DEFAULT_STATUS;
365
- });
366
-
367
- it('should correctly change status to in progress', () => {
368
- reconnectionManager.setStatus(RECONNECTION.STATE.IN_PROGRESS);
369
-
370
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.IN_PROGRESS);
371
- });
372
-
373
- it('should correctly change status to complete', () => {
374
- reconnectionManager.setStatus(RECONNECTION.STATE.COMPLETE);
375
-
376
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.COMPLETE);
377
- });
378
-
379
- it('should correctly change status to failure', () => {
380
- reconnectionManager.setStatus(RECONNECTION.STATE.FAILURE);
381
-
382
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.FAILURE);
383
- });
384
- });
385
-
386
474
  describe('cleanUp()', () => {
387
475
  it('should call reset and keep reference to meeting object', () => {
388
476
  const resetSpy = sinon.spy(reconnectionManager, 'reset');
@@ -133,20 +133,6 @@ describe('plugin-meetings/roap', () => {
133
133
  locusMediaRequest,
134
134
  });
135
135
 
136
- assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
137
- name: 'client.locus.media.request',
138
- options: {
139
- meetingId: 'meeting-id',
140
- },
141
- });
142
-
143
- assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
144
- name: 'client.locus.media.response',
145
- options: {
146
- meetingId: 'meeting-id',
147
- },
148
- });
149
-
150
136
  const requestParams = locusMediaRequest.send.getCall(0).args[0];
151
137
  assert.deepEqual(requestParams, {
152
138
  type: 'RoapMessage',
@@ -175,29 +161,6 @@ describe('plugin-meetings/roap', () => {
175
161
  },
176
162
  });
177
163
  });
178
-
179
- it('sends correct client event when fails', async () => {
180
- const locusMediaRequest = {send: sinon.stub().rejects({code: 300, message: 'error'})};
181
- try {
182
- await roapRequest.sendRoap({
183
- locusSelfUrl: locusUrl,
184
- mediaId: 'mediaId',
185
- roapMessage: {
186
- seq: 'seq',
187
- },
188
- meetingId: 'meeting-id',
189
- locusMediaRequest,
190
- });
191
- } catch (err) {
192
- assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
193
- name: 'client.locus.media.response',
194
- options: {
195
- meetingId: 'meeting-id',
196
- rawError: {code: 300, message: 'error'},
197
- },
198
- });
199
- }
200
- });
201
164
  });
202
165
 
203
166
  it('calls attachReachabilityData when sendRoap', async () => {
@@ -88,6 +88,7 @@ describe('plugin-meetings', () => {
88
88
  trackId: 'RTCMediaStreamTrack_sender_2',
89
89
  transportId: 'RTCTransport_0_1',
90
90
  type: 'outbound-rtp',
91
+ requestedBitrate: 10000,
91
92
  },
92
93
  'audio-send',
93
94
  true
@@ -97,6 +98,7 @@ describe('plugin-meetings', () => {
97
98
  assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalBytesSent, 50000);
98
99
  assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalNackCount, 1);
99
100
  assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalPacketsSent, 3600);
101
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.requestedBitrate, 10000);
100
102
  assert.strictEqual(
101
103
  statsAnalyzer.statsResults['audio-send'].send.retransmittedPacketsSent,
102
104
  2
@@ -143,6 +145,7 @@ describe('plugin-meetings', () => {
143
145
  trackId: 'RTCMediaStreamTrack_receiver_76',
144
146
  transportId: 'RTCTransport_0_1',
145
147
  type: 'inbound-rtp',
148
+ requestedBitrate: 10000,
146
149
  },
147
150
  'audio-recv-1',
148
151
  false
@@ -155,6 +158,7 @@ describe('plugin-meetings', () => {
155
158
  assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.fecPacketsDiscarded, 1);
156
159
  assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.fecPacketsReceived, 1);
157
160
  assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalBytesReceived, 509);
161
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.requestedBitrate, 10000);
158
162
  assert.strictEqual(
159
163
  statsAnalyzer.statsResults['audio-recv-1'].recv.headerBytesReceived,
160
164
  250
@@ -1202,6 +1206,7 @@ describe('plugin-meetings', () => {
1202
1206
  },
1203
1207
  transmittedKeyFrames: 0,
1204
1208
  requestedKeyFrames: 0,
1209
+ requestedBitrate: 0,
1205
1210
  },
1206
1211
  ]);
1207
1212
  assert.deepEqual(mqeData.audioTransmit[1].streams, [
@@ -1218,6 +1223,7 @@ describe('plugin-meetings', () => {
1218
1223
  },
1219
1224
  transmittedKeyFrames: 0,
1220
1225
  requestedKeyFrames: 0,
1226
+ requestedBitrate: 0,
1221
1227
  },
1222
1228
  ]);
1223
1229
  assert.deepEqual(mqeData.audioReceive[0].streams, [
@@ -1306,6 +1312,7 @@ describe('plugin-meetings', () => {
1306
1312
  transmittedKeyFramesStartup: 0,
1307
1313
  transmittedKeyFramesUnknown: 0,
1308
1314
  transmittedWidth: 0,
1315
+ requestedBitrate: 0,
1309
1316
  },
1310
1317
  ]);
1311
1318
  assert.deepEqual(mqeData.videoTransmit[1].streams, [
@@ -1329,6 +1336,7 @@ describe('plugin-meetings', () => {
1329
1336
  maxNoiseLevel: 0,
1330
1337
  minRegionQp: 0,
1331
1338
  remoteConfigurationChanges: 0,
1339
+ requestedBitrate: 0,
1332
1340
  requestedFrameSize: 0,
1333
1341
  requestedKeyFrames: 0,
1334
1342
  transmittedFrameSize: 0,
@@ -1647,6 +1655,7 @@ describe('plugin-meetings', () => {
1647
1655
  transmittedKeyFramesStartup: 0,
1648
1656
  transmittedKeyFramesUnknown: 0,
1649
1657
  transmittedWidth: 0,
1658
+ requestedBitrate: 0,
1650
1659
  },
1651
1660
  {
1652
1661
  common: {
@@ -1683,6 +1692,7 @@ describe('plugin-meetings', () => {
1683
1692
  transmittedKeyFramesStartup: 0,
1684
1693
  transmittedKeyFramesUnknown: 0,
1685
1694
  transmittedWidth: 0,
1695
+ requestedBitrate: 0,
1686
1696
  },
1687
1697
  {
1688
1698
  common: {
@@ -1719,6 +1729,7 @@ describe('plugin-meetings', () => {
1719
1729
  transmittedKeyFramesStartup: 0,
1720
1730
  transmittedKeyFramesUnknown: 0,
1721
1731
  transmittedWidth: 0,
1732
+ requestedBitrate: 0,
1722
1733
  }
1723
1734
  ]);
1724
1735
  });
@@ -1 +0,0 @@
1
- {"version":3,"names":["ReconnectInProgress","exports","default","_Error","_inherits2","_super","_createSuper","_classCallCheck2","apply","arguments","_createClass2","_wrapNativeSuper2","Error"],"sources":["reconnection-in-progress.ts"],"sourcesContent":["/**\n *\n *\n * @export\n * @class ReconnectInProgress\n * @extends {Error}\n */\nexport default class ReconnectInProgress extends Error {}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AANA,IAOqBA,mBAAmB,GAAAC,OAAA,CAAAC,OAAA,0BAAAC,MAAA;EAAA,IAAAC,UAAA,CAAAF,OAAA,EAAAF,mBAAA,EAAAG,MAAA;EAAA,IAAAE,MAAA,GAAAC,YAAA,CAAAN,mBAAA;EAAA,SAAAA,oBAAA;IAAA,IAAAO,gBAAA,CAAAL,OAAA,QAAAF,mBAAA;IAAA,OAAAK,MAAA,CAAAG,KAAA,OAAAC,SAAA;EAAA;EAAA,WAAAC,aAAA,CAAAR,OAAA,EAAAF,mBAAA;AAAA,oBAAAW,iBAAA,CAAAT,OAAA,EAASU,KAAK"}
@@ -1,9 +0,0 @@
1
- /**
2
- *
3
- *
4
- * @export
5
- * @class ReconnectInProgress
6
- * @extends {Error}
7
- */
8
- export default class ReconnectInProgress extends Error {
9
- }
@@ -1,8 +0,0 @@
1
- /**
2
- *
3
- *
4
- * @export
5
- * @class ReconnectInProgress
6
- * @extends {Error}
7
- */
8
- export default class ReconnectInProgress extends Error {}