@webex/plugin-meetings 3.4.0-next.9 → 3.5.0-next.1

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 (42) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/interpretation/index.js +1 -1
  4. package/dist/interpretation/siLanguage.js +1 -1
  5. package/dist/meeting/index.js +106 -12
  6. package/dist/meeting/index.js.map +1 -1
  7. package/dist/meeting/util.js +1 -0
  8. package/dist/meeting/util.js.map +1 -1
  9. package/dist/meetings/index.js +7 -0
  10. package/dist/meetings/index.js.map +1 -1
  11. package/dist/types/meeting/index.d.ts +20 -0
  12. package/dist/types/meetings/index.d.ts +2 -1
  13. package/dist/webinar/index.js +1 -1
  14. package/package.json +22 -22
  15. package/src/meeting/index.ts +73 -4
  16. package/src/meeting/util.ts +2 -0
  17. package/src/meetings/index.ts +7 -1
  18. package/test/integration/spec/converged-space-meetings.js +1 -1
  19. package/test/unit/spec/breakouts/index.ts +1 -0
  20. package/test/unit/spec/interceptors/locusRetry.ts +11 -10
  21. package/test/unit/spec/media/MediaConnectionAwaiter.ts +1 -0
  22. package/test/unit/spec/media/index.ts +1 -0
  23. package/test/unit/spec/media/properties.ts +1 -1
  24. package/test/unit/spec/meeting/connectionStateHandler.ts +1 -0
  25. package/test/unit/spec/meeting/index.js +67 -6
  26. package/test/unit/spec/meeting/locusMediaRequest.ts +3 -2
  27. package/test/unit/spec/meeting/request.js +1 -0
  28. package/test/unit/spec/meeting/utils.js +4 -0
  29. package/test/unit/spec/meeting-info/meetinginfov2.js +10 -11
  30. package/test/unit/spec/meeting-info/request.js +1 -1
  31. package/test/unit/spec/meetings/index.js +10 -2
  32. package/test/unit/spec/members/request.js +2 -1
  33. package/test/unit/spec/multistream/mediaRequestManager.ts +1 -0
  34. package/test/unit/spec/multistream/receiveSlot.ts +1 -0
  35. package/test/unit/spec/multistream/receiveSlotManager.ts +1 -0
  36. package/test/unit/spec/multistream/remoteMedia.ts +1 -0
  37. package/test/unit/spec/multistream/remoteMediaGroup.ts +1 -0
  38. package/test/unit/spec/multistream/remoteMediaManager.ts +1 -0
  39. package/test/unit/spec/multistream/sendSlotManager.ts +1 -0
  40. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +0 -1
  41. package/test/unit/spec/reachability/request.js +1 -0
  42. package/test/unit/spec/roap/request.ts +1 -0
package/package.json CHANGED
@@ -43,13 +43,13 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.4.0-next.9",
47
- "@webex/plugin-rooms": "3.4.0-next.2",
48
- "@webex/test-helper-chai": "3.4.0-next.2",
49
- "@webex/test-helper-mocha": "3.4.0-next.2",
50
- "@webex/test-helper-mock-webex": "3.4.0-next.2",
51
- "@webex/test-helper-retry": "3.4.0-next.2",
52
- "@webex/test-helper-test-users": "3.4.0-next.2",
46
+ "@webex/plugin-meetings": "3.5.0-next.1",
47
+ "@webex/plugin-rooms": "3.5.0-next.1",
48
+ "@webex/test-helper-chai": "3.5.0-next.1",
49
+ "@webex/test-helper-mocha": "3.5.0-next.1",
50
+ "@webex/test-helper-mock-webex": "3.5.0-next.1",
51
+ "@webex/test-helper-retry": "3.5.0-next.1",
52
+ "@webex/test-helper-test-users": "3.5.0-next.1",
53
53
  "chai": "^4.3.4",
54
54
  "chai-as-promised": "^7.1.1",
55
55
  "eslint": "^8.24.0",
