@webex/plugin-meetings 3.6.0-next.9 → 3.7.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 (118) hide show
  1. package/README.md +2 -1
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/config.js +2 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/constants.js +24 -2
  7. package/dist/constants.js.map +1 -1
  8. package/dist/controls-options-manager/enums.js +1 -0
  9. package/dist/controls-options-manager/enums.js.map +1 -1
  10. package/dist/controls-options-manager/index.js +10 -3
  11. package/dist/controls-options-manager/index.js.map +1 -1
  12. package/dist/controls-options-manager/types.js.map +1 -1
  13. package/dist/controls-options-manager/util.js +12 -0
  14. package/dist/controls-options-manager/util.js.map +1 -1
  15. package/dist/interpretation/index.js +1 -1
  16. package/dist/interpretation/siLanguage.js +1 -1
  17. package/dist/locus-info/controlsUtils.js +28 -4
  18. package/dist/locus-info/controlsUtils.js.map +1 -1
  19. package/dist/locus-info/fullState.js +2 -1
  20. package/dist/locus-info/fullState.js.map +1 -1
  21. package/dist/locus-info/index.js +61 -3
  22. package/dist/locus-info/index.js.map +1 -1
  23. package/dist/meeting/in-meeting-actions.js +19 -1
  24. package/dist/meeting/in-meeting-actions.js.map +1 -1
  25. package/dist/meeting/index.js +564 -441
  26. package/dist/meeting/index.js.map +1 -1
  27. package/dist/meeting/locusMediaRequest.js +2 -6
  28. package/dist/meeting/locusMediaRequest.js.map +1 -1
  29. package/dist/meeting/request.js +21 -29
  30. package/dist/meeting/request.js.map +1 -1
  31. package/dist/meeting/util.js +94 -59
  32. package/dist/meeting/util.js.map +1 -1
  33. package/dist/meetings/index.js +2 -0
  34. package/dist/meetings/index.js.map +1 -1
  35. package/dist/members/index.js +3 -2
  36. package/dist/members/index.js.map +1 -1
  37. package/dist/members/util.js +9 -5
  38. package/dist/members/util.js.map +1 -1
  39. package/dist/reachability/clusterReachability.js +0 -4
  40. package/dist/reachability/clusterReachability.js.map +1 -1
  41. package/dist/reachability/index.js +433 -136
  42. package/dist/reachability/index.js.map +1 -1
  43. package/dist/reachability/reachability.types.js +7 -0
  44. package/dist/reachability/reachability.types.js.map +1 -0
  45. package/dist/reachability/request.js +23 -9
  46. package/dist/reachability/request.js.map +1 -1
  47. package/dist/roap/index.js +5 -7
  48. package/dist/roap/index.js.map +1 -1
  49. package/dist/roap/request.js +45 -79
  50. package/dist/roap/request.js.map +1 -1
  51. package/dist/roap/turnDiscovery.js +3 -6
  52. package/dist/roap/turnDiscovery.js.map +1 -1
  53. package/dist/types/config.d.ts +1 -0
  54. package/dist/types/constants.d.ts +19 -0
  55. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  56. package/dist/types/controls-options-manager/index.d.ts +2 -1
  57. package/dist/types/controls-options-manager/types.d.ts +2 -0
  58. package/dist/types/locus-info/index.d.ts +9 -0
  59. package/dist/types/meeting/in-meeting-actions.d.ts +18 -0
  60. package/dist/types/meeting/index.d.ts +14 -3
  61. package/dist/types/meeting/locusMediaRequest.d.ts +2 -3
  62. package/dist/types/meeting/request.d.ts +2 -2
  63. package/dist/types/meeting/util.d.ts +2 -2
  64. package/dist/types/meetings/index.d.ts +1 -1
  65. package/dist/types/members/index.d.ts +2 -1
  66. package/dist/types/members/util.d.ts +3 -1
  67. package/dist/types/reachability/clusterReachability.d.ts +1 -10
  68. package/dist/types/reachability/index.d.ts +74 -35
  69. package/dist/types/reachability/reachability.types.d.ts +64 -0
  70. package/dist/types/reachability/request.d.ts +5 -1
  71. package/dist/types/roap/request.d.ts +1 -13
  72. package/dist/webinar/index.js +32 -19
  73. package/dist/webinar/index.js.map +1 -1
  74. package/package.json +22 -22
  75. package/src/config.ts +1 -0
  76. package/src/constants.ts +25 -0
  77. package/src/controls-options-manager/enums.ts +1 -0
  78. package/src/controls-options-manager/index.ts +19 -2
  79. package/src/controls-options-manager/types.ts +2 -0
  80. package/src/controls-options-manager/util.ts +12 -0
  81. package/src/locus-info/controlsUtils.ts +46 -2
  82. package/src/locus-info/fullState.ts +1 -0
  83. package/src/locus-info/index.ts +60 -0
  84. package/src/meeting/in-meeting-actions.ts +37 -0
  85. package/src/meeting/index.ts +114 -11
  86. package/src/meeting/locusMediaRequest.ts +4 -8
  87. package/src/meeting/request.ts +4 -11
  88. package/src/meeting/util.ts +24 -4
  89. package/src/meetings/index.ts +46 -39
  90. package/src/members/index.ts +4 -2
  91. package/src/members/util.ts +3 -1
  92. package/src/reachability/clusterReachability.ts +1 -14
  93. package/src/reachability/index.ts +285 -77
  94. package/src/reachability/reachability.types.ts +85 -0
  95. package/src/reachability/request.ts +55 -30
  96. package/src/roap/index.ts +4 -5
  97. package/src/roap/request.ts +30 -44
  98. package/src/roap/turnDiscovery.ts +2 -4
  99. package/src/webinar/index.ts +31 -17
  100. package/test/unit/spec/controls-options-manager/index.js +56 -32
  101. package/test/unit/spec/controls-options-manager/util.js +44 -0
  102. package/test/unit/spec/locus-info/controlsUtils.js +80 -4
  103. package/test/unit/spec/locus-info/index.js +59 -2
  104. package/test/unit/spec/meeting/in-meeting-actions.ts +18 -0
  105. package/test/unit/spec/meeting/index.js +231 -100
  106. package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
  107. package/test/unit/spec/meeting/request.js +3 -26
  108. package/test/unit/spec/meeting/utils.js +53 -13
  109. package/test/unit/spec/meetings/index.js +16 -1
  110. package/test/unit/spec/members/index.js +25 -2
  111. package/test/unit/spec/members/request.js +37 -3
  112. package/test/unit/spec/members/utils.js +15 -1
  113. package/test/unit/spec/reachability/index.ts +265 -1
  114. package/test/unit/spec/reachability/request.js +56 -15
  115. package/test/unit/spec/roap/index.ts +1 -1
  116. package/test/unit/spec/roap/request.ts +51 -109
  117. package/test/unit/spec/roap/turnDiscovery.ts +202 -147
  118. package/test/unit/spec/webinar/index.ts +82 -16
