@webex/plugin-meetings 2.60.0-next.1 → 2.60.0-next.3

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 (62) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +1 -1
  4. package/dist/constants.js.map +1 -1
  5. package/dist/controls-options-manager/enums.js +2 -1
  6. package/dist/controls-options-manager/enums.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/parser.js +5 -5
  10. package/dist/locus-info/parser.js.map +1 -1
  11. package/dist/media/index.js +6 -5
  12. package/dist/media/index.js.map +1 -1
  13. package/dist/meeting/in-meeting-actions.js +4 -0
  14. package/dist/meeting/in-meeting-actions.js.map +1 -1
  15. package/dist/meeting/index.js +276 -150
  16. package/dist/meeting/index.js.map +1 -1
  17. package/dist/meeting-info/meeting-info-v2.js +3 -0
  18. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  19. package/dist/meeting-info/utilv2.js +14 -29
  20. package/dist/meeting-info/utilv2.js.map +1 -1
  21. package/dist/meetings/collection.js +17 -0
  22. package/dist/meetings/collection.js.map +1 -1
  23. package/dist/meetings/index.js +30 -9
  24. package/dist/meetings/index.js.map +1 -1
  25. package/dist/metrics/constants.js +3 -0
  26. package/dist/metrics/constants.js.map +1 -1
  27. package/dist/reconnection-manager/index.js +27 -28
  28. package/dist/reconnection-manager/index.js.map +1 -1
  29. package/dist/rtcMetrics/index.js +25 -0
  30. package/dist/rtcMetrics/index.js.map +1 -1
  31. package/dist/statsAnalyzer/index.js +21 -1
  32. package/dist/statsAnalyzer/index.js.map +1 -1
  33. package/dist/statsAnalyzer/mqaUtil.js +16 -16
  34. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  35. package/dist/webinar/index.js +1 -1
  36. package/package.json +21 -22
  37. package/src/constants.ts +10 -4
  38. package/src/controls-options-manager/enums.ts +2 -0
  39. package/src/locus-info/parser.ts +6 -6
  40. package/src/media/index.ts +5 -5
  41. package/src/meeting/in-meeting-actions.ts +8 -0
  42. package/src/meeting/index.ts +249 -120
  43. package/src/meeting-info/meeting-info-v2.ts +4 -0
  44. package/src/meeting-info/utilv2.ts +6 -19
  45. package/src/meetings/collection.ts +13 -0
  46. package/src/meetings/index.ts +28 -10
  47. package/src/metrics/constants.ts +3 -0
  48. package/src/reconnection-manager/index.ts +63 -68
  49. package/src/rtcMetrics/index.ts +24 -0
  50. package/src/statsAnalyzer/index.ts +30 -1
  51. package/src/statsAnalyzer/mqaUtil.ts +17 -14
  52. package/test/unit/spec/media/index.ts +20 -4
  53. package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
  54. package/test/unit/spec/meeting/index.js +1253 -157
  55. package/test/unit/spec/meeting/muteState.js +2 -1
  56. package/test/unit/spec/meeting-info/meetinginfov2.js +28 -0
  57. package/test/unit/spec/meetings/collection.js +12 -0
  58. package/test/unit/spec/meetings/index.js +382 -118
  59. package/test/unit/spec/member/util.js +0 -31
  60. package/test/unit/spec/reconnection-manager/index.js +42 -12
  61. package/test/unit/spec/rtcMetrics/index.ts +20 -0
  62. package/test/unit/spec/stats-analyzer/index.js +12 -2
@@ -3,6 +3,10 @@
3
3
  */
4
4
  import 'jsdom-global/register';
5
5
 
6
+ // Polyfill for crypto: https://github.com/jsdom/jsdom/issues/1612#issuecomment-663210638
7
+ import {Crypto} from '@peculiar/webcrypto';
8
+ global.crypto = new Crypto();
9
+
6
10
  import Device from '@webex/internal-plugin-device';
7
11
  import Mercury from '@webex/internal-plugin-mercury';
8
12
  import {assert} from '@webex/test-helper-chai';
@@ -32,10 +36,10 @@ import {
32
36
  EVENT_TRIGGERS,
33
37
  } from '../../../../src/constants';
34
38
  import CaptchaError from '@webex/plugin-meetings/src/common/errors/captcha-error';
35
- import { forEach } from 'lodash';
39
+ import {forEach} from 'lodash';
36
40
  import PasswordError from '@webex/plugin-meetings/src/common/errors/password-error';
37
41
  import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
38
- import {NoiseReductionEffect,VirtualBackgroundEffect} from '@webex/media-helpers';
42
+ import {NoiseReductionEffect, VirtualBackgroundEffect} from '@webex/media-helpers';
39
43
  import NoMeetingInfoError from '../../../../src/common/errors/no-meeting-info';
40
44
 