@@ -61,21 +61,21 @@
61
61
  "typescript": "^4.7.4"
62
62
  },
63
63
  "dependencies": {
64
- "@webex/common": "3.4.0-next.2",
65
- "@webex/internal-media-core": "2.10.2",
66
- "@webex/internal-plugin-conversation": "3.4.0-next.2",
67
- "@webex/internal-plugin-device": "3.4.0-next.2",
68
- "@webex/internal-plugin-llm": "3.4.0-next.2",
69
- "@webex/internal-plugin-mercury": "3.4.0-next.2",
70
- "@webex/internal-plugin-metrics": "3.4.0-next.2",
71
- "@webex/internal-plugin-support": "3.4.0-next.2",
72
- "@webex/internal-plugin-user": "3.4.0-next.2",
73
- "@webex/internal-plugin-voicea": "3.4.0-next.9",
74
- "@webex/media-helpers": "3.4.0-next.3",
75
- "@webex/plugin-people": "3.4.0-next.2",
76
- "@webex/plugin-rooms": "3.4.0-next.2",
64
+ "@webex/common": "3.5.0-next.1",
65
+ "@webex/internal-media-core": "2.11.1",
66
+ "@webex/internal-plugin-conversation": "3.5.0-next.1",
67
+ "@webex/internal-plugin-device": "3.5.0-next.1",
68
+ "@webex/internal-plugin-llm": "3.5.0-next.1",
69
+ "@webex/internal-plugin-mercury": "3.5.0-next.1",
70
+ "@webex/internal-plugin-metrics": "3.5.0-next.1",
71
+ "@webex/internal-plugin-support": "3.5.0-next.1",
72
+ "@webex/internal-plugin-user": "3.5.0-next.1",
73
+ "@webex/internal-plugin-voicea": "3.5.0-next.1",
74
+ "@webex/media-helpers": "3.5.0-next.1",
75
+ "@webex/plugin-people": "3.5.0-next.1",
76
+ "@webex/plugin-rooms": "3.5.0-next.1",
77
77
  "@webex/web-capabilities": "^1.4.0",
78
- "@webex/webex-core": "3.4.0-next.2",
78
+ "@webex/webex-core": "3.5.0-next.1",
79
79
  "ampersand-collection": "^2.0.2",
80
80
  "bowser": "^2.11.0",
81
81
  "btoa": "^1.2.1",
@@ -91,5 +91,5 @@
91
91
  "//": [
92
92
  "TODO: upgrade jwt-decode when moving to node 18"
93
93
  ],
94
- "version": "3.4.0-next.9"
94
+ "version": "3.5.0-next.1"
95
95
  }