@@ -90,8 +90,8 @@ import WebExMeetingsErrors from '../../../../src/common/errors/webex-meetings-er
90
90
  import ParameterError from '../../../../src/common/errors/parameter';
91
91
  import PasswordError from '../../../../src/common/errors/password-error';
92
92
  import CaptchaError from '../../../../src/common/errors/captcha-error';
93
- import PermissionError from '../../../../src/common/errors/permission';
94
- import WebinarRegistrationError from '../../../../src/common/errors/webinar-registration-error';
93
+ import PermissionError from '../../../../src/common/errors/permission';
94
+ import WebinarRegistrationError from '../../../../src/common/errors/webinar-registration-error';
95
95
  import IntentToJoinError from '../../../../src/common/errors/intent-to-join';
96
96
  import testUtils from '../../../utils/testUtils';
97
97
  import {
@@ -377,7 +377,10 @@ describe('plugin-meetings', () => {
377
377
  }
378
378
  );
379
379
  assert.equal(newMeeting.correlationId, newMeeting.id);
380
- assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id, sessionCorrelationId: ''});
380
+ assert.deepEqual(newMeeting.callStateForMetrics, {
381
+ correlationId: newMeeting.id,
382
+ sessionCorrelationId: '',
383
+ });
381
384
  });
382
385
 
