@webex/plugin-meetings 3.4.0 → 3.5.0-next.10

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 (76) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +1 -0
  4. package/dist/constants.js.map +1 -1
  5. package/dist/interpretation/index.js +1 -1
  6. package/dist/interpretation/siLanguage.js +1 -1
  7. package/dist/media/index.js +6 -9
  8. package/dist/media/index.js.map +1 -1
  9. package/dist/meeting/in-meeting-actions.js +3 -1
  10. package/dist/meeting/in-meeting-actions.js.map +1 -1
  11. package/dist/meeting/index.js +154 -50
  12. package/dist/meeting/index.js.map +1 -1
  13. package/dist/meeting/util.js +1 -0
  14. package/dist/meeting/util.js.map +1 -1
  15. package/dist/meetings/index.js +11 -2
  16. package/dist/meetings/index.js.map +1 -1
  17. package/dist/reachability/index.js +175 -103
  18. package/dist/reachability/index.js.map +1 -1
  19. package/dist/reconnection-manager/index.js +1 -1
  20. package/dist/reconnection-manager/index.js.map +1 -1
  21. package/dist/types/constants.d.ts +2 -1
  22. package/dist/types/meeting/in-meeting-actions.d.ts +2 -0
  23. package/dist/types/meeting/index.d.ts +22 -2
  24. package/dist/types/meetings/index.d.ts +4 -2
  25. package/dist/types/reachability/index.d.ts +14 -2
  26. package/dist/webinar/index.js +1 -1
  27. package/package.json +22 -22
  28. package/src/constants.ts +1 -0
  29. package/src/media/index.ts +6 -10
  30. package/src/meeting/in-meeting-actions.ts +3 -0
  31. package/src/meeting/index.ts +92 -10
  32. package/src/meeting/util.ts +2 -0
  33. package/src/meetings/index.ts +11 -4
  34. package/src/reachability/index.ts +49 -4
  35. package/src/reconnection-manager/index.ts +1 -1
  36. package/test/integration/spec/converged-space-meetings.js +1 -1
  37. package/test/unit/spec/breakouts/index.ts +1 -0
  38. package/test/unit/spec/interceptors/locusRetry.ts +11 -10
  39. package/test/unit/spec/media/MediaConnectionAwaiter.ts +1 -0
  40. package/test/unit/spec/media/index.ts +34 -7
  41. package/test/unit/spec/media/properties.ts +1 -1
  42. package/test/unit/spec/meeting/connectionStateHandler.ts +1 -0
  43. package/test/unit/spec/meeting/in-meeting-actions.ts +2 -0
  44. package/test/unit/spec/meeting/index.js +119 -12
  45. package/test/unit/spec/meeting/locusMediaRequest.ts +3 -2
  46. package/test/unit/spec/meeting/request.js +1 -0
  47. package/test/unit/spec/meeting/utils.js +4 -0
  48. package/test/unit/spec/meeting-info/meetinginfov2.js +10 -11
  49. package/test/unit/spec/meeting-info/request.js +1 -1
  50. package/test/unit/spec/meetings/index.js +40 -5
  51. package/test/unit/spec/members/request.js +2 -1
  52. package/test/unit/spec/multistream/mediaRequestManager.ts +1 -0
  53. package/test/unit/spec/multistream/receiveSlot.ts +1 -0
  54. package/test/unit/spec/multistream/receiveSlotManager.ts +1 -0
  55. package/test/unit/spec/multistream/remoteMedia.ts +1 -0
  56. package/test/unit/spec/multistream/remoteMediaGroup.ts +1 -0
  57. package/test/unit/spec/multistream/remoteMediaManager.ts +1 -0
  58. package/test/unit/spec/multistream/sendSlotManager.ts +1 -0
  59. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +0 -1
  60. package/test/unit/spec/reachability/index.ts +211 -13
  61. package/test/unit/spec/reachability/request.js +1 -0
  62. package/test/unit/spec/roap/request.ts +1 -0
  63. package/dist/networkQualityMonitor/index.js +0 -227
  64. package/dist/networkQualityMonitor/index.js.map +0 -1
  65. package/dist/rtcMetrics/constants.js +0 -11
  66. package/dist/rtcMetrics/constants.js.map +0 -1
  67. package/dist/rtcMetrics/index.js +0 -177
  68. package/dist/rtcMetrics/index.js.map +0 -1
  69. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  70. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  71. package/dist/types/rtcMetrics/index.d.ts +0 -61
  72. package/src/networkQualityMonitor/index.ts +0 -211
  73. package/src/rtcMetrics/constants.ts +0 -3
  74. package/src/rtcMetrics/index.ts +0 -166
  75. package/test/unit/spec/networkQualityMonitor/index.js +0 -99
  76. package/test/unit/spec/rtcMetrics/index.ts +0 -123
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  /* eslint-disable camelcase */
6
+ import 'jsdom-global/register';
6
7
  import {assert} from '@webex/test-helper-chai';