@@ -227,6 +227,7 @@ export type AddMediaOptions = {
227
227
 
228
228
  export type CallStateForMetrics = {
229
229
  correlationId?: string;
230
+ sessionCorrelationId?: string;
230
231
  joinTrigger?: string;
231
232
  loginType?: string;
232
233
  };
@@ -538,6 +539,7 @@ export default class Meeting extends StatelessWebexPlugin {
538
539
  id: string;
539
540
  isMultistream: boolean;
540
541
  locusUrl: string;
542
+ #isoLocalClientMeetingJoinTime?: string;
541
543
  mediaConnections: any[];
542
544
  mediaId?: string;
543
545
  meetingFiniteStateMachine: any;
@@ -741,12 +743,29 @@ export default class Meeting extends StatelessWebexPlugin {
741
743
  */
742
744
  this.callStateForMetrics = attrs.callStateForMetrics || {};
743
745
  const correlationId = attrs.correlationId || attrs.callStateForMetrics?.correlationId;
746
+ const sessionCorrelationId =
747
+ attrs.sessionCorrelationId || attrs.callStateForMetrics?.sessionCorrelationId;
748
+ if (sessionCorrelationId) {
749
+ LoggerProxy.logger.log(
750
+ `Meetings:index#constructor --> Initializing the meeting object with session correlation id from app ${correlationId}`
751
+ );
752
+ this.callStateForMetrics.sessionCorrelationId = sessionCorrelationId;
753
+ } else {
754
+ LoggerProxy.logger.log(
755
+ `Meetings:index#constructor --> No session correlation id supplied. None will be generated and this field will remain blank`
756
+ );
757
+ // TODO: supply a session from the meetings instance
758
+ this.callStateForMetrics.sessionCorrelationId = '';
759
+ }
744
760
  if (correlationId) {
745
761
  LoggerProxy.logger.log(
746
762
  `Meetings:index#constructor --> Initializing the meeting object with correlation id from app ${correlationId}`
747
763
  );
748
764
  this.callStateForMetrics.correlationId = correlationId;
749
765
  } else {
766
+ LoggerProxy.logger.log(
767
+ `Meetings:index#constructor --> Initializing the meeting object with generated correlation id from sdk ${this.id}`
768
+ );
750
769
  this.callStateForMetrics.correlationId = this.id;
751
770
  }
752
771
  /**
@@ -1521,6 +1540,17 @@ export default class Meeting extends StatelessWebexPlugin {
1521
1540
  * @memberof Meeting
1522
1541
  */
1523
1542
  this.iceCandidatesCount = 0;
1543
+
1544
+ /**
1545
+ * Start time of meeting as an ISO string
1546
+ * based on browser time, so can only be used to compute durations client side
1547
+ * undefined if meeting has not been joined, set once on meeting join, and not updated again
1548
+ * @instance
1549
+ * @type {string}
1550
+ * @private
1551
+ * @memberof Meeting
1552
+ */
1553
+ this.#isoLocalClientMeetingJoinTime = undefined;
1524
1554
  }
1525
1555
 
1526
1556
  /**
@@ -1569,6 +1599,31 @@ export default class Meeting extends StatelessWebexPlugin {
1569
1599
  this.callStateForMetrics.correlationId = correlationId;
1570
1600
  }
1571
1601
 
1602
+ /**
1603
+ * Getter - Returns callStateForMetrics.sessionCorrelationId
1604
+ * @returns {string}
1605
+ */
1606
+ get sessionCorrelationId() {
1607
+ return this.callStateForMetrics.correlationId;
1608
+ }
1609
+
1610
+ /**
1611
+ * Setter - sets callStateForMetrics.sessionCorrelationId
1612
+ * @param {string} sessionCorrelationId
1613
+ */
1614
+ set sessionCorrelationId(sessionCorrelationId: string) {
1615
+ this.callStateForMetrics.sessionCorrelationId = sessionCorrelationId;
1616
+ }
1617
+
1618
+ /**
1619
+ * Getter - Returns isoLocalClientMeetingJoinTime
1620
+ * This will be set once on meeting join, and not updated again
1621
+ * @returns {string | undefined}
1622
+ */
1623
+ get isoLocalClientMeetingJoinTime(): string | undefined {
1624
+ return this.#isoLocalClientMeetingJoinTime;
1625
+ }
1626
+
1572
1627
  /**
1573
1628
  * Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
1574
1629
  * @param {any} info
@@ -5232,6 +5287,11 @@ export default class Meeting extends StatelessWebexPlugin {
5232
5287
  this.meetingFiniteStateMachine.join();
5233
5288
  this.setupLocusMediaRequest();
5234
5289
 
5290
+ // @ts-ignore
5291
+ this.webex.internal.device.meetingStarted();
5292
+
5293
+ this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
5294
+
5235
5295
  LoggerProxy.logger.log('Meeting:index#join --> Success');
5236
5296
 
5237
5297
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
@@ -6518,12 +6578,21 @@ export default class Meeting extends StatelessWebexPlugin {
6518
6578
  *
6519
6579
  * @private
6520
6580
  * @static
6581
+ * @param {boolean} isAudioEnabled
6582
+ * @param {boolean} isVideoEnabled
6521
6583
  * @returns {Promise<void>}
6522
6584
  */
6523
- private static async handleDeviceLogging(): Promise<void> {
6524
- try {
6525
- const devices = await getDevices();
6526
6585
 
6586
+ private static async handleDeviceLogging(isAudioEnabled, isVideoEnabled): Promise<void> {
6587
+ try {
6588
+ let devices = [];
6589
+ if (isVideoEnabled && isAudioEnabled) {
6590
+ devices = await getDevices();
6591
+ } else if (isVideoEnabled) {
6592
+ devices = await getDevices(Media.DeviceKind.VIDEO_INPUT);
6593
+ } else if (isAudioEnabled) {
6594
+ devices = await getDevices(Media.DeviceKind.AUDIO_INPUT);
6595
+ }
6527
6596
  MeetingUtil.handleDeviceLogging(devices);
6528
6597
  } catch {
6529
6598
  // getDevices may fail if we don't have browser permissions, that's ok, we still can have a media connection
@@ -7016,7 +7085,7 @@ export default class Meeting extends StatelessWebexPlugin {
7016
7085
  );
7017
7086
 
7018
7087
  if (audioEnabled || videoEnabled) {
7019
- await Meeting.handleDeviceLogging();
7088
+ await Meeting.handleDeviceLogging(audioEnabled, videoEnabled);
7020
7089
  } else {
7021
7090
  LoggerProxy.logger.info(`${LOG_HEADER} device logging not required`);
7022
7091
  }
@@ -170,6 +170,8 @@ const MeetingUtil = {
170
170
  },
171
171
 
172
172
  cleanUp: (meeting) => {
173
+ meeting.getWebexObject().internal.device.meetingEnded();
174
+
173
175
  meeting.breakouts.cleanUp();
174
176
  meeting.simultaneousInterpretation.cleanUp();
175
177
  meeting.locusMediaRequest = undefined;
@@ -1081,6 +1081,7 @@ export default class Meetings extends WebexPlugin {
1081
1081
  * @param {CallStateForMetrics} callStateForMetrics - information about call state for metrics
1082
1082
  * @param {Object} [meetingInfo] - Pre-fetched complete meeting info
1083
1083
  * @param {String} [meetingLookupUrl] - meeting info prefetch url
1084
+ * @param {string} sessionCorrelationId - the optional specified sessionCorrelationId (callStateForMetrics.sessionCorrelationId) can be provided instead
1084
1085
  * @returns {Promise<Meeting>} A new Meeting.
1085
1086
  * @public
1086
1087
  * @memberof Meetings
@@ -1094,7 +1095,8 @@ export default class Meetings extends WebexPlugin {
1094
1095
  failOnMissingMeetingInfo = false,
1095
1096
  callStateForMetrics: CallStateForMetrics = undefined,
1096
1097
  meetingInfo = undefined,
1097
- meetingLookupUrl = undefined
1098
+ meetingLookupUrl = undefined,
1099
+ sessionCorrelationId: string = undefined
1098
1100
  ) {
1099
1101
  // Validate meeting information based on the provided destination and
1100
1102
  // type. This must be performed prior to determining if the meeting is
@@ -1105,6 +1107,10 @@ export default class Meetings extends WebexPlugin {
1105
1107
  callStateForMetrics = {...(callStateForMetrics || {}), correlationId};
1106
1108
  }
1107
1109
 
1110
+ if (sessionCorrelationId) {
1111
+ callStateForMetrics = {...(callStateForMetrics || {}), sessionCorrelationId};
1112
+ }
1113
+
1108
1114
  return (
1109
1115
  this.meetingInfo
1110
1116
  .fetchInfoOptions(destination, type)
@@ -1,5 +1,5 @@
1
- import { config } from 'dotenv';
2
1
  import 'jsdom-global/register';
2
+ import {config} from 'dotenv';
3
3
  import {assert} from '@webex/test-helper-chai';
4
4
  import {skipInNode} from '@webex/test-helper-mocha';
5
5
  import BrowserDetection from '@webex/plugin-meetings/dist/common/browser-detection';
@@ -1,3 +1,4 @@
1
+ import 'jsdom-global/register';
1
2
  import {assert, expect} from '@webex/test-helper-chai';
2
3
  import Breakouts from '@webex/plugin-meetings/src/breakouts';
3
4
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
@@ -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,3 +1,4 @@
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';
@@ -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 {
@@ -307,7 +307,7 @@ describe('plugin-meetings', () => {
307
307
  assert.equal(meeting.resource, uuid2);
308
308
  assert.equal(meeting.deviceUrl, uuid3);
309
309
  assert.equal(meeting.correlationId, correlationId);
310
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
310
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
311
311
  assert.deepEqual(meeting.meetingInfo, {});
312
312
  assert.instanceOf(meeting.members, Members);
313
313
  assert.calledOnceWithExactly(
@@ -331,6 +331,7 @@ describe('plugin-meetings', () => {
331
331
  assert.isNull(meeting.partner);
332
332
  assert.isNull(meeting.type);
333
333
  assert.isNull(meeting.owner);
334
+ assert.isUndefined(meeting.isoLocalClientMeetingJoinTime);
334
335
  assert.isNull(meeting.hostId);
335
336
  assert.isNull(meeting.policy);
336
337
  assert.instanceOf(meeting.meetingRequest, MeetingRequest);
@@ -375,7 +376,7 @@ describe('plugin-meetings', () => {
375
376
  }
376
377
  );
377
378
  assert.equal(newMeeting.correlationId, newMeeting.id);
378
- assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id});
379
+ assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id, sessionCorrelationId: ''});
379
380
  });
380
381
 
381
382
  it('correlationId can be provided in callStateForMetrics', () => {
@@ -402,6 +403,36 @@ describe('plugin-meetings', () => {
402
403
  correlationId: uuid4,
403
404
  joinTrigger: 'fake-join-trigger',
404
405
  loginType: 'fake-login-type',
406
+ sessionCorrelationId: '',
407
+ });
408
+ });
409
+
410
+ it('sessionCorrelationId can be provided in callStateForMetrics', () => {
411
+ const newMeeting = new Meeting(
412
+ {
413
+ userId: uuid1,
414
+ resource: uuid2,
415
+ deviceUrl: uuid3,
416
+ locus: {url: url1},
417
+ destination: testDestination,
418
+ destinationType: DESTINATION_TYPE.MEETING_ID,
419
+ callStateForMetrics: {
420
+ correlationId: uuid4,
421
+ sessionCorrelationId: uuid1,
422
+ joinTrigger: 'fake-join-trigger',
423
+ loginType: 'fake-login-type',
424
+ },
425
+ },
426
+ {
427
+ parent: webex,
428
+ }
429
+ );
430
+ assert.exists(newMeeting.sessionCorrelationId);
431
+ assert.deepEqual(newMeeting.callStateForMetrics, {
432
+ correlationId: uuid4,
433
+ sessionCorrelationId: uuid1,
434
+ joinTrigger: 'fake-join-trigger',
435
+ loginType: 'fake-login-type',
405
436
  });
406
437
  });
407
438
 
@@ -1587,6 +1618,10 @@ describe('plugin-meetings', () => {
1587
1618
  sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
1588
1619
  });
1589
1620
 
1621
+ afterEach(() => {
1622
+ assert.exists(meeting.isoLocalClientMeetingJoinTime);
1623
+ });
1624
+
1590
1625
  it('should join the meeting and return promise', async () => {
1591
1626
  const join = meeting.join({pstnAudioType: 'dial-in'});
1592
1627
  meeting.config.enableAutomaticLLM = true;
@@ -1605,6 +1640,7 @@ describe('plugin-meetings', () => {
1605
1640
  const result = await join;
1606
1641
 
1607
1642
  assert.calledOnce(MeetingUtil.joinMeeting);
1643
+ assert.calledOnce(webex.internal.device.meetingStarted);
1608
1644
  assert.calledOnce(meeting.setLocus);
1609
1645
  assert.equal(result, joinMeetingResult);
1610
1646
  assert.calledWith(webex.internal.llm.on, 'online', meeting.handleLLMOnline);
@@ -4278,6 +4314,20 @@ describe('plugin-meetings', () => {
4278
4314
  assert.calledTwice(locusMediaRequestStub);
4279
4315
  });
4280
4316
 
4317
+ it('addMedia() works correctly when media is disabled with no streams to publish', async () => {
4318
+ const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4319
+ await meeting.addMedia({audioEnabled: false});
4320
+ //calling handleDeviceLogging with audioEnaled as true adn videoEnabled as false
4321
+ assert.calledWith(handleDeviceLoggingSpy,false,true);
4322
+ });
4323
+
4324
+ it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
4325
+ const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4326
+ await meeting.addMedia({videoEnabled: false});
4327
+ //calling handleDeviceLogging audioEnabled as true videoEnabled as false
4328
+ assert.calledWith(handleDeviceLoggingSpy,true,false);
4329
+ });
4330
+
4281
4331
  it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
4282
4332
  await meeting.addMedia({videoEnabled: false});
4283
4333
  await simulateRoapOffer();
@@ -4344,6 +4394,14 @@ describe('plugin-meetings', () => {
4344
4394
  assert.calledTwice(locusMediaRequestStub);
4345
4395
  });
4346
4396
 
4397
+
4398
+ it('addMedia() works correctly when both shareAudio and shareVideo is disabled with no streams publish', async () => {
4399
+ const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4400
+ await meeting.addMedia({shareAudioEnabled: false, shareVideoEnabled: false});
4401
+ //calling handleDeviceLogging with audioEnabled true and videoEnabled as true
4402
+ assert.calledWith(handleDeviceLoggingSpy,true,true);
4403
+ });
4404
+
4347
4405
  describe('publishStreams()/unpublishStreams() calls', () => {
4348
4406
  [
4349
4407
  {mediaEnabled: true, expected: {direction: 'sendrecv', localMuteSentValue: false}},
@@ -6899,33 +6957,36 @@ describe('plugin-meetings', () => {
6899
6957
  describe('#setCorrelationId', () => {
6900
6958
  it('should set the correlationId and return undefined', () => {
6901
6959
  assert.equal(meeting.correlationId, correlationId);
6902
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
6960
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6903
6961
  meeting.setCorrelationId(uuid1);
6904
6962
  assert.equal(meeting.correlationId, uuid1);
6905
- assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1});
6963
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, sessionCorrelationId: ''});
6906
6964
  });
6907
6965
  });
6908
6966
 
6909
6967
  describe('#updateCallStateForMetrics', () => {
6910
6968
  it('should update the callState, overriding existing values', () => {
6911
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
6969
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6912
6970
  meeting.updateCallStateForMetrics({
6913
6971
  correlationId: uuid1,
6972
+ sessionCorrelationId: uuid3,
6914
6973
  joinTrigger: 'jt',
6915
6974
  loginType: 'lt',
6916
6975
  });
6917
6976
  assert.deepEqual(meeting.callStateForMetrics, {
6918
6977
  correlationId: uuid1,
6978
+ sessionCorrelationId: uuid3,
6919
6979
  joinTrigger: 'jt',
6920
6980
  loginType: 'lt',
6921
6981
  });
6922
6982
  });
6923
6983
 
6924
6984
  it('should update the callState, keeping non-supplied values', () => {
6925
- assert.deepEqual(meeting.callStateForMetrics, {correlationId});
6985
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6926
6986
  meeting.updateCallStateForMetrics({joinTrigger: 'jt', loginType: 'lt'});
6927
6987
  assert.deepEqual(meeting.callStateForMetrics, {
6928
6988
  correlationId,
6989
+ sessionCorrelationId: '',
6929
6990
  joinTrigger: 'jt',
6930
6991
  loginType: 'lt',
6931
6992
  });
@@ -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