383
386
  it('correlationId can be provided in callStateForMetrics', () => {
@@ -646,7 +649,6 @@ describe('plugin-meetings', () => {
646
649
  });
647
650
 
648
651
  const fakeRoapMessage = {id: 'fake TURN discovery message'};
649
- const fakeReachabilityResults = {id: 'fake reachability'};
650
652
  const fakeTurnServerInfo = {id: 'fake turn info'};
651
653
  const fakeJoinResult = {id: 'join result'};
652
654
 
@@ -664,8 +666,6 @@ describe('plugin-meetings', () => {
664
666
  .stub(meeting, 'addMediaInternal')
665
667
  .returns(Promise.resolve(test4));
666
668
 
667
- webex.meetings.reachability.getReachabilityResults.resolves(fakeReachabilityResults);
668
-
669
669
  generateTurnDiscoveryRequestMessageStub = sinon
670
670
  .stub(meeting.roap, 'generateTurnDiscoveryRequestMessage')
671
671
  .resolves({roapMessage: fakeRoapMessage});
@@ -685,7 +685,6 @@ describe('plugin-meetings', () => {
685
685
  assert.calledOnceWithExactly(meeting.join, {
686
686
  ...joinOptions,
687
687
  roapMessage: fakeRoapMessage,
688
- reachability: fakeReachabilityResults,
689
688
  });
690
689
  assert.calledOnceWithExactly(generateTurnDiscoveryRequestMessageStub, meeting, true);
691
690
  assert.calledOnceWithExactly(
@@ -722,7 +721,6 @@ describe('plugin-meetings', () => {
722
721
  assert.calledOnceWithExactly(meeting.join, {
723
722
  ...joinOptions,
724
723
  roapMessage: undefined,
725
- reachability: fakeReachabilityResults,
726
724
  });
727
725
  assert.calledOnceWithExactly(generateTurnDiscoveryRequestMessageStub, meeting, true);
728
726
  assert.notCalled(handleTurnDiscoveryHttpResponseStub);
@@ -754,7 +752,6 @@ describe('plugin-meetings', () => {
754
752
  assert.calledOnceWithExactly(meeting.join, {
755
753
  ...joinOptions,
756
754
  roapMessage: fakeRoapMessage,
757
- reachability: fakeReachabilityResults,
758
755
  });
759
756
  assert.calledOnceWithExactly(generateTurnDiscoveryRequestMessageStub, meeting, true);
760
757
  assert.calledOnceWithExactly(
@@ -3442,47 +3439,60 @@ describe('plugin-meetings', () => {
3442
3439
  });
3443
3440
  });
3444
3441
 
3445
- it('should pass bundlePolicy to createMediaConnection', async () => {
3442
+ describe('bundlePolicy', () => {
3446
3443
  const FAKE_TURN_URL = 'turns:webex.com:3478';
3447
3444
  const FAKE_TURN_USER = 'some-turn-username';
3448
3445
  const FAKE_TURN_PASSWORD = 'some-password';
3449
3446
 
3450
- meeting.meetingState = 'ACTIVE';
3451
- Media.createMediaConnection.resetHistory();
3452
-
3453
- meeting.roap.doTurnDiscovery = sinon.stub().resolves({
3454
- turnServerInfo: {
3455
- url: FAKE_TURN_URL,
3456
- username: FAKE_TURN_USER,
3457
- password: FAKE_TURN_PASSWORD,
3458
- },
3459
- turnDiscoverySkippedReason: undefined,
3460
- });
3461
- const media = meeting.addMedia({
3462
- mediaSettings: {},
3463
- bundlePolicy: 'bundlePolicy-value',
3464
- });
3447
+ beforeEach(() => {
3448
+ meeting.meetingState = 'ACTIVE';
3449
+ Media.createMediaConnection.resetHistory();
3465
3450
 
3466
- assert.exists(media);
3467
- await media;
3468
- assert.calledOnce(meeting.roap.doTurnDiscovery);
3469
- assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
3470
- assert.calledOnce(Media.createMediaConnection);
3471
- assert.calledWith(
3472
- Media.createMediaConnection,
3473
- false,
3474
- meeting.getMediaConnectionDebugId(),
3475
- meeting.id,
3476
- sinon.match({
3451
+ meeting.roap.doTurnDiscovery = sinon.stub().resolves({
3477
3452
  turnServerInfo: {
3478
3453
  url: FAKE_TURN_URL,
3479
3454
  username: FAKE_TURN_USER,
3480
3455
  password: FAKE_TURN_PASSWORD,
3481
3456
  },
3482
- bundlePolicy: 'bundlePolicy-value',
3483
- })
3484
- );
3485
- assert.calledOnce(fakeMediaConnection.initiateOffer);
3457
+ turnDiscoverySkippedReason: undefined,
3458
+ });
3459
+ });
3460
+
3461
+ const runCheck = async (bundlePolicy, expectedValue) => {
3462
+ const media = meeting.addMedia({
3463
+ mediaSettings: {},
3464
+ bundlePolicy,
3465
+ });
3466
+
3467
+ assert.exists(media);
3468
+ await media;
3469
+ assert.calledOnce(meeting.roap.doTurnDiscovery);
3470
+ assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
3471
+ assert.calledOnce(Media.createMediaConnection);
3472
+ assert.calledWith(
3473
+ Media.createMediaConnection,
3474
+ false,
3475
+ meeting.getMediaConnectionDebugId(),
3476
+ meeting.id,
3477
+ sinon.match({
3478
+ turnServerInfo: {
3479
+ url: FAKE_TURN_URL,
3480
+ username: FAKE_TURN_USER,
3481
+ password: FAKE_TURN_PASSWORD,
3482
+ },
3483
+ bundlePolicy: expectedValue,
3484
+ })
3485
+ );
3486
+ assert.calledOnce(fakeMediaConnection.initiateOffer);
3487
+ };
3488
+
3489
+ it('should pass bundlePolicy to createMediaConnection', async () => {
3490
+ await runCheck('max-compat', 'max-compat');
3491
+ });
3492
+
3493
+ it('should pass max-bundle to createMediaConnection if bundlePolicy is not provided', async () => {
3494
+ await runCheck(undefined, 'max-bundle');
3495
+ });
3486
3496
  });
3487
3497
 
3488
3498
  it('succeeds even if getDevices() throws', async () => {
@@ -3676,6 +3686,8 @@ describe('plugin-meetings', () => {
3676
3686
  meeting.setMercuryListener = sinon.stub();
3677
3687
  meeting.locusInfo.onFullLocus = sinon.stub();
3678
3688
  meeting.webex.meetings.geoHintInfo = {regionCode: 'EU', countryCode: 'UK'};
3689
+ meeting.webex.meetings.reachability.getReachabilityReportToAttachToRoap = sinon.stub().resolves({id: 'fake reachability'});
3690
+ meeting.webex.meetings.reachability.getClientMediaPreferences = sinon.stub().resolves({id: 'fake clientMediaPreferences'});
3679
3691
  meeting.roap.doTurnDiscovery = sinon.stub().resolves({
3680
3692
  turnServerInfo: {
3681
3693
  url: 'turns:turn-server-url:443?transport=tcp',
@@ -3795,12 +3807,12 @@ describe('plugin-meetings', () => {
3795
3807
  id: 'fake locus from mocked join request',
3796
3808
  locusUrl: 'fake locus url',
3797
3809
  mediaId: 'fake media id',
3798
- })
3810
+ });
3799
3811
  sinon.stub(meeting.meetingRequest, 'joinMeeting').resolves({
3800
3812
  headers: {
3801
3813
  trackingid: 'fake tracking id',
3802
- }
3803
- })
3814
+ },
3815
+ });
3804
3816
  await meeting.join({enableMultistream: isMultistream});
3805
3817
  });
3806
3818
 
@@ -3861,6 +3873,9 @@ describe('plugin-meetings', () => {
3861
3873
  const checkSdpOfferSent = ({audioMuted, videoMuted}) => {
3862
3874
  const {sdp, seq, tieBreaker} = roapOfferMessage;
3863
3875
 
3876
+ assert.calledWith(meeting.webex.meetings.reachability.getClientMediaPreferences, meeting.isMultistream, 0);
3877
+ assert.calledWith(meeting.webex.meetings.reachability.getReachabilityReportToAttachToRoap);
3878
+
3864
3879
  assert.calledWith(locusMediaRequestStub, {
3865
3880
  method: 'PUT',
3866
3881
  uri: `${meeting.selfUrl}/media`,
@@ -3874,14 +3889,12 @@ describe('plugin-meetings', () => {
3874
3889
  correlationId: meeting.correlationId,
3875
3890
  localMedias: [
3876
3891
  {
3877
- localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted},"roapMessage":{"messageType":"OFFER","sdps":["${sdp}"],"version":"2","seq":"${seq}","tieBreaker":"${tieBreaker}","headers":["includeAnswerInHttpResponse","noOkInTransaction"]}}`,
3892
+ localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted},"roapMessage":{"messageType":"OFFER","sdps":["${sdp}"],"version":"2","seq":"${seq}","tieBreaker":"${tieBreaker}","headers":["includeAnswerInHttpResponse","noOkInTransaction"]},"reachability":{"id":"fake reachability"}}`,
3878
3893
  mediaId: 'fake media id',
3879
3894
  },
3880
3895
  ],
3881
3896
  clientMediaPreferences: {
3882
- preferTranscoding: !meeting.isMultistream,
3883
- joinCookie: undefined,
3884
- ipver: 0,
3897
+ id: 'fake clientMediaPreferences',
3885
3898
  },
3886
3899
  },
3887
3900
  });
@@ -3902,13 +3915,11 @@ describe('plugin-meetings', () => {
3902
3915
  },
3903
3916
  correlationId: meeting.correlationId,
3904
3917
  clientMediaPreferences: {
3905
- preferTranscoding: !meeting.isMultistream,
3906
- ipver: undefined,
3907
- joinCookie: undefined,
3918
+ id: 'fake clientMediaPreferences',
3908
3919
  },
3909
3920
  localMedias: [
3910
3921
  {
3911
- localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted},"roapMessage":{"messageType":"OK","version":"2","seq":"${seq}"}}`,
3922
+ localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted},"roapMessage":{"messageType":"OK","version":"2","seq":"${seq}"},"reachability":{"id":"fake reachability"}}`,
3912
3923
  mediaId: 'fake media id',
3913
3924
  },
3914
3925
  ],
@@ -3934,10 +3945,6 @@ describe('plugin-meetings', () => {
3934
3945
  mediaId: 'fake media id',
3935
3946
  },
3936
3947
  ],
3937
- clientMediaPreferences: {
3938
- preferTranscoding: !meeting.isMultistream,
3939
- ipver: undefined,
3940
- },
3941
3948
  respOnlySdp: true,
3942
3949
  usingResource: null,
3943
3950
  },
@@ -3993,7 +4000,10 @@ describe('plugin-meetings', () => {
3993
4000
  assert.notCalled(
3994
4001
  meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream
3995
4002
  );
3996
- assert.throws(meeting.publishStreams(localStreams), `Attempted to publish microphone stream with ended readyState, correlationId=${meeting.correlationId}`);
4003
+ assert.throws(
4004
+ meeting.publishStreams(localStreams),
4005
+ `Attempted to publish microphone stream with ended readyState, correlationId=${meeting.correlationId}`
4006
+ );
3997
4007
  } else {
3998
4008
  assert.calledOnceWithExactly(
3999
4009
  meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream,
@@ -4006,7 +4016,10 @@ describe('plugin-meetings', () => {
4006
4016
  assert.notCalled(
4007
4017
  meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream
4008
4018
  );
4009
- assert.throws(meeting.publishStreams(localStreams), `Attempted to publish camera stream with ended readyState, correlationId=${meeting.correlationId}`);
4019
+ assert.throws(
4020
+ meeting.publishStreams(localStreams),
4021
+ `Attempted to publish camera stream with ended readyState, correlationId=${meeting.correlationId}`
4022
+ );
4010
4023
  } else {
4011
4024
  assert.calledOnceWithExactly(
4012
4025
  meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream,
@@ -4019,7 +4032,10 @@ describe('plugin-meetings', () => {
4019
4032
  assert.notCalled(
4020
4033
  meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream
4021
4034
  );
4022
- assert.throws(meeting.publishStreams(localStreams), `Attempted to publish screenShare audio stream with ended readyState, correlationId=${meeting.correlationId}`);
4035
+ assert.throws(
4036
+ meeting.publishStreams(localStreams),
4037
+ `Attempted to publish screenShare audio stream with ended readyState, correlationId=${meeting.correlationId}`
4038
+ );
4023
4039
  } else {
4024
4040
  assert.calledOnceWithExactly(
4025
4041
  meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
@@ -4032,7 +4048,10 @@ describe('plugin-meetings', () => {
4032
4048
  assert.notCalled(
4033
4049
  meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream
4034
4050
  );
4035
- assert.throws(meeting.publishStreams(localStreams), `Attempted to publish screenShare video stream with ended readyState, correlationId=${meeting.correlationId}`);
4051
+ assert.throws(
4052
+ meeting.publishStreams(localStreams),
4053
+ `Attempted to publish screenShare video stream with ended readyState, correlationId=${meeting.correlationId}`
4054
+ );
4036
4055
  } else {
4037
4056
  assert.calledOnceWithExactly(
4038
4057
  meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream,
@@ -4327,14 +4346,14 @@ describe('plugin-meetings', () => {
4327
4346
  const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4328
4347
  await meeting.addMedia({audioEnabled: false});
4329
4348
  //calling handleDeviceLogging with audioEnaled as true adn videoEnabled as false
4330
- assert.calledWith(handleDeviceLoggingSpy,false,true);
4349
+ assert.calledWith(handleDeviceLoggingSpy, false, true);
4331
4350
  });
4332
4351
 
4333
4352
  it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
4334
4353
  const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4335
4354
  await meeting.addMedia({videoEnabled: false});
4336
4355
  //calling handleDeviceLogging audioEnabled as true videoEnabled as false
4337
- assert.calledWith(handleDeviceLoggingSpy,true,false);
4356
+ assert.calledWith(handleDeviceLoggingSpy, true, false);
4338
4357
  });
4339
4358
 
4340
4359
  it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
@@ -4403,12 +4422,11 @@ describe('plugin-meetings', () => {
4403
4422
  assert.calledTwice(locusMediaRequestStub);
4404
4423
  });
4405
4424
 
4406
-
4407
4425
  it('addMedia() works correctly when both shareAudio and shareVideo is disabled with no streams publish', async () => {
4408
4426
  const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
4409
4427
  await meeting.addMedia({shareAudioEnabled: false, shareVideoEnabled: false});
4410
4428
  //calling handleDeviceLogging with audioEnabled true and videoEnabled as true
4411
- assert.calledWith(handleDeviceLoggingSpy,true,true);
4429
+ assert.calledWith(handleDeviceLoggingSpy, true, true);
4412
4430
  });
4413
4431
 
4414
4432
  describe('publishStreams()/unpublishStreams() calls', () => {
@@ -6263,14 +6281,22 @@ describe('plugin-meetings', () => {
6263
6281
  meeting.attrs.meetingInfoProvider = {
6264
6282
  fetchMeetingInfo: sinon
6265
6283
  .stub()
6266
- .throws(new MeetingInfoV2WebinarRegistrationError(403021, FAKE_MEETING_INFO, 'a message')),
6284
+ .throws(
6285
+ new MeetingInfoV2WebinarRegistrationError(403021, FAKE_MEETING_INFO, 'a message')
6286
+ ),
6267
6287
  };
6268
6288
 
6269
- await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), WebinarRegistrationError);
6289
+ await assert.isRejected(
6290
+ meeting.fetchMeetingInfo({sendCAevents: true}),
6291
+ WebinarRegistrationError
6292
+ );
6270
6293
 
6271
6294
  assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
6272
6295
  assert.equal(meeting.meetingInfoFailureCode, 403021);
6273
- assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION);
6296
+ assert.equal(
6297
+ meeting.meetingInfoFailureReason,
6298
+ MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION
6299
+ );
6274
6300
  });
6275
6301
  });
6276
6302
 
@@ -6985,7 +7011,10 @@ describe('plugin-meetings', () => {
6985
7011
  assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
6986
7012
  meeting.setCorrelationId(uuid1);
6987
7013
  assert.equal(meeting.correlationId, uuid1);
6988
- assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, sessionCorrelationId: ''});
7014
+ assert.deepEqual(meeting.callStateForMetrics, {
7015
+ correlationId: uuid1,
7016
+ sessionCorrelationId: '',
7017
+ });
6989
7018
  });
6990
7019
  });
6991
7020
 
@@ -7657,11 +7686,11 @@ describe('plugin-meetings', () => {
7657
7686
  id: 'stream',
7658
7687
  getTracks: () => [{id: 'track', addEventListener: sinon.stub()}],
7659
7688
  };
7660
- const simulateConnectionStateChange = (newState) => {
7689
+ const simulateConnectionStateChange = async (newState) => {
7661
7690
  meeting.mediaProperties.webrtcMediaConnection.getConnectionState = sinon
7662
7691
  .stub()
7663
7692
  .returns(newState);
7664
- eventListeners[MediaConnectionEventNames.PEER_CONNECTION_STATE_CHANGED]();
7693
+ await eventListeners[MediaConnectionEventNames.PEER_CONNECTION_STATE_CHANGED]();
7665
7694
  };
7666
7695
 
7667
7696
  beforeEach(() => {
@@ -7731,11 +7760,17 @@ describe('plugin-meetings', () => {
7731
7760
  });
7732
7761
 
7733
7762
  it('should collect ice candidates', () => {
7734
- eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: 'candidate'});
7763
+ eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: {candidate: 'candidate'}});
7735
7764
 
7736
7765
  assert.equal(meeting.iceCandidatesCount, 1);
7737
7766
  });
7738
7767
 
7768
+ it('should not collect empty ice candidates', () => {
7769
+ eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: {candidate: ''}});
7770
+
7771
+ assert.equal(meeting.iceCandidatesCount, 0);
7772
+ });
7773
+
7739
7774
  it('should not collect null ice candidates', () => {
7740
7775
  eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: null});
7741
7776
 
@@ -7917,7 +7952,7 @@ describe('plugin-meetings', () => {
7917
7952
  meeting.reconnectionManager = new ReconnectionManager(meeting);
7918
7953
  meeting.reconnectionManager.iceReconnected = sinon.stub().returns(undefined);
7919
7954
  meeting.setNetworkStatus = sinon.stub().returns(undefined);
7920
- meeting.statsAnalyzer = {startAnalyzer: sinon.stub()};
7955
+ meeting.statsAnalyzer = {startAnalyzer: sinon.stub(), stopAnalyzer: sinon.stub()};
7921
7956
  meeting.mediaProperties.webrtcMediaConnection = {
7922
7957
  // mock the on() method and store all the listeners
7923
7958
  on: sinon.stub().callsFake((event, listener) => {
@@ -7992,10 +8027,10 @@ describe('plugin-meetings', () => {
7992
8027
  });
7993
8028
 
7994
8029
  describe('CONNECTION_STATE_CHANGED event when state = "Failed"', () => {
7995
- const mockFailedEvent = () => {
8030
+ const mockFailedEvent = async () => {
7996
8031
  meeting.setupMediaConnectionListeners();
7997
8032
 
7998
- simulateConnectionStateChange(ConnectionState.Failed);
8033
+ await simulateConnectionStateChange(ConnectionState.Failed);
7999
8034
  };
8000
8035
 
8001
8036
  const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
@@ -8025,6 +8060,22 @@ describe('plugin-meetings', () => {
8025
8060
  assert.notCalled(webex.internal.newMetrics.submitClientEvent);
8026
8061
  checkBehavioralMetricSent(true);
8027
8062
  });
8063
+
8064
+ it('stop stats analyzer during reconnection ', async () => {
8065
+ meeting.hasMediaConnectionConnectedAtLeastOnce = true;
8066
+ meeting.statsAnalyzer.stopAnalyzer = sinon.stub().resolves();
8067
+ meeting.reconnectionManager = {
8068
+ reconnect: sinon.stub().resolves(),
8069
+ resetReconnectionTimer: () => {}
8070
+ };
8071
+ meeting.currentMediaStatus = {
8072
+ video: true
8073
+ };
8074
+
8075
+ await mockFailedEvent();
8076
+
8077
+ assert.calledOnce(meeting.statsAnalyzer.stopAnalyzer);
8078
+ });
8028
8079
  });
8029
8080
 
8030
8081
  describe('should send correct metrics for ROAP_FAILURE event', () => {
@@ -8885,6 +8936,78 @@ describe('plugin-meetings', () => {
8885
8936
  );
8886
8937
  });
8887
8938
 
8939
+ it('listens to MEETING_CONTROLS_WEBCAST_UPDATED', async () => {
8940
+ const state = {example: 'value'};
8941
+
8942
+ await meeting.locusInfo.emitScoped(
8943
+ {function: 'test', file: 'test'},
8944
+ LOCUSINFO.EVENTS.CONTROLS_WEBCAST_CHANGED,
8945
+ {state}
8946
+ );
8947
+
8948
+ assert.calledWith(
8949
+ TriggerProxy.trigger,
8950
+ meeting,
8951
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
8952
+ EVENT_TRIGGERS.MEETING_CONTROLS_WEBCAST_UPDATED,
8953
+ {state}
8954
+ );
8955
+ });
8956
+
8957
+ it('listens to MEETING_CONTROLS_MEETING_FULL_UPDATED', async () => {
8958
+ const state = {example: 'value'};
8959
+
8960
+ await meeting.locusInfo.emitScoped(
8961
+ {function: 'test', file: 'test'},
8962
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_FULL_CHANGED,
8963
+ {state}
8964
+ );
8965
+
8966
+ assert.calledWith(
8967
+ TriggerProxy.trigger,
8968
+ meeting,
8969
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
8970
+ EVENT_TRIGGERS.MEETING_CONTROLS_MEETING_FULL_UPDATED,
8971
+ {state}
8972
+ );
8973
+ });
8974
+
8975
+ it('listens to MEETING_CONTROLS_PRACTICE_SESSION_STATUS_UPDATED', async () => {
8976
+ const state = {example: 'value'};
8977
+
8978
+ await meeting.locusInfo.emitScoped(
8979
+ {function: 'test', file: 'test'},
8980
+ LOCUSINFO.EVENTS.CONTROLS_PRACTICE_SESSION_STATUS_UPDATED,
8981
+ {state}
8982
+ );
8983
+
8984
+ assert.calledWith(
8985
+ TriggerProxy.trigger,
8986
+ meeting,
8987
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
8988
+ EVENT_TRIGGERS.MEETING_CONTROLS_PRACTICE_SESSION_STATUS_UPDATED,
8989
+ {state}
8990
+ );
8991
+ });
8992
+
8993
+ it('listens to MEETING_CONTROLS_STAGE_VIEW_UPDATED', async () => {
8994
+ const state = {example: 'value'};
8995
+
8996
+ await meeting.locusInfo.emitScoped(
8997
+ {function: 'test', file: 'test'},
8998
+ LOCUSINFO.EVENTS.CONTROLS_STAGE_VIEW_UPDATED,
8999
+ {state}
9000
+ );
9001
+
9002
+ assert.calledWith(
9003
+ TriggerProxy.trigger,
9004
+ meeting,
9005
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
9006
+ EVENT_TRIGGERS.MEETING_CONTROLS_STAGE_VIEW_UPDATED,
9007
+ {state}
9008
+ );
9009
+ });
9010
+
8888
9011
  it('listens to MEETING_CONTROLS_VIDEO_UPDATED', async () => {
8889
9012
  const state = {example: 'value'};
8890
9013
 
@@ -8998,12 +9121,6 @@ describe('plugin-meetings', () => {
8998
9121
  approval: {
8999
9122
  url: 'url',
9000
9123
  },
9001
- webcast: {
9002
- url: 'url',
9003
- },
9004
- webinarAttendeesSearching: {
9005
- url: 'url',
9006
- },
9007
9124
  },
9008
9125
  };
9009
9126
 
@@ -9017,10 +9134,6 @@ describe('plugin-meetings', () => {
9017
9134
  meeting.simultaneousInterpretation = {
9018
9135
  approvalUrlUpdate: sinon.stub().returns(undefined),
9019
9136
  };
9020
- meeting.webinar = {
9021
- webcastUrlUpdate: sinon.stub().returns(undefined),
9022
- webinarAttendeesSearchingUrlUpdate: sinon.stub().returns(undefined),
9023
- };
9024
9137
 
9025
9138
  meeting.locusInfo.emit(
9026
9139
  {function: 'test', file: 'test'},
@@ -9040,19 +9153,37 @@ describe('plugin-meetings', () => {
9040
9153
  meeting.simultaneousInterpretation.approvalUrlUpdate,
9041
9154
  newLocusServices.services.approval.url
9042
9155
  );
9043
- assert.calledWith(
9044
- meeting.webinar.webcastUrlUpdate,
9045
- newLocusServices.services.webcast.url
9046
- );
9047
- assert.calledWith(
9048
- meeting.webinar.webinarAttendeesSearchingUrlUpdate,
9049
- newLocusServices.services.webinarAttendeesSearching.url
9050
- );
9051
9156
  assert.calledOnce(meeting.recordingController.setSessionId);
9052
9157
  done();
9053
9158
  });
9054
9159
  });
9055
9160
 
9161
+ describe('#setUpLocusResourcesListener', () => {
9162
+ it('listens to the locus resources update event', (done) => {
9163
+ const newLocusResources = {
9164
+ resources: {
9165
+ webcastInstance: {
9166
+ url: 'url',
9167
+ },
9168
+ },
9169
+ };
9170
+
9171
+ meeting.webinar = {
9172
+ updateWebcastUrl: sinon.stub().returns(undefined),
9173
+ };
9174
+
9175
+ meeting.locusInfo.emit(
9176
+ {function: 'test', file: 'test'},
9177
+ 'LINKS_RESOURCES',
9178
+ newLocusResources
9179
+ );
9180
+
9181
+ assert.calledWith(meeting.webinar.updateWebcastUrl, newLocusResources);
9182
+
9183
+ done();
9184
+ });
9185
+ });
9186
+
9056
9187
  describe('#setUpLocusInfoMediaInactiveListener', () => {
9057
9188
  it('listens to disconnect due to un activity ', (done) => {
9058
9189
  TriggerProxy.trigger.reset();
@@ -12205,14 +12336,10 @@ describe('plugin-meetings', () => {
12205
12336
  const testEmit = async (unmuteAllowed) => {
12206
12337
  meeting.audio = {
12207
12338
  handleServerLocalUnmuteRequired: sinon.stub(),
12208
- }
12209
- await meeting.locusInfo.emitScoped(
12210
- {},
12211
- LOCUSINFO.EVENTS.LOCAL_UNMUTE_REQUIRED,
12212
- {
12213
- unmuteAllowed,
12214
- }
12215
- );
12339
+ };
12340
+ await meeting.locusInfo.emitScoped({}, LOCUSINFO.EVENTS.LOCAL_UNMUTE_REQUIRED, {
12341
+ unmuteAllowed,
12342
+ });
12216
12343
 
12217
12344
  assert.calledWith(
12218
12345
  TriggerProxy.trigger,
@@ -12228,7 +12355,11 @@ describe('plugin-meetings', () => {
12228
12355
  },
12229
12356
  }
12230
12357
  );
12231
- assert.calledOnceWithExactly(meeting.audio.handleServerLocalUnmuteRequired, meeting, unmuteAllowed)
12358
+ assert.calledOnceWithExactly(
12359
+ meeting.audio.handleServerLocalUnmuteRequired,
12360
+ meeting,
12361
+ unmuteAllowed
12362
+ );
12232
12363
  };
12233
12364
 
12234
12365
  [true, false].forEach((unmuteAllowed) => {
@@ -34,12 +34,19 @@ describe('LocusMediaRequest.send()', () => {
34
34
  'wjfkm.wjfkm.*': {udp:{reachable: true}, tcp:{reachable:false}},
35
35
  '1eb65fdf-9643-417f-9974-ad72cae0e10f.59268c12-7a04-4b23-a1a1-4c74be03019a.*': {udp:{reachable: false}, tcp:{reachable:true}},
36
36
  },
37
- joinCookie: {
38
- anycastEntryPoint: 'aws-eu-west-1',
39
- clientIpAddress: 'some ip',
40
- timeShot: '2023-05-23T08:03:49Z',
41
- },
42
- ipVersion: IP_VERSION.only_ipv4,
37
+ clientMediaPreferences: {
38
+ preferTranscoding: false,
39
+ joinCookie: {
40
+ anycastEntryPoint: 'aws-eu-west-1',
41
+ clientIpAddress: 'some ip',
42
+ timeShot: '2023-05-23T08:03:49Z',
43
+ },
44
+ ipver: IP_VERSION.only_ipv4,
45
+ reachability: {
46
+ version: '1',
47
+ result: 'some fake reachability result',
48
+ }
49
+ }
43
50
  };
44
51
 
45
52
  const createExpectedRoapBody = (expectedMessageType, expectedMute:{audioMuted: boolean, videoMuted: boolean}) => {
@@ -53,12 +60,16 @@ describe('LocusMediaRequest.send()', () => {
53
60
  }
54
61
  ],
55
62
  clientMediaPreferences: {
56
- preferTranscoding: true,
63
+ preferTranscoding: false,
57
64
  ipver: 4,
58
65
  joinCookie: {
59
66
  anycastEntryPoint: 'aws-eu-west-1',
60
67
  clientIpAddress: 'some ip',
61
68
  timeShot: '2023-05-23T08:03:49Z'
69
+ },
70
+ reachability: {
71
+ version: '1',
72
+ result: 'some fake reachability result',
62
73
  }
63
74
  }
64
75
  };
@@ -87,10 +98,6 @@ describe('LocusMediaRequest.send()', () => {
87
98
  localSdp: `{"audioMuted":${expectedMute.audioMuted},"videoMuted":${expectedMute.videoMuted}}`,
88
99
  },
89
100
  ],
90
- clientMediaPreferences: {
91
- preferTranscoding: true,
92
- ipver: undefined,
93
- },
94
101
  };
95
102
 
96
103
  if (sequence) {