41
45
  describe('plugin-meetings', () => {
@@ -333,10 +337,10 @@ describe('plugin-meetings', () => {
333
337
  beforeEach(() => {
334
338
  webex.credentials = {
335
339
  supertoken: {
336
- access_token: "fake_token"
337
- }
340
+ access_token: 'fake_token',
341
+ },
338
342
  };
339
- })
343
+ });
340
344
 
341
345
  it('creates background effect', async () => {
342
346
  const result = await webex.meetings.createVirtualBackgroundEffect();
@@ -350,7 +354,7 @@ describe('plugin-meetings', () => {
350
354
  generator: 'worker',
351
355
  quality: 'LOW',
352
356
  authToken: 'fake_token',
353
- mirror: false
357
+ mirror: false,
354
358
  });
355
359
  assert.exists(result.enable);
356
360
  assert.exists(result.disable);
@@ -359,13 +363,13 @@ describe('plugin-meetings', () => {
359
363
 
360
364
  it('creates background effect with custom options passed', async () => {
361
365
  const effectOptions = {
362
- generator: "local",
366
+ generator: 'local',
363
367
  frameRate: 45,
364
- mode: "IMAGE",
368
+ mode: 'IMAGE',
365
369
  mirror: false,
366
- quality: "HIGH",
367
- blurStrength: "STRONG",
368
- bgImageUrl: "https://test.webex.com/landscape.5a535788.jpg",
370
+ quality: 'HIGH',
371
+ blurStrength: 'STRONG',
372
+ bgImageUrl: 'https://test.webex.com/landscape.5a535788.jpg',
369
373
  };
370
374
 
371
375
  const result = await webex.meetings.createVirtualBackgroundEffect(effectOptions);
@@ -373,21 +377,21 @@ describe('plugin-meetings', () => {
373
377
  assert.exists(result);
374
378
  assert.instanceOf(result, VirtualBackgroundEffect);
375
379
  assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'options']);
376
- assert.deepEqual(result.options, {...effectOptions, authToken: "fake_token"});
380
+ assert.deepEqual(result.options, {...effectOptions, authToken: 'fake_token'});
377
381
  assert.exists(result.enable);
378
382
  assert.exists(result.disable);
379
383
  assert.exists(result.dispose);
380
384
  });
381
- })
385
+ });
382
386
 
383
387
  describe('noise reduction effect', () => {
384
388
  beforeEach(() => {
385
389
  webex.credentials = {
386
390
  supertoken: {
387
- access_token: "fake_token"
388
- }
391
+ access_token: 'fake_token',
392
+ },
389
393
  };
390
- })
394
+ });
391
395
 