7
8
  import { expect } from "@webex/test-helper-chai";
8
9
  import MockWebex from '@webex/test-helper-mock-webex';
@@ -13,7 +14,7 @@ import sinon from 'sinon';
13
14
 
14
15
  describe('plugin-meetings', () => {
15
16
  describe('Interceptors', () => {
16
- describe('LocusRetryStatusInterceptor', () => {
17
+ describe('LocusRetryStatusInterceptor', () => {
17
18
  let interceptor, webex;
18
19
  beforeEach(() => {
19
20
  webex = new MockWebex({
@@ -24,7 +25,7 @@ describe('plugin-meetings', () => {
24
25
  interceptor = Reflect.apply(LocusRetryStatusInterceptor.create, {
25
26
  sessionId: 'mock-webex_uuid',
26
27
  }, []);
27
- });
28
+ });
28
29
  describe('#onResponseError', () => {
29
30
  const options = {
30
31
  method: 'POST',
@@ -41,7 +42,7 @@ describe('plugin-meetings', () => {
41
42
  headers: {
42
43
  trackingid: 'test',
43
44
  'retry-after': 1000,
44
- },
45
+ },
45
46
  uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
46
47
  },
47
48
  body: {
@@ -54,7 +55,7 @@ describe('plugin-meetings', () => {
54
55
  headers: {
55
56
  trackingid: 'test',
56
57
  'retry-after': 1000,
57
- },
58
+ },
58
59
  uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
59
60
  },
60
61
  body: {
@@ -73,7 +74,7 @@ describe('plugin-meetings', () => {
73
74
 
74
75
  return interceptor.onResponseError(options, reason2).then(() => {
75
76
  expect(handleRetryStub.calledWith(options, 1000)).to.be.true;
76
-
77
+
77
78
  });
78
79
  });
79
80
  });
@@ -92,7 +93,7 @@ describe('plugin-meetings', () => {
92
93
  it('returns the correct resolved value when the request is successful', () => {
93
94
  const mockResponse = 'mock response'
94
95
  interceptor.webex.request = sinon.stub().returns(Promise.resolve(mockResponse));
95
-
96
+
96
97
  return interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime)
97
98
  .then((response) => {
98
99
  expect(response).to.equal(mockResponse);
@@ -101,9 +102,9 @@ describe('plugin-meetings', () => {
101
102
 
102
103
  it('rejects the promise when the request is unsuccessful', () => {
103
104
  const rejectionReason = 'Service Unavaialble after retry';
104
-
105
+
105
106
  interceptor.webex.request = sinon.stub().returns(Promise.reject(rejectionReason));
106
-
107
+
107
108
  return interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime)
108
109
  .catch((error) => {
109
110
  expect(error).to.equal(rejectionReason);
@@ -114,10 +115,10 @@ describe('plugin-meetings', () => {
114
115
  let clock;
115
116
  clock = sinon.useFakeTimers();
116
117
  const mockResponse = 'mock response'
117
-
118
+
118
119
  interceptor.webex.request = sinon.stub().returns(Promise.resolve(mockResponse));
119
120
  const promise = interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime);
120
-
121
+
121
122
  clock.tick(retryAfterTime);
122
123
 
123
124
  return promise.then(() => {
@@ -1,3 +1,4 @@
1
+ import 'jsdom-global/register';
1
2
  import {assert} from '@webex/test-helper-chai';
2
3
  import sinon from 'sinon';
3
4
  import {ConnectionState, MediaConnectionEventNames} from '@webex/internal-media-core';
@@ -1,16 +1,15 @@
1
+ import 'jsdom-global/register';
1
2
  import * as InternalMediaCoreModule from '@webex/internal-media-core';
2
3
  import Media from '@webex/plugin-meetings/src/media/index';
3
4
  import {assert} from '@webex/test-helper-chai';
4
5
  import sinon from 'sinon';
5
6
  import StaticConfig from '@webex/plugin-meetings/src/common/config';
6
- import MockWebex from '@webex/test-helper-mock-webex';
7
7
 
8
8
  describe('createMediaConnection', () => {
9
9
  let clock;
10
10
  beforeEach(() => {
11
11
  clock = sinon.useFakeTimers();
12
12
  });
13
- const webex = MockWebex();
14
13
 
15
14
  const fakeRoapMediaConnection = {
16
15
  id: 'roap media connection',
@@ -61,7 +60,7 @@ describe('createMediaConnection', () => {
61
60
  const ENABLE_EXTMAP = false;
62
61
  const ENABLE_RTX = true;
63
62
 
64
- Media.createMediaConnection(false, 'some debug id', webex, 'meetingId', 'correlationId', {
63
+ Media.createMediaConnection(false, 'some debug id', 'meetingId', {
65
64
  mediaProperties: {
66
65
  mediaDirection: {
67
66
  sendAudio: false,
@@ -139,7 +138,13 @@ describe('createMediaConnection', () => {
139
138
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
140
139
  .returns(fakeRoapMediaConnection);
141
140
 
142
- Media.createMediaConnection(true, 'some debug id', webex, 'meeting id', 'correlationId', {
141
+ const rtcMetrics = {
142
+ addMetrics: sinon.stub(),
143
+ closeMetrics: sinon.stub(),
144
+ sendMetricsInQueue: sinon.stub(),
145
+ };
146
+
147
+ Media.createMediaConnection(true, 'some debug id', 'meeting id', {
143
148
  mediaProperties: {
144
149
  mediaDirection: {
145
150
  sendAudio: true,
@@ -150,6 +155,7 @@ describe('createMediaConnection', () => {
150
155
  receiveShare: true,
151
156
  },
152
157
  },
158
+ rtcMetrics,
153
159
  turnServerInfo: {
154
160
  url: 'turns:turn-server-url:443?transport=tcp',
155
161
  username: 'turn username',
@@ -177,6 +183,27 @@ describe('createMediaConnection', () => {
177
183
  },
178
184
  'meeting id'
179
185
  );
186
+
187
+ // check if rtcMetrics callbacks are configured correctly
188
+ const addMetricsCallback = multistreamRoapMediaConnectionConstructorStub.getCalls()[0].args[2];
189
+ const closeMetricsCallback = multistreamRoapMediaConnectionConstructorStub.getCalls()[0].args[3];
190
+ const sendMetricsInQueueCallback = multistreamRoapMediaConnectionConstructorStub.getCalls()[0].args[4];
191
+
192
+ assert.isFunction(addMetricsCallback);
193
+ assert.isFunction(closeMetricsCallback);
194
+ assert.isFunction(sendMetricsInQueueCallback);
195
+
196
+ const fakeMetricsData = {id: 'metrics data'};
197
+
198
+ addMetricsCallback(fakeMetricsData);
199
+ assert.calledOnceWithExactly(rtcMetrics.addMetrics, fakeMetricsData);
200
+
201
+ closeMetricsCallback();
202
+ assert.calledOnce(rtcMetrics.closeMetrics);
203
+
204
+ sendMetricsInQueueCallback();
205
+ assert.calledOnce(rtcMetrics.sendMetricsInQueue);
206
+
180
207
  });
181
208
 
182
209
  [
@@ -191,7 +218,7 @@ describe('createMediaConnection', () => {
191
218
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
192
219
  .returns(fakeRoapMediaConnection);
193
220
 
194
- Media.createMediaConnection(true, 'debug string', webex, 'meeting id', 'correlationId', {
221
+ Media.createMediaConnection(true, 'debug string', 'meeting id', {
195
222
  mediaProperties: {
196
223
  mediaDirection: {
197
224
  sendAudio: true,
@@ -220,7 +247,7 @@ describe('createMediaConnection', () => {
220
247
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
221
248
  .returns(fakeRoapMediaConnection);
222
249
 
223
- Media.createMediaConnection(true, 'debug string', webex, 'meeting id', 'correlationId', {
250
+ Media.createMediaConnection(true, 'debug string', 'meeting id', {
224
251
  mediaProperties: {
225
252
  mediaDirection: {
226
253
  sendAudio: true,
@@ -260,7 +287,7 @@ describe('createMediaConnection', () => {
260
287
  const ENABLE_EXTMAP = false;
261
288
  const ENABLE_RTX = true;
262
289
 
263
- Media.createMediaConnection(false, 'some debug id', webex, 'meeting id', 'correlationId', {
290
+ Media.createMediaConnection(false, 'some debug id', 'meeting id', {
264
291
  mediaProperties: {
265
292
  mediaDirection: {
266
293
  sendAudio: true,
@@ -1,8 +1,8 @@
1
+ import 'jsdom-global/register';
1
2
  import {assert} from '@webex/test-helper-chai';
2
3
  import sinon from 'sinon';
3
4
  import {ConnectionState} from '@webex/internal-media-core';
4
5
  import MediaProperties from '@webex/plugin-meetings/src/media/properties';
5
- import testUtils from '../../../utils/testUtils';
6
6
  import {Defer} from '@webex/common';
7
7
  import MediaConnectionAwaiter from '../../../../src/media/MediaConnectionAwaiter';
8
8
 
@@ -1,3 +1,4 @@
1
+ import 'jsdom-global/register'
1
2
  import sinon from 'sinon';
2
3
  import {assert} from '@webex/test-helper-chai';
3
4
  import {
@@ -78,6 +78,7 @@ describe('plugin-meetings', () => {
78
78
  supportHDV: null,
79
79
  canShareWhiteBoard: null,
80
80
  enforceVirtualBackground: null,
81
+ canPollingAndQA: null,
81
82
  ...expected,
82
83
  };
83
84
 
@@ -161,6 +162,7 @@ describe('plugin-meetings', () => {
161
162
  'supportHDV',
162
163
  'canShareWhiteBoard',
163
164
  'enforceVirtualBackground',
165
+ 'canPollingAndQA',
164
166
  ].forEach((key) => {
165
167
  it(`get and set for ${key} work as expected`, () => {
166
168
  const inMeetingActions = new InMeetingActions();
@@ -5,6 +5,7 @@ import 'jsdom-global/register';
5
5
  import {cloneDeep, forEach, isEqual, isUndefined} from 'lodash';
6
6
  import sinon from 'sinon';
7
7
  import * as InternalMediaCoreModule from '@webex/internal-media-core';
8
+ import * as RemoteMediaManagerModule from '@webex/plugin-meetings/src/multistream/remoteMediaManager';
8
9
  import StateMachine from 'javascript-state-machine';
9
10
  import uuid from 'uuid';
10
11
  import {assert, expect} from '@webex/test-helper-chai';
@@ -305,7 +306,7 @@ describe('plugin-meetings', () => {
305
306
  assert.equal(meeting.resource, uuid2);
306
307
  assert.equal(meeting.deviceUrl, uuid3);
307
308
  assert.equal(meeting.correlationId, correlationId);
308
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
309
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
309
310
  assert.deepEqual(meeting.meetingInfo, {});
310
311
  assert.instanceOf(meeting.members, Members);
311
312
  assert.calledOnceWithExactly(
@@ -329,6 +330,7 @@ describe('plugin-meetings', () => {
329
330
  assert.isNull(meeting.partner);
330
331
  assert.isNull(meeting.type);
331
332
  assert.isNull(meeting.owner);
333
+ assert.isUndefined(meeting.isoLocalClientMeetingJoinTime);
332
334
  assert.isNull(meeting.hostId);
333
335
  assert.isNull(meeting.policy);
334
336
  assert.instanceOf(meeting.meetingRequest, MeetingRequest);
@@ -373,7 +375,7 @@ describe('plugin-meetings', () => {
373
375
  }
374
376
  );
375
377
  assert.equal(newMeeting.correlationId, newMeeting.id);
376
- assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id});
378
+ assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id, sessionCorrelationId: ''});
377
379
  });
378
380
 
379
381
  it('correlationId can be provided in callStateForMetrics', () => {
@@ -400,6 +402,37 @@ describe('plugin-meetings', () => {
400
402
  correlationId: uuid4,
401
403
  joinTrigger: 'fake-join-trigger',
402
404
  loginType: 'fake-login-type',
405
+ sessionCorrelationId: '',
406
+ });
407
+ });
408
+
409
+ it('sessionCorrelationId can be provided in callStateForMetrics', () => {
410
+ const newMeeting = new Meeting(
411
+ {
412
+ userId: uuid1,
413
+ resource: uuid2,
414
+ deviceUrl: uuid3,
415
+ locus: {url: url1},
416
+ destination: testDestination,
417
+ destinationType: DESTINATION_TYPE.MEETING_ID,
418
+ callStateForMetrics: {
419
+ correlationId: uuid4,
420
+ sessionCorrelationId: uuid1,
421
+ joinTrigger: 'fake-join-trigger',
422
+ loginType: 'fake-login-type',
423
+ },
424
+ },
425
+ {
426
+ parent: webex,
427
+ }
428
+ );
429
+ assert.exists(newMeeting.sessionCorrelationId);
430
+ assert.equal(newMeeting.sessionCorrelationId, uuid1);
431
+ assert.deepEqual(newMeeting.callStateForMetrics, {
432
+ correlationId: uuid4,
433
+ sessionCorrelationId: uuid1,
434
+ joinTrigger: 'fake-join-trigger',
435
+ loginType: 'fake-login-type',
403
436
  });
404
437
  });
405
438
 
@@ -1585,6 +1618,10 @@ describe('plugin-meetings', () => {
1585
1618
  sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
1586
1619
  });
1587
1620
 
1621
+ afterEach(() => {
1622
+ assert.exists(meeting.isoLocalClientMeetingJoinTime);
1623
+ });
1624
+
1588
1625
  it('should join the meeting and return promise', async () => {
1589
1626
  const join = meeting.join({pstnAudioType: 'dial-in'});
1590
1627
  meeting.config.enableAutomaticLLM = true;
@@ -1603,6 +1640,7 @@ describe('plugin-meetings', () => {
1603
1640
  const result = await join;
1604
1641
 
1605
1642
  assert.calledOnce(MeetingUtil.joinMeeting);
1643
+ assert.calledOnce(webex.internal.device.meetingStarted);
1606
1644
  assert.calledOnce(meeting.setLocus);
1607
1645
  assert.equal(result, joinMeetingResult);
1608
1646
  assert.calledWith(webex.internal.llm.on, 'online', meeting.handleLLMOnline);
@@ -2405,9 +2443,7 @@ describe('plugin-meetings', () => {
2405
2443
  Media.createMediaConnection,
2406
2444
  false,
2407
2445
  meeting.getMediaConnectionDebugId(),
2408
- webex,
2409
2446
  meeting.id,
2410
- meeting.correlationId,
2411
2447
  sinon.match({turnServerInfo: undefined})
2412
2448
  );
2413
2449
  assert.calledOnce(meeting.setMercuryListener);
@@ -2449,6 +2485,42 @@ describe('plugin-meetings', () => {
2449
2485
  checkWorking({allowMediaInLobby: true});
2450
2486
  });
2451
2487
 
2488
+ it('should create rtcMetrics and pass them to Media.createMediaConnection()', async () => {
2489
+ const setIntervalOriginal = window.setInterval;
2490
+ window.setInterval = sinon.stub().returns(1);
2491
+
2492
+ // setup the minimum mocks required for multistream connection
2493
+ fakeMediaConnection.createSendSlot = sinon.stub().returns({
2494
+ publishStream: sinon.stub(),
2495
+ unpublishStream: sinon.stub(),
2496
+ setNamedMediaGroups: sinon.stub(),
2497
+ });
2498
+ sinon.stub(RemoteMediaManagerModule, 'RemoteMediaManager').returns({
2499
+ start: sinon.stub().resolves(),
2500
+ on: sinon.stub(),
2501
+ logAllReceiveSlots: sinon.stub(),
2502
+ });
2503
+
2504
+ meeting.meetingState = 'ACTIVE';
2505
+ meeting.isMultistream = true;
2506
+
2507
+ await meeting.addMedia({
2508
+ mediaSettings: {},
2509
+ });
2510
+
2511
+ // check that rtcMetrics was passed to Media.createMediaConnection
2512
+ assert.calledOnce(Media.createMediaConnection);
2513
+ assert.calledWith(
2514
+ Media.createMediaConnection,
2515
+ true,
2516
+ meeting.getMediaConnectionDebugId(),
2517
+ meeting.id,
2518
+ sinon.match.hasNested('rtcMetrics.webex', webex)
2519
+ );
2520
+
2521
+ window.setInterval = setIntervalOriginal;
2522
+ });
2523
+
2452
2524
  it('should pass the turn server info to the peer connection', async () => {
2453
2525
  const FAKE_TURN_URL = 'turns:webex.com:3478';
2454
2526
  const FAKE_TURN_USER = 'some-turn-username';
@@ -2478,9 +2550,7 @@ describe('plugin-meetings', () => {
2478
2550
  Media.createMediaConnection,
2479
2551
  false,
2480
2552
  meeting.getMediaConnectionDebugId(),
2481
- webex,
2482
2553
  meeting.id,
2483
- meeting.correlationId,
2484
2554
  sinon.match({
2485
2555
  turnServerInfo: {
2486
2556
  url: FAKE_TURN_URL,
@@ -3023,6 +3093,8 @@ describe('plugin-meetings', () => {
3023
3093
  }),
3024
3094
  };
3025
3095
  meeting.iceCandidatesCount = 3;
3096
+ meeting.iceCandidateErrors.set('701_error', 3);
3097
+ meeting.iceCandidateErrors.set('701_turn_host_lookup_received_error', 1);
3026
3098
 
3027
3099
  await meeting.addMedia({
3028
3100
  mediaSettings: {},
@@ -3044,6 +3116,8 @@ describe('plugin-meetings', () => {
3044
3116
  someReachabilityMetric1: 'some value1',
3045
3117
  someReachabilityMetric2: 'some value2',
3046
3118
  iceCandidatesCount: 3,
3119
+ '701_error': 3,
3120
+ '701_turn_host_lookup_received_error': 1,
3047
3121
  }
3048
3122
  );
3049
3123
 
@@ -3397,9 +3471,7 @@ describe('plugin-meetings', () => {
3397
3471
  Media.createMediaConnection,
3398
3472
  false,
3399
3473
  meeting.getMediaConnectionDebugId(),
3400
- webex,
3401
3474
  meeting.id,
3402
- meeting.correlationId,
3403
3475
  sinon.match({
3404
3476
  turnServerInfo: {
3405
3477
  url: FAKE_TURN_URL,
@@ -4240,6 +4312,20 @@ describe('plugin-meetings', () => {
4240
4312
  assert.calledTwice(locusMediaRequestStub);
4241
4313
  });
4242
4314
 
4315
+ it('addMedia() works correctly when media is disabled with no streams to publish', async () => {
4316
+ const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4317
+ await meeting.addMedia({audioEnabled: false});
4318
+ //calling handleDeviceLogging with audioEnaled as true adn videoEnabled as false
4319
+ assert.calledWith(handleDeviceLoggingSpy,false,true);
4320
+ });
4321
+
4322
+ it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
4323
+ const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4324
+ await meeting.addMedia({videoEnabled: false});
4325
+ //calling handleDeviceLogging audioEnabled as true videoEnabled as false
4326
+ assert.calledWith(handleDeviceLoggingSpy,true,false);
4327
+ });
4328
+
4243
4329
  it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
4244
4330
  await meeting.addMedia({videoEnabled: false});
4245
4331
  await simulateRoapOffer();
@@ -4306,6 +4392,14 @@ describe('plugin-meetings', () => {
4306
4392
  assert.calledTwice(locusMediaRequestStub);
4307
4393
  });
4308
4394
 
4395
+
4396
+ it('addMedia() works correctly when both shareAudio and shareVideo is disabled with no streams publish', async () => {
4397
+ const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4398
+ await meeting.addMedia({shareAudioEnabled: false, shareVideoEnabled: false});
4399
+ //calling handleDeviceLogging with audioEnabled true and videoEnabled as true
4400
+ assert.calledWith(handleDeviceLoggingSpy,true,true);
4401
+ });
4402
+
4309
4403
  describe('publishStreams()/unpublishStreams() calls', () => {
4310
4404
  [
4311
4405
  {mediaEnabled: true, expected: {direction: 'sendrecv', localMuteSentValue: false}},
@@ -6861,33 +6955,36 @@ describe('plugin-meetings', () => {
6861
6955
  describe('#setCorrelationId', () => {
6862
6956
  it('should set the correlationId and return undefined', () => {
6863
6957
  assert.equal(meeting.correlationId, correlationId);
6864
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
6958
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6865
6959
  meeting.setCorrelationId(uuid1);
6866
6960
  assert.equal(meeting.correlationId, uuid1);
6867
- assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1});
6961
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, sessionCorrelationId: ''});
6868
6962
  });
6869
6963
  });
6870
6964
 
6871
6965
  describe('#updateCallStateForMetrics', () => {
6872
6966
  it('should update the callState, overriding existing values', () => {
6873
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
6967
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6874
6968
  meeting.updateCallStateForMetrics({
6875
6969
  correlationId: uuid1,
6970
+ sessionCorrelationId: uuid3,
6876
6971
  joinTrigger: 'jt',
6877
6972
  loginType: 'lt',
6878
6973
  });
6879
6974
  assert.deepEqual(meeting.callStateForMetrics, {
6880
6975
  correlationId: uuid1,
6976
+ sessionCorrelationId: uuid3,
6881
6977
  joinTrigger: 'jt',
6882
6978
  loginType: 'lt',
6883
6979
  });
6884
6980
  });
6885
6981
 
6886
6982
  it('should update the callState, keeping non-supplied values', () => {
6887
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
6983
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6888
6984
  meeting.updateCallStateForMetrics({joinTrigger: 'jt', loginType: 'lt'});
6889
6985
  assert.deepEqual(meeting.callStateForMetrics, {
6890
6986
  correlationId,
6987
+ sessionCorrelationId: '',
6891
6988
  joinTrigger: 'jt',
6892
6989
  loginType: 'lt',
6893
6990
  });
@@ -8450,6 +8547,9 @@ describe('plugin-meetings', () => {
8450
8547
  it('listens to the self admitted guest event', (done) => {
8451
8548
  meeting.stopKeepAlive = sinon.stub();
8452
8549
  meeting.updateLLMConnection = sinon.stub();
8550
+ meeting.rtcMetrics = {
8551
+ sendNextMetrics: sinon.stub(),
8552
+ };
8453
8553
  meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_ADMITTED_GUEST', test1);
8454
8554
  assert.calledOnceWithExactly(meeting.stopKeepAlive);
8455
8555
  assert.calledThrice(TriggerProxy.trigger);
@@ -8461,6 +8561,8 @@ describe('plugin-meetings', () => {
8461
8561
  {payload: test1}
8462
8562
  );
8463
8563
  assert.calledOnce(meeting.updateLLMConnection);
8564
+ assert.calledOnceWithExactly(meeting.rtcMetrics.sendNextMetrics);
8565
+
8464
8566
  done();
8465
8567
  });
8466
8568
 
@@ -9766,6 +9868,11 @@ describe('plugin-meetings', () => {
9766
9868
  requiredDisplayHints: [],
9767
9869
  requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
9768
9870
  },
9871
+ {
9872
+ actionName: 'canPollingAndQA',
9873
+ requiredDisplayHints: [],
9874
+ requiredPolicies: [SELF_POLICY.SUPPORT_POLLING_AND_QA],
9875
+ },
9769
9876
  ],
9770
9877
  ({
9771
9878
  actionName,
@@ -1,6 +1,7 @@
1
+ import 'jsdom-global/register';
1
2
  import sinon from 'sinon';
2
3
  import {assert} from '@webex/test-helper-chai';
3
- import { cloneDeep, defer } from 'lodash';
4
+ import { cloneDeep } from 'lodash';
4
5
 
5
6
  import MockWebex from '@webex/test-helper-mock-webex';
6
7
  import Meetings from '@webex/plugin-meetings';
@@ -495,4 +496,4 @@ describe('LocusMediaRequest.send()', () => {
495
496
  });
496
497
 
497
498
  });
498
- })
499
+ })
@@ -1,3 +1,4 @@
1
+ import 'jsdom-global/register';
1
2
  import sinon from 'sinon';
2
3
  import {assert} from '@webex/test-helper-chai';
3
4
  import MockWebex from '@webex/test-helper-mock-webex';
@@ -1,3 +1,4 @@
1
+ import 'jsdom-global/register';
1
2
  import sinon from 'sinon';
2
3
  import {assert} from '@webex/test-helper-chai';
3
4
  import Meetings from '@webex/plugin-meetings';
@@ -71,6 +72,7 @@ describe('plugin-meetings', () => {
71
72
  assert.calledOnce(meeting.updateLLMConnection);
72
73
  assert.calledOnce(meeting.breakouts.cleanUp);
73
74
  assert.calledOnce(meeting.simultaneousInterpretation.cleanUp);
75
+ assert.calledOnce(webex.internal.device.meetingEnded);
74
76
  });
75
77
 
76
78
  it('do clean up on meeting object with LLM disabled', async () => {
@@ -87,6 +89,7 @@ describe('plugin-meetings', () => {
87
89
  assert.notCalled(meeting.updateLLMConnection);
88
90
  assert.calledOnce(meeting.breakouts.cleanUp);
89
91
  assert.calledOnce(meeting.simultaneousInterpretation.cleanUp);
92
+ assert.calledOnce(webex.internal.device.meetingEnded);
90
93
  });
91
94
 
92
95
  it('do clean up on meeting object with no config', async () => {
@@ -102,6 +105,7 @@ describe('plugin-meetings', () => {
102
105
  assert.notCalled(meeting.updateLLMConnection);
103
106
  assert.calledOnce(meeting.breakouts.cleanUp);
104
107
  assert.calledOnce(meeting.simultaneousInterpretation.cleanUp);
108
+ assert.calledOnce(webex.internal.device.meetingEnded);
105
109
  });
106
110
  });
107
111
 
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
3
  */
4
-
4
+ import 'jsdom-global/register';
5
5
  import {assert} from '@webex/test-helper-chai';
6
6
  import sinon from 'sinon';
7
7
  import MockWebex from '@webex/test-helper-mock-webex';
@@ -23,7 +23,6 @@ import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
23
23
  import Metrics from '@webex/plugin-meetings/src/metrics';
24
24
  import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
25
25
  import {forEach} from 'lodash';
26
- import { request } from 'express';
27
26
 
28
27
  describe('plugin-meetings', () => {
29
28
  const conversation = {
@@ -433,7 +432,7 @@ describe('plugin-meetings', () => {
433
432
  assert.deepEqual(submitInternalEventCalls[1].args[0], {
434
433
  name: 'internal.client.meetinginfo.response',
435
434
  });
436
-
435
+
437
436
  assert.deepEqual(submitClientEventCalls[1].args[0], {
438
437
  name: 'client.meetinginfo.response',
439
438
  payload: {
@@ -484,9 +483,9 @@ describe('plugin-meetings', () => {
484
483
  requestResponse.body.confIdStr = confIdStr;
485
484
  }
486
485
  const extraParams = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'}
487
-
486
+
488
487
  webex.request.resolves(requestResponse);
489
-
488
+
490
489
  const result = await meetingInfo.fetchMeetingInfo(
491
490
  '1234323',
492
491
  DESTINATION_TYPE.MEETING_ID,
@@ -497,7 +496,7 @@ describe('plugin-meetings', () => {
497
496
  extraParams,
498
497
  {meetingId, sendCAevents}
499
498
  );
500
-
499
+
501
500
  assert.calledWith(webex.request, {
502
501
  method: 'POST',
503
502
  service: WBXAPPAPI_SERVICE,
@@ -515,7 +514,7 @@ describe('plugin-meetings', () => {
515
514
  Metrics.sendBehavioralMetric,
516
515
  BEHAVIORAL_METRICS.FETCH_MEETING_INFO_V1_SUCCESS
517
516
  );
518
-
517
+
519
518
  const submitInternalEventCalls = webex.internal.newMetrics.submitInternalEvent.getCalls();
520
519
  const submitClientEventCalls = webex.internal.newMetrics.submitClientEvent.getCalls();
521
520
 
@@ -529,7 +528,7 @@ describe('plugin-meetings', () => {
529
528
  meetingId,
530
529
  }
531
530
  });
532
-
531
+
533
532
  assert.deepEqual(submitInternalEventCalls[1].args[0], {
534
533
  name: 'internal.client.meetinginfo.response',
535
534
  });
@@ -591,7 +590,7 @@ describe('plugin-meetings', () => {
591
590
 
592
591
  const submitInternalEventCalls = webex.internal.newMetrics.submitInternalEvent.getCalls();
593
592
  const submitClientEventCalls = webex.internal.newMetrics.submitClientEvent.getCalls();
594
-
593
+
595
594
  assert.deepEqual(submitInternalEventCalls[0].args[0], {
596
595
  name: 'internal.client.meetinginfo.request',
597
596
  });
@@ -601,7 +600,7 @@ describe('plugin-meetings', () => {
601
600
  meetingId: 'meetingId',
602
601
  }
603
602
  });
604
-
603
+
605
604
  assert.deepEqual(submitInternalEventCalls[1].args[0], {
606
605
  name: 'internal.client.meetinginfo.response',
607
606
  });
@@ -629,7 +628,7 @@ describe('plugin-meetings', () => {
629
628
  it(`should not send CA metric if meetingId is not provided disregarding if sendCAevents is ${sendCAevents}`, async () => {
630
629
  const message = 'a message';
631
630
  const meetingInfoData = 'meeting info';
632
-
631
+
633
632
  webex.request = sinon.stub().rejects({
634
633
  statusCode: 403,
635
634
  body: {message, code: 403102, data: {meetingInfo: meetingInfoData}},
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
3
  */
4
-
4
+ import 'jsdom-global/register';
5
5
  import {assert} from '@webex/test-helper-chai';
6
6
  import sinon from 'sinon';
7
7
  import MockWebex from '@webex/test-helper-mock-webex';