392
396
  it('creates noise reduction effect', async () => {
393
397
  const result = await webex.meetings.createNoiseReductionEffect({audioContext: {}});
@@ -397,7 +401,7 @@ describe('plugin-meetings', () => {
397
401
  assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
398
402
  assert.deepEqual(result.options, {
399
403
  authToken: 'fake_token',
400
- audioContext: {}
404
+ audioContext: {},
401
405
  });
402
406
  assert.exists(result.enable);
403
407
  assert.exists(result.disable);
@@ -407,8 +411,8 @@ describe('plugin-meetings', () => {
407
411
  it('creates noise reduction effect with custom options passed', async () => {
408
412
  const effectOptions = {
409
413
  audioContext: {},
410
- mode: "WORKLET",
411
- env: "prod"
414
+ mode: 'WORKLET',
415
+ env: 'prod',
412
416
  };
413
417
 
414
418
  const result = await webex.meetings.createNoiseReductionEffect(effectOptions);
@@ -416,12 +420,12 @@ describe('plugin-meetings', () => {
416
420
  assert.exists(result);
417
421
  assert.instanceOf(result, NoiseReductionEffect);
418
422
  assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
419
- assert.deepEqual(result.options, {...effectOptions, authToken: "fake_token"});
423
+ assert.deepEqual(result.options, {...effectOptions, authToken: 'fake_token'});
420
424
  assert.exists(result.enable);
421
425
  assert.exists(result.disable);
422
426
  assert.exists(result.dispose);
423
427
  });
424
- })
428
+ });
425
429
 
426
430
  describe('gets', () => {
427
431
  describe('#getReachability', () => {
@@ -431,10 +435,7 @@ describe('plugin-meetings', () => {
431
435
  it('gets the reachability data instance from webex.meetings', () => {
432
436
  const reachability = webex.meetings.getReachability();
433
437
 
434
- assert.exists(
435
- reachability,
436
- 'reachability is defined'
437
- );
438
+ assert.exists(reachability, 'reachability is defined');
438
439
  assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
439
440
  });
440
441
  });
@@ -510,7 +511,6 @@ describe('plugin-meetings', () => {
510
511
  );
511
512
  });
512
513
  describe('when meeting is returned', () => {
513
-
514
514
  beforeEach(() => {
515
515
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
516
516
  locusInfo,
@@ -637,6 +637,29 @@ describe('plugin-meetings', () => {
637
637
 
638
638
  const FAKE_USE_RANDOM_DELAY = true;
639
639
  const correlationId = 'my-correlationId';
640
+ const callStateForMetrics = {
641
+ correlationId: 'my-correlationId2',
642
+ joinTrigger: 'my-join-trigger',
643
+ loginType: 'my-login-type',
644
+ };
645
+
646
+ it('should call setCallStateForMetrics on any pre-existing meeting', async () => {
647
+ const fakeMeeting = {setCallStateForMetrics: sinon.mock()};
648
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns(fakeMeeting);
649
+ await webex.meetings.create(
650
+ test1,
651
+ test2,
652
+ FAKE_USE_RANDOM_DELAY,
653
+ {},
654
+ correlationId,
655
+ true,
656
+ callStateForMetrics
657
+ );
658
+ assert.calledOnceWithExactly(fakeMeeting.setCallStateForMetrics, {
659
+ ...callStateForMetrics,
660
+ correlationId,
661
+ });
662
+ });
640
663
 
641
664
  const checkCallCreateMeeting = async (createParameters, createMeetingParameters) => {
642
665
  const create = webex.meetings.create(...createParameters);
@@ -645,31 +668,71 @@ describe('plugin-meetings', () => {
645
668
  await create;
646
669
  assert.calledOnce(webex.meetings.createMeeting);
647
670
  assert.calledWith(webex.meetings.createMeeting, ...createMeetingParameters);
648
- }
671
+ };
649
672
 
650
673
  it('calls createMeeting and returns its promise', async () => {
651
- checkCallCreateMeeting([test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true], [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true]);
674
+ await checkCallCreateMeeting(
675
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true],
676
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, true]
677
+ );
652
678
  });
653
679
 
654
680
  it('calls createMeeting when failOnMissingMeetinginfo is undefined and returns its promise', async () => {
655
- checkCallCreateMeeting([test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, undefined], [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false]);
681
+ await checkCallCreateMeeting(
682
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, undefined],
683
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, false]
684
+ );
656
685
  });
657
686
 
658
687
  it('calls createMeeting when failOnMissingMeetinginfo is false and returns its promise', async () => {
659
- checkCallCreateMeeting([test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false], [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false]);
688
+ await checkCallCreateMeeting(
689
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false],
690
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, false]
691
+ );
692
+ });
693
+
694
+ it('calls createMeeting with callStateForMetrics and returns its promise', async () => {
695
+ await checkCallCreateMeeting(
696
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, undefined, true, callStateForMetrics],
697
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, callStateForMetrics, true]
698
+ );
699
+ });
700
+
701
+ it('calls createMeeting with callStateForMetrics overwritten with correlationId and returns its promise', async () => {
702
+ await checkCallCreateMeeting(
703
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true, callStateForMetrics],
704
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {...callStateForMetrics, correlationId}, true]
705
+ );
660
706
  });
661
707
 
662
708
  it('calls createMeeting with extra info params and returns its promise', async () => {
663
709
  const FAKE_USE_RANDOM_DELAY = false;
664
710
  const correlationId = 'my-correlationId';
665
711
 
666
- const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
667
- const create = webex.meetings.create(test1, test2, FAKE_USE_RANDOM_DELAY, FAKE_INFO_EXTRA_PARAMS, correlationId);
712
+ const FAKE_INFO_EXTRA_PARAMS = {
713
+ mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
714
+ joinTXId: 'TSmrX61wNF',
715
+ };
716
+ const create = webex.meetings.create(
717
+ test1,
718
+ test2,
719
+ FAKE_USE_RANDOM_DELAY,
720
+ FAKE_INFO_EXTRA_PARAMS,
721
+ correlationId
722
+ );
668
723
 
669
724
  assert.exists(create.then);
670
725
  await create;
671
726
  assert.calledOnce(webex.meetings.createMeeting);
672
- assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY, FAKE_INFO_EXTRA_PARAMS, correlationId);
727
+ assert.calledWith(
728
+ webex.meetings.createMeeting,
729
+ test1,
730
+ test2,
731
+ FAKE_USE_RANDOM_DELAY,
732
+ FAKE_INFO_EXTRA_PARAMS,
733
+ {correlationId},
734
+ false
735
+ );
673
736
  });
674
737
 
675
738
  it('creates a new meeting when a scheduled meeting exists in the conversation', async () => {
@@ -765,7 +828,6 @@ describe('plugin-meetings', () => {
765
828
  });
766
829
  describe('#handleLocusEvent', () => {
767
830
  describe('there was a meeting', () => {
768
-
769
831
  beforeEach(() => {
770
832
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
771
833
  locusInfo,
@@ -831,7 +893,7 @@ describe('plugin-meetings', () => {
831
893
  },
832
894
  },
833
895
  info: {
834
- webExMeetingId
896
+ webExMeetingId,
835
897
  },
836
898
  },
837
899
  eventType: 'locus.difference',
@@ -839,7 +901,11 @@ describe('plugin-meetings', () => {
839
901
  });
840
902
  assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
841
903
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
842
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
904
+ assert.calledWith(
905
+ webex.meetings.meetingCollection.getByKey,
906
+ 'meetingNumber',
907
+ webExMeetingId
908
+ );
843
909
  assert.calledOnce(initialSetup);
844
910
  assert.calledWith(initialSetup, {
845
911
  id: uuid1,
@@ -854,7 +920,7 @@ describe('plugin-meetings', () => {
854
920
  },
855
921
  },
856
922
  info: {
857
- webExMeetingId
923
+ webExMeetingId,
858
924
  },
859
925
  });
860
926
  });
@@ -868,7 +934,7 @@ describe('plugin-meetings', () => {
868
934
  },
869
935
  },
870
936
  info: {
871
- webExMeetingId
937
+ webExMeetingId,
872
938
  },
873
939
  },
874
940
  eventType: 'locus.difference',
@@ -876,7 +942,11 @@ describe('plugin-meetings', () => {
876
942
  });
877
943
  assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
878
944
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
879
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
945
+ assert.calledWith(
946
+ webex.meetings.meetingCollection.getByKey,
947
+ 'meetingNumber',
948
+ webExMeetingId
949
+ );
880
950
  assert.calledOnce(initialSetup);
881
951
  assert.calledWith(initialSetup, {
882
952
  id: uuid1,
@@ -886,7 +956,7 @@ describe('plugin-meetings', () => {
886
956
  },
887
957
  },
888
958
  info: {
889
- webExMeetingId
959
+ webExMeetingId,
890
960
  },
891
961
  });
892
962
  });
@@ -933,7 +1003,7 @@ describe('plugin-meetings', () => {
933
1003
  },
934
1004
  },
935
1005
  info: {
936
- webExMeetingId
1006
+ webExMeetingId,
937
1007
  },
938
1008
  },
939
1009
  eventType: test1,
@@ -941,7 +1011,11 @@ describe('plugin-meetings', () => {
941
1011
  });
942
1012
  assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
943
1013
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
944
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
1014
+ assert.calledWith(
1015
+ webex.meetings.meetingCollection.getByKey,
1016
+ 'meetingNumber',
1017
+ webExMeetingId
1018
+ );
945
1019
  assert.calledOnce(initialSetup);
946
1020
  assert.calledWith(initialSetup, {
947
1021
  id: uuid1,
@@ -951,7 +1025,7 @@ describe('plugin-meetings', () => {
951
1025
  },
952
1026
  },
953
1027
  info: {
954
- webExMeetingId
1028
+ webExMeetingId,
955
1029
  },
956
1030
  });
957
1031
  });
@@ -1023,7 +1097,10 @@ describe('plugin-meetings', () => {
1023
1097
  });
1024
1098
  describe('successful MeetingInfo.#fetchMeetingInfo', () => {
1025
1099
  let clock, setTimeoutSpy, fakeMeetingStartTimeString, FAKE_TIME_TO_START;
1026
- const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
1100
+ const FAKE_INFO_EXTRA_PARAMS = {
1101
+ mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
1102
+ joinTXId: 'TSmrX61wNF',
1103
+ };
1027
1104
 
1028
1105
  beforeEach(() => {
1029
1106
  clock = sinon.useFakeTimers();
@@ -1055,13 +1132,23 @@ describe('plugin-meetings', () => {
1055
1132
  type,
1056
1133
  extraParams = {},
1057
1134
  expectedMeetingData = {},
1058
- sendCAevents = false,
1135
+ sendCAevents = false
1059
1136
  ) => {
1060
1137
  assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
1061
1138
  assert.calledOnce(MeetingsUtil.getMeetingAddedType);
1062
1139
  assert.notCalled(setTimeoutSpy);
1063
1140
  assert.callCount(TriggerProxy.trigger, 5);
1064
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type, null, null, undefined, undefined, extraParams, {meetingId: meeting.id, sendCAevents});
1141
+ assert.calledWith(
1142
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1143
+ destination,
1144
+ type,
1145
+ null,
1146
+ null,
1147
+ undefined,
1148
+ undefined,
1149
+ extraParams,
1150
+ {meetingId: meeting.id, sendCAevents}
1151
+ );
1065
1152
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1066
1153
 
1067
1154
  if (expectedMeetingData.permissionToken) {
@@ -1070,9 +1157,15 @@ describe('plugin-meetings', () => {
1070
1157
  if (expectedMeetingData.meetingJoinUrl) {
1071
1158
  assert.equal(meeting.meetingJoinUrl, expectedMeetingData.meetingJoinUrl);
1072
1159
  }
1073
- if(expectedMeetingData.correlationId) {
1160
+ if (expectedMeetingData.correlationId) {
1074
1161
  assert.equal(meeting.correlationId, expectedMeetingData.correlationId);
1075
1162
  }
1163
+ if (expectedMeetingData.callStateForMetrics) {
1164
+ assert.deepEqual(
1165
+ meeting.callStateForMetrics,
1166
+ expectedMeetingData.callStateForMetrics
1167
+ );
1168
+ }
1076
1169
  assert.equal(meeting.destination, destination);
1077
1170
  assert.equal(meeting.destinationType, type);
1078
1171
  assert.calledWith(
@@ -1105,14 +1198,27 @@ describe('plugin-meetings', () => {
1105
1198
  correlationId: meeting.id,
1106
1199
  };
1107
1200
 
1108
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', {}, expectedMeetingData);
1201
+ checkCreateWithoutDelay(
1202
+ meeting,
1203
+ 'test destination',
1204
+ 'test type',
1205
+ {},
1206
+ expectedMeetingData
1207
+ );
1109
1208
  });
1110
1209
 
1111
1210
  [undefined, FAKE_INFO_EXTRA_PARAMS].forEach((infoExtraParams) => {
1112
1211
  const infoExtraParamsProvided = infoExtraParams !== undefined;
1113
1212
 
1114
- it(`creates the meeting from a successful meeting info fetch meeting resolve testing${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1115
- const meeting = await webex.meetings.createMeeting('test destination', 'test type', false, infoExtraParams);
1213
+ it(`creates the meeting from a successful meeting info fetch meeting resolve testing${
1214
+ infoExtraParamsProvided ? ' with infoExtraParams' : ''
1215
+ }`, async () => {
1216
+ const meeting = await webex.meetings.createMeeting(
1217
+ 'test destination',
1218
+ 'test type',
1219
+ false,
1220
+ infoExtraParams
1221
+ );
1116
1222
  const expectedMeetingData = {
1117
1223
  permissionToken: 'PT',
1118
1224
  meetingJoinUrl: 'meetingJoinUrl',
@@ -1123,10 +1229,18 @@ describe('plugin-meetings', () => {
1123
1229
  Meeting,
1124
1230
  'createMeeting should eventually resolve to a Meeting Object'
1125
1231
  );
1126
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', infoExtraParamsProvided ? infoExtraParams : {}, expectedMeetingData);
1232
+ checkCreateWithoutDelay(
1233
+ meeting,
1234
+ 'test destination',
1235
+ 'test type',
1236
+ infoExtraParamsProvided ? infoExtraParams : {},
1237
+ expectedMeetingData
1238
+ );
1127
1239
  });
1128
1240
 
1129
- it(`creates the meeting from a successful meeting info fetch with random delay${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1241
+ it(`creates the meeting from a successful meeting info fetch with random delay${
1242
+ infoExtraParamsProvided ? ' with infoExtraParams' : ''
1243
+ }`, async () => {
1130
1244
  const FAKE_LOCUS_MEETING = {
1131
1245
  conversationUrl: 'locusConvURL',
1132
1246
  url: 'locusUrl',
@@ -1214,7 +1328,7 @@ describe('plugin-meetings', () => {
1214
1328
  'meeting:meetingInfoAvailable'
1215
1329
  );
1216
1330
  });
1217
- })
1331
+ });
1218
1332
 
1219
1333
  it('creates the meeting from a successful meeting info fetch that has no random delay because it is active', async () => {
1220
1334
  const FAKE_LOCUS_MEETING = {
@@ -1315,14 +1429,59 @@ describe('plugin-meetings', () => {
1315
1429
  });
1316
1430
 
1317
1431
  it('creates meeting with the correlationId provided', async () => {
1318
- const meeting = await webex.meetings.createMeeting('test destination', 'test type', false, {}, 'my-correlationId');
1432
+ const meeting = await webex.meetings.createMeeting(
1433
+ 'test destination',
1434
+ 'test type',
1435
+ false,
1436
+ {},
1437
+ {correlationId: 'my-correlationId'}
1438
+ );
1319
1439
 
1320
1440
  const expectedMeetingData = {
1321
1441
  correlationId: 'my-correlationId',
1322
1442
  };
1323
1443
 
1324
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', {}, expectedMeetingData, true);
1325
- })
1444
+ checkCreateWithoutDelay(
1445
+ meeting,
1446
+ 'test destination',
1447
+ 'test type',
1448
+ {},
1449
+ expectedMeetingData,
1450
+ true
1451
+ );
1452
+ });
1453
+
1454
+ it('creates meeting with the callStateForMetrics provided', async () => {
1455
+ const meeting = await webex.meetings.createMeeting(
1456
+ 'test destination',
1457
+ 'test type',
1458
+ false,
1459
+ {},
1460
+ {
1461
+ correlationId: 'my-correlationId',
1462
+ joinTrigger: 'my-join-trigger',
1463
+ loginType: 'my-login-type',
1464
+ }
1465
+ );
1466
+
1467
+ const expectedMeetingData = {
1468
+ correlationId: 'my-correlationId',
1469
+ callStateForMetrics: {
1470
+ correlationId: 'my-correlationId',
1471
+ joinTrigger: 'my-join-trigger',
1472
+ loginType: 'my-login-type',
1473
+ },
1474
+ };
1475
+
1476
+ checkCreateWithoutDelay(
1477
+ meeting,
1478
+ 'test destination',
1479
+ 'test type',
1480
+ {},
1481
+ expectedMeetingData,
1482
+ true
1483
+ );
1484
+ });
1326
1485
  });
1327
1486
 
1328
1487
  describe('rejected MeetingInfo.#fetchMeetingInfo', () => {
@@ -1332,16 +1491,21 @@ describe('plugin-meetings', () => {
1332
1491
  webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1333
1492
  .stub()
1334
1493
  .returns(Promise.reject(new Error('test')));
1335
- webex.meetings.destroy = sinon
1336
- .stub()
1337
- .returns(Promise.resolve());
1494
+ webex.meetings.destroy = sinon.stub().returns(Promise.resolve());
1338
1495
  webex.meetings.createMeeting = sinon.spy(webex.meetings.createMeeting);
1339
1496
  });
1340
1497
 
1341
1498
  const checkCreateMeetingWithNoMeetingInfo = async (failOnMissingMeetingInfo, destroy) => {
1342
1499
  try {
1343
- const meeting = await webex.meetings.createMeeting('test destination', 'test type', undefined, undefined, undefined, failOnMissingMeetingInfo);
1344
-
1500
+ const meeting = await webex.meetings.createMeeting(
1501
+ 'test destination',
1502
+ 'test type',
1503
+ undefined,
1504
+ undefined,
1505
+ undefined,
1506
+ failOnMissingMeetingInfo
1507
+ );
1508
+
1345
1509
  assert.instanceOf(
1346
1510
  meeting,
1347
1511
  Meeting,
@@ -1355,9 +1519,13 @@ describe('plugin-meetings', () => {
1355
1519
  'test destination',
1356
1520
  'test type'
1357
1521
  );
1358
-
1522
+
1359
1523
  if (destroy) {
1360
- assert.calledWith(webex.meetings.destroy, sinon.match.instanceOf(Meeting), 'MISSING_MEETING_INFO')
1524
+ assert.calledWith(
1525
+ webex.meetings.destroy,
1526
+ sinon.match.instanceOf(Meeting),
1527
+ 'MISSING_MEETING_INFO'
1528
+ );
1361
1529
  assert.notCalled(MeetingsUtil.getMeetingAddedType);
1362
1530
  assert.notCalled(TriggerProxy.trigger);
1363
1531
  assert.throw(webex.meetings.createMeeting, 'meeting information not found');
@@ -1378,10 +1546,10 @@ describe('plugin-meetings', () => {
1378
1546
  }
1379
1547
  );
1380
1548
  }
1381
- } catch (err) {
1549
+ } catch (err) {
1382
1550
  assert.instanceOf(err, NoMeetingInfoError);
1383
1551
  }
1384
- }
1552
+ };
1385
1553
 
1386
1554
  it('creates the meeting from a rejected meeting info fetch', async () => {
1387
1555
  checkCreateMeetingWithNoMeetingInfo(false, false);
@@ -1526,7 +1694,6 @@ describe('plugin-meetings', () => {
1526
1694
  });
1527
1695
 
1528
1696
  describe('#fetchUserPreferredWebexSite', () => {
1529
-
1530
1697
  let loggerProxySpy;
1531
1698
 
1532
1699
  it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
@@ -1544,12 +1711,10 @@ describe('plugin-meetings', () => {
1544
1711
  getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
1545
1712
  },
1546
1713
  user: {
1547
- get: sinon.stub().returns(
1548
- Promise.resolve(user)
1549
- ),
1714
+ get: sinon.stub().returns(Promise.resolve(user)),
1550
1715
  },
1551
1716
  });
1552
- }
1717
+ };
1553
1718
 
1554
1719
  it('should not fail if UserPreferred info is not fetched ', async () => {
1555
1720
  setup();
@@ -1586,6 +1751,59 @@ describe('plugin-meetings', () => {
1586
1751
  assert.notCalled(loggerProxySpy);
1587
1752
  });
1588
1753
 
1754
+ forEach(
1755
+ [
1756
+ {user: undefined},
1757
+ {user: {userPreferences: {}}},
1758
+ {user: {userPreferences: {userPreferencesItems: {}}}},
1759
+ {user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
1760
+ ],
1761
+ ({user}) => {
1762
+ it(`should handle invalid user data ${user}`, async () => {
1763
+ setup({user});
1764
+
1765
+ await webex.meetings.fetchUserPreferredWebexSite();
1766
+
1767
+ assert.equal(webex.meetings.preferredWebexSite, '');
1768
+ assert.calledOnceWithExactly(
1769
+ loggerProxySpy,
1770
+ 'Failed to fetch preferred site from user - no site will be set'
1771
+ );
1772
+ });
1773
+ }
1774
+ );
1775
+
1776
+ it('should handle a get user failure', async () => {
1777
+ setup();
1778
+
1779
+ webex.internal.user.get.rejects(new Error());
1780
+
1781
+ await webex.meetings.fetchUserPreferredWebexSite();
1782
+
1783
+ assert.equal(webex.meetings.preferredWebexSite, '');
1784
+ assert.calledOnceWithExactly(
1785
+ loggerProxySpy,
1786
+ 'Failed to fetch preferred site from user - no site will be set'
1787
+ );
1788
+ });
1789
+
1790
+ it('should fall back to fetching the site from the user', async () => {
1791
+ setup({
1792
+ user: {
1793
+ userPreferences: {
1794
+ userPreferencesItems: {
1795
+ preferredWebExSite: 'site.webex.com',
1796
+ },
1797
+ },
1798
+ },
1799
+ });
1800
+
1801
+ await webex.meetings.fetchUserPreferredWebexSite();
1802
+
1803
+ assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
1804
+ assert.notCalled(loggerProxySpy);
1805
+ });
1806
+
1589
1807
  forEach([
1590
1808
  {user: undefined},
1591
1809
  {user: {userPreferences: {}}},
@@ -1714,7 +1932,7 @@ describe('plugin-meetings', () => {
1714
1932
  newLocus = {
1715
1933
  controls: {},
1716
1934
  self: {},
1717
- }
1935
+ };
1718
1936
  });
1719
1937
  afterEach(() => {
1720
1938
  sinon.restore();
@@ -1745,16 +1963,24 @@ describe('plugin-meetings', () => {
1745
1963
  });
1746
1964
 
1747
1965
  it('if newLocus replaceAt time is expired, then return false', () => {
1748
- sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({joinedWith: {replaces: [{
1749
- replaceAt: '2023-03-27T02:17:02.506Z',
1750
- }]}});
1966
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1967
+ joinedWith: {
1968
+ replaces: [
1969
+ {
1970
+ replaceAt: '2023-03-27T02:17:02.506Z',
1971
+ },
1972
+ ],
1973
+ },
1974
+ });
1751
1975
  newLocus.self.state = 'JOINED';
1752
1976
  sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1753
1977
  sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1754
- replaces: [{
1755
- replaceAt: '2023-03-27T02:17:01.506Z'
1756
- }]
1757
- })
1978
+ replaces: [
1979
+ {
1980
+ replaceAt: '2023-03-27T02:17:01.506Z',
1981
+ },
1982
+ ],
1983
+ });
1758
1984
 
1759
1985
  LoggerProxy.logger.log = sinon.stub();
1760
1986
  const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
@@ -1843,7 +2069,7 @@ describe('plugin-meetings', () => {
1843
2069
  newLocus = {
1844
2070
  controls: {},
1845
2071
  self: {},
1846
- }
2072
+ };
1847
2073
  });
1848
2074
  afterEach(() => {
1849
2075
  sinon.restore();
@@ -1909,13 +2135,13 @@ describe('plugin-meetings', () => {
1909
2135
  self: {
1910
2136
  callbackInfo: {
1911
2137
  callbackAddress: 'address1',
1912
- }
2138
+ },
1913
2139
  },
1914
2140
  info: {
1915
2141
  webExMeetingId: '123456',
1916
2142
  isUnifiedSpaceMeeting: false,
1917
2143
  },
1918
- conversationUrl: 'conversationUrl1'
2144
+ conversationUrl: 'conversationUrl1',
1919
2145
  };
1920
2146
 
1921
2147
  sinon.stub(MeetingsUtil, 'checkForCorrelationId').returns('correlationId1');
@@ -1929,9 +2155,17 @@ describe('plugin-meetings', () => {
1929
2155
  assert.isNull(result);
1930
2156
  assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1931
2157
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1932
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
2158
+ assert.calledWith(
2159
+ webex.meetings.meetingCollection.getByKey,
2160
+ 'correlationId',
2161
+ 'correlationId1'
2162
+ );
1933
2163
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1934
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
2164
+ assert.calledWith(
2165
+ webex.meetings.meetingCollection.getByKey,
2166
+ 'conversationUrl',
2167
+ 'conversationUrl1'
2168
+ );
1935
2169
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1936
2170
  });
1937
2171
 
@@ -1941,7 +2175,7 @@ describe('plugin-meetings', () => {
1941
2175
  const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1942
2176
  assert.isNull(result);
1943
2177
  assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1944
- })
2178
+ });
1945
2179
 
1946
2180
  it('check the calls when meeting found by key: locusUrl', () => {
1947
2181
  mockGetByKey('locusUrl');
@@ -1957,7 +2191,11 @@ describe('plugin-meetings', () => {
1957
2191
  assert.deepEqual(result, mockReturnMeeting);
1958
2192
  assert.callCount(webex.meetings.meetingCollection.getByKey, 2);
1959
2193
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1960
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
2194
+ assert.calledWith(
2195
+ webex.meetings.meetingCollection.getByKey,
2196
+ 'correlationId',
2197
+ 'correlationId1'
2198
+ );
1961
2199
  });
1962
2200
 
1963
2201
  it('check the calls when meeting found by key: sipUri', () => {
@@ -1966,7 +2204,11 @@ describe('plugin-meetings', () => {
1966
2204
  assert.deepEqual(result, mockReturnMeeting);
1967
2205
  assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
1968
2206
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1969
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
2207
+ assert.calledWith(
2208
+ webex.meetings.meetingCollection.getByKey,
2209
+ 'correlationId',
2210
+ 'correlationId1'
2211
+ );
1970
2212
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1971
2213
  });
1972
2214
 
@@ -1976,9 +2218,17 @@ describe('plugin-meetings', () => {
1976
2218
  assert.deepEqual(result, mockReturnMeeting);
1977
2219
  assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1978
2220
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1979
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
2221
+ assert.calledWith(
2222
+ webex.meetings.meetingCollection.getByKey,
2223
+ 'correlationId',
2224
+ 'correlationId1'
2225
+ );
1980
2226
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1981
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
2227
+ assert.calledWith(
2228
+ webex.meetings.meetingCollection.getByKey,
2229
+ 'conversationUrl',
2230
+ 'conversationUrl1'
2231
+ );
1982
2232
  });
1983
2233
 
1984
2234
  it('check the calls when meeting found by key: meetingNumber', () => {
@@ -1987,9 +2237,17 @@ describe('plugin-meetings', () => {
1987
2237
  assert.deepEqual(result, mockReturnMeeting);
1988
2238
  assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1989
2239
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1990
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
2240
+ assert.calledWith(
2241
+ webex.meetings.meetingCollection.getByKey,
2242
+ 'correlationId',
2243
+ 'correlationId1'
2244
+ );
1991
2245
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1992
- assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
2246
+ assert.calledWith(
2247
+ webex.meetings.meetingCollection.getByKey,
2248
+ 'conversationUrl',
2249
+ 'conversationUrl1'
2250
+ );
1993
2251
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1994
2252
  });
1995
2253
  });
@@ -2004,18 +2262,18 @@ describe('plugin-meetings', () => {
2004
2262
  controls: {
2005
2263
  breakout: {
2006
2264
  sessionType: 'MAIN',
2007
- url: 'breakoutUnifiedUrl1'
2008
- }
2009
- }
2265
+ url: 'breakoutUnifiedUrl1',
2266
+ },
2267
+ },
2010
2268
  };
2011
2269
  breakoutLocus = {
2012
2270
  url: 'breakoutUrl1',
2013
2271
  controls: {
2014
2272
  breakout: {
2015
2273
  sessionType: 'BREAKOUT',
2016
- url: 'breakoutUnifiedUrl1'
2017
- }
2018
- }
2274
+ url: 'breakoutUnifiedUrl1',
2275
+ },
2276
+ },
2019
2277
  };
2020
2278
  lociArray = [mainLocus, breakoutLocus];
2021
2279
 
@@ -2058,8 +2316,8 @@ describe('plugin-meetings', () => {
2058
2316
  breakout: {
2059
2317
  sessionType: 'BREAKOUT',
2060
2318
  url: 'breakoutUnifiedUrl1',
2061
- }
2062
- }
2319
+ },
2320
+ },
2063
2321
  };
2064
2322
 
2065
2323
  webex.meetings.handleLocusEvent = sinon.stub();
@@ -2089,8 +2347,8 @@ describe('plugin-meetings', () => {
2089
2347
  breakout: {
2090
2348
  sessionType: 'MAIN',
2091
2349
  url: 'breakoutUnifiedUrl2',
2092
- }
2093
- }
2350
+ },
2351
+ },
2094
2352
  });
2095
2353
  assert.notCalled(webex.meetings.handleLocusEvent);
2096
2354
  });
@@ -2102,10 +2360,13 @@ describe('plugin-meetings', () => {
2102
2360
  breakout: {
2103
2361
  sessionType: 'MAIN',
2104
2362
  url: 'breakoutUnifiedUrl1',
2105
- }
2106
- }
2363
+ },
2364
+ },
2365
+ });
2366
+ assert.calledWith(webex.meetings.handleLocusEvent, {
2367
+ locus: breakoutLocus,
2368
+ locusUrl: breakoutLocus.url,
2107
2369
  });
2108
- assert.calledWith(webex.meetings.handleLocusEvent, {locus: breakoutLocus, locusUrl: breakoutLocus.url});
2109
2370
  });
2110
2371
  });
2111
2372
 
@@ -2129,17 +2390,16 @@ describe('plugin-meetings', () => {
2129
2390
  meeting.locusId = 'locus id';
2130
2391
  meeting.correlationId = 'correlation id';
2131
2392
  meeting.locusInfo = {
2132
- fullState: { lastActive: 'last active', sessionId: 'locus session id'},
2133
- info: { webExMeetingId: 'meeting id'}
2134
- }
2393
+ fullState: {lastActive: 'last active', sessionId: 'locus session id'},
2394
+ info: {webExMeetingId: 'meeting id'},
2395
+ };
2135
2396
  });
2136
2397
 
2137
2398
  afterEach(() => {
2138
2399
  sinon.restore();
2139
- })
2400
+ });
2140
2401
 
2141
2402
  it('sends metrics on success', async () => {
2142
-
2143
2403
  await meeting.uploadLogs();
2144
2404
 
2145
2405
  await testUtils.flushPromises();
@@ -2162,16 +2422,20 @@ describe('plugin-meetings', () => {
2162
2422
 
2163
2423
  await testUtils.flushPromises();
2164
2424
 
2165
- assert.calledOnceWithExactly(metricsSpy, 'js_sdk_upload_logs_failure', sinon.match({
2166
- callStart: 'last active',
2167
- correlationId: 'correlation id',
2168
- feedbackId: 'correlation id',
2169
- locusId: 'locus id',
2170
- meetingId: 'meeting id',
2171
- reason: 'fake error',
2172
- autoupload: true,
2173
- locussessionid: 'locus session id',
2174
- }));
2425
+ assert.calledOnceWithExactly(
2426
+ metricsSpy,
2427
+ 'js_sdk_upload_logs_failure',
2428
+ sinon.match({
2429
+ callStart: 'last active',
2430
+ correlationId: 'correlation id',
2431
+ feedbackId: 'correlation id',
2432
+ locusId: 'locus id',
2433
+ meetingId: 'meeting id',
2434
+ reason: 'fake error',
2435
+ autoupload: true,
2436
+ locussessionid: 'locus session id',
2437
+ })
2438
+ );
2175
2439
  });
2176
2440
  });
2177
2441
  });