@webex/plugin-meetings 3.0.0-beta.34 → 3.0.0-beta.36

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 (71) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/edit-lock-error.js +52 -0
  3. package/dist/breakouts/edit-lock-error.js.map +1 -0
  4. package/dist/breakouts/index.js +86 -2
  5. package/dist/breakouts/index.js.map +1 -1
  6. package/dist/constants.js +14 -2
  7. package/dist/constants.js.map +1 -1
  8. package/dist/media/index.js +4 -18
  9. package/dist/media/index.js.map +1 -1
  10. package/dist/media/properties.js +3 -3
  11. package/dist/media/properties.js.map +1 -1
  12. package/dist/meeting/index.js +194 -306
  13. package/dist/meeting/index.js.map +1 -1
  14. package/dist/meeting/muteState.js +7 -2
  15. package/dist/meeting/muteState.js.map +1 -1
  16. package/dist/meeting/request.js +135 -85
  17. package/dist/meeting/request.js.map +1 -1
  18. package/dist/meeting/util.js +2 -2
  19. package/dist/meeting/util.js.map +1 -1
  20. package/dist/metrics/constants.js +0 -4
  21. package/dist/metrics/constants.js.map +1 -1
  22. package/dist/reachability/index.js +25 -17
  23. package/dist/reachability/index.js.map +1 -1
  24. package/dist/reachability/request.js +12 -5
  25. package/dist/reachability/request.js.map +1 -1
  26. package/dist/reconnection-manager/index.js +1 -2
  27. package/dist/reconnection-manager/index.js.map +1 -1
  28. package/dist/roap/request.js +114 -83
  29. package/dist/roap/request.js.map +1 -1
  30. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  31. package/dist/types/constants.d.ts +13 -1
  32. package/dist/types/media/properties.d.ts +7 -6
  33. package/dist/types/meeting/index.d.ts +11 -36
  34. package/dist/types/meeting/request.d.ts +10 -0
  35. package/dist/types/metrics/constants.d.ts +0 -4
  36. package/dist/types/reachability/request.d.ts +5 -3
  37. package/dist/types/roap/request.d.ts +6 -3
  38. package/package.json +19 -19
  39. package/src/breakouts/README.md +8 -2
  40. package/src/breakouts/edit-lock-error.ts +25 -0
  41. package/src/breakouts/index.ts +73 -0
  42. package/src/constants.ts +13 -1
  43. package/src/media/index.ts +14 -24
  44. package/src/media/properties.ts +16 -10
  45. package/src/meeting/index.ts +122 -204
  46. package/src/meeting/muteState.ts +5 -5
  47. package/src/meeting/request.ts +35 -1
  48. package/src/meeting/util.ts +5 -4
  49. package/src/metrics/constants.ts +0 -4
  50. package/src/reachability/index.ts +12 -4
  51. package/src/reachability/request.ts +10 -5
  52. package/src/reconnection-manager/index.ts +1 -1
  53. package/src/roap/request.ts +93 -78
  54. package/test/integration/spec/converged-space-meetings.js +3 -3
  55. package/test/integration/spec/journey.js +3 -3
  56. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  57. package/test/unit/spec/breakouts/index.ts +92 -1
  58. package/test/unit/spec/media/index.ts +8 -6
  59. package/test/unit/spec/meeting/index.js +87 -114
  60. package/test/unit/spec/meeting/muteState.js +21 -22
  61. package/test/unit/spec/meeting/request.js +27 -0
  62. package/test/unit/spec/meeting/utils.js +3 -1
  63. package/test/unit/spec/reachability/index.ts +18 -7
  64. package/test/unit/spec/reachability/request.js +66 -0
  65. package/test/unit/spec/roap/request.ts +187 -84
  66. package/test/utils/testUtils.js +30 -25
  67. package/dist/meeting/effectsState.js +0 -262
  68. package/dist/meeting/effectsState.js.map +0 -1
  69. package/dist/types/meeting/effectsState.d.ts +0 -42
  70. package/src/meeting/effectsState.ts +0 -211
  71. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -22,7 +22,8 @@ import {
22
22
  LOCUSINFO,
23
23
  PC_BAIL_TIMEOUT,
24
24
  } from '@webex/plugin-meetings/src/constants';
25
- import {ConnectionState, Event, Errors, ErrorType, RemoteTrackType} from '@webex/internal-media-core';
25
+ import * as InternalMediaCoreModule from '@webex/internal-media-core';
26
+ import {ConnectionState, Event, Errors, ErrorType, LocalTrackEvents, RemoteTrackType} from '@webex/internal-media-core';
26
27
  import * as StatsAnalyzerModule from '@webex/plugin-meetings/src/statsAnalyzer';
27
28
  import * as MuteStateModule from '@webex/plugin-meetings/src/meeting/muteState';
28
29
  import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
@@ -194,7 +195,11 @@ describe('plugin-meetings', () => {
194
195
  TriggerProxy.trigger = sinon.stub().returns(true);
195
196
  Metrics.postEvent = sinon.stub();
196
197
  Metrics.initialSetup(null, webex);
197
- MediaUtil.createMediaStream = sinon.stub().returns(true);
198
+ MediaUtil.createMediaStream = sinon.stub().callsFake((tracks) => {
199
+ return {
200
+ getTracks: () => tracks
201
+ };
202
+ });;
198
203
 
199
204
  uuid1 = uuid.v4();
200
205
  uuid2 = uuid.v4();
@@ -483,85 +488,6 @@ describe('plugin-meetings', () => {
483
488
  });
484
489
  });
485
490
  });
486
- describe('#enableBNR', () => {
487
- it('should have #enableBnr', () => {
488
- assert.exists(meeting.enableBNR);
489
- });
490
-
491
- describe('before audio attached to meeting', () => {
492
- it('should throw no audio error', async () => {
493
- await meeting.enableBNR().catch((err) => {
494
- assert.equal(err.toString(), "Error: Meeting doesn't have an audioTrack attached");
495
- });
496
- });
497
- });
498
-
499
- describe('after audio attached to meeting', () => {
500
- let handleClientRequest;
501
-
502
- beforeEach(async () => {
503
- await meeting.getMediaStreams();
504
- await meeting.addMedia();
505
- });
506
-
507
- it('should throw error if meeting audio is muted', async () => {
508
- const handleClientRequest = (meeting, mute) => {
509
- meeting.mediaProperties.audioTrack.enabled = !mute;
510
-
511
- return Promise.resolve();
512
- };
513
- const isMuted = () => !meeting.mediaProperties.audioTrack.enabled;
514
-
515
- meeting.locusInfo.parsedLocus = {self: {state: 'JOINED'}};
516
- meeting.mediaId = 'mediaId';
517
- meeting.audio = {handleClientRequest, isMuted};
518
- await meeting.muteAudio();
519
- await meeting.enableBNR().catch((err) => {
520
- assert.equal(err.message, 'Cannot enable BNR while meeting is muted');
521
- });
522
- });
523
-
524
- it('should return true on enable bnr success', async () => {
525
- handleClientRequest = sinon.stub().returns(Promise.resolve(true));
526
- meeting.effects = {handleClientRequest};
527
- const response = await meeting.enableBNR();
528
-
529
- assert.equal(response, true);
530
- });
531
- });
532
- });
533
-
534
- describe('#disableBNR', () => {
535
- describe('before audio attached to meeting', () => {
536
- it('should have #disableBnr', () => {
537
- assert.exists(meeting.disableBNR);
538
- });
539
-
540
- it('should throw no audio error', async () => {
541
- await meeting.disableBNR().catch((err) => {
542
- assert.equal(err.toString(), "Error: Meeting doesn't have an audioTrack attached");
543
- });
544
- });
545
- });
546
- describe('after audio attached to meeting', () => {
547
- beforeEach(async () => {
548
- await meeting.getMediaStreams();
549
- await meeting.addMedia();
550
- });
551
-
552
- let handleClientRequest;
553
- let isBnrEnabled;
554
-
555
- it('should return true on disable bnr success', async () => {
556
- handleClientRequest = sinon.stub().returns(Promise.resolve(true));
557
- isBnrEnabled = sinon.stub().returns(Promise.resolve(true));
558
- meeting.effects = {handleClientRequest, isBnrEnabled};
559
- const response = await meeting.disableBNR();
560
-
561
- assert.equal(response, true);
562
- });
563
- });
564
- });
565
491
  });
566
492
  describe('#muteVideo', () => {
567
493
  it('should have #muteVideo', () => {
@@ -1311,8 +1237,7 @@ describe('plugin-meetings', () => {
1311
1237
  .addMedia({
1312
1238
  mediaSettings: {},
1313
1239
  })
1314
- .catch((error) => {
1315
- assert.equal(error.code, IceGatheringFailed.CODE);
1240
+ .catch(() => {
1316
1241
  errorThrown = true;
1317
1242
  });
1318
1243
 
@@ -1700,26 +1625,30 @@ describe('plugin-meetings', () => {
1700
1625
 
1701
1626
  it('skips canUpdateMedia() check on contentTracks.onended', () => {
1702
1627
  const {mediaProperties} = meeting;
1703
- let registeredListener = null;
1704
1628
  const fakeTrack = {
1705
1629
  getSettings: sinon.stub().returns({}),
1706
- onended: sinon.stub(),
1707
- addEventListener: sinon.stub().callsFake((event, listener) => {
1708
- registeredListener = listener;
1709
- }),
1710
1630
  };
1711
1631
 
1632
+ const listeners = {};
1633
+
1634
+ const fakeLocalDisplayTrack = {
1635
+ on: sinon.stub().callsFake((event, listener) => {
1636
+ listeners[event] = listener;
1637
+ })
1638
+ };
1639
+ sinon.stub(InternalMediaCoreModule, 'LocalDisplayTrack').returns(fakeLocalDisplayTrack);
1640
+
1641
+
1712
1642
  sandbox.stub(mediaProperties, 'setLocalShareTrack');
1713
- sandbox.stub(mediaProperties, 'shareTrack').value(fakeTrack);
1714
1643
  sandbox.stub(mediaProperties, 'setMediaSettings');
1715
1644
  sandbox.stub(meeting, 'stopShare').resolves(true);
1716
1645
  meeting.setLocalShareTrack(fakeTrack);
1717
1646
 
1718
- assert.calledOnce(fakeTrack.addEventListener);
1719
- assert.calledWith(fakeTrack.addEventListener, 'ended', sinon.match.any);
1720
- assert.isNotNull(registeredListener);
1647
+ assert.calledOnce(fakeLocalDisplayTrack.on);
1648
+ assert.calledWith(fakeLocalDisplayTrack.on, LocalTrackEvents.Ended, sinon.match.any);
1649
+ assert.isNotNull(listeners[LocalTrackEvents.Ended]);
1721
1650
 
1722
- registeredListener();
1651
+ listeners[LocalTrackEvents.Ended]();
1723
1652
 
1724
1653
  assert.calledWith(meeting.stopShare, {skipSignalingCheck: true});
1725
1654
  });
@@ -2135,7 +2064,7 @@ describe('plugin-meetings', () => {
2135
2064
  screenshareVideo: {
2136
2065
  id: 'fake share track',
2137
2066
  getSettings: sinon.stub().returns({}),
2138
- addEventListener: sinon.stub()
2067
+ on: sinon.stub()
2139
2068
  },
2140
2069
  };
2141
2070
 
@@ -2297,7 +2226,7 @@ describe('plugin-meetings', () => {
2297
2226
  screenshareVideo: {
2298
2227
  id: 'fake share track',
2299
2228
  getSettings: sinon.stub().returns({}),
2300
- addEventListener: sinon.stub(),
2229
+ on: sinon.stub(),
2301
2230
  },
2302
2231
  };
2303
2232
 
@@ -3582,6 +3511,12 @@ describe('plugin-meetings', () => {
3582
3511
  let videoTrack;
3583
3512
  let videoShareTrack;
3584
3513
  let createMuteStateStub;
3514
+ let LocalDisplayTrackConstructorStub;
3515
+ let LocalMicrophoneTrackConstructorStub;
3516
+ let LocalCameraTrackConstructorStub;
3517
+ let fakeLocalDisplayTrack;
3518
+ let fakeLocalMicrophoneTrack;
3519
+ let fakeLocalCameraTrack;
3585
3520
 
3586
3521
  beforeEach(() => {
3587
3522
  audioTrack = {
@@ -3594,7 +3529,7 @@ describe('plugin-meetings', () => {
3594
3529
  };
3595
3530
  videoShareTrack = {
3596
3531
  id: 'share track',
3597
- addEventListener: sinon.stub(),
3532
+ on: sinon.stub(),
3598
3533
  removeEventListener: sinon.stub(),
3599
3534
  getSettings: sinon.stub().returns({}),
3600
3535
  };
@@ -3606,6 +3541,28 @@ describe('plugin-meetings', () => {
3606
3541
  unpublishTrack: sinon.stub().resolves({}),
3607
3542
  };
3608
3543
 
3544
+ const createFakeLocalTrack = (originalTrack) => ({
3545
+ on: sinon.stub(),
3546
+ off: sinon.stub(),
3547
+ stop: sinon.stub(),
3548
+ originalTrack
3549
+ });
3550
+
3551
+ // setup mock constructors for webrtc-core local track classes in such a way
3552
+ // that they return the original track correctly (this is needed for unpublish() API tests)
3553
+ LocalDisplayTrackConstructorStub = sinon.stub(InternalMediaCoreModule, 'LocalDisplayTrack').callsFake((stream) => {
3554
+ fakeLocalDisplayTrack = createFakeLocalTrack(stream.getTracks()[0])
3555
+ return fakeLocalDisplayTrack;
3556
+ });
3557
+ LocalMicrophoneTrackConstructorStub = sinon.stub(InternalMediaCoreModule, 'LocalMicrophoneTrack').callsFake((stream) => {
3558
+ fakeLocalMicrophoneTrack = createFakeLocalTrack(stream.getTracks()[0])
3559
+ return fakeLocalMicrophoneTrack;
3560
+ });
3561
+ LocalCameraTrackConstructorStub = sinon.stub(InternalMediaCoreModule, 'LocalCameraTrack').callsFake((stream) => {
3562
+ fakeLocalCameraTrack = createFakeLocalTrack(stream.getTracks()[0])
3563
+ return fakeLocalCameraTrack;
3564
+ });
3565
+
3609
3566
  createMuteStateStub = sinon.stub(MuteStateModule, 'createMuteState').returns({id: 'fake mute state instance'});
3610
3567
  })
3611
3568
  describe('#publishTracks', () => {
@@ -3615,23 +3572,33 @@ describe('plugin-meetings', () => {
3615
3572
  });
3616
3573
 
3617
3574
  const checkAudioPublished = () => {
3575
+ assert.calledWith(MediaUtil.createMediaStream, [audioTrack]);
3576
+ assert.calledOnce(LocalMicrophoneTrackConstructorStub);
3577
+
3618
3578
  assert.calledWith(createMuteStateStub, 'audio', meeting, meeting.mediaProperties.mediaDirection);
3619
- assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, audioTrack, 'main');
3620
- assert.equal(meeting.mediaProperties.audioTrack, audioTrack);
3579
+ assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, fakeLocalMicrophoneTrack);
3580
+ assert.equal(meeting.mediaProperties.audioTrack, fakeLocalMicrophoneTrack);
3621
3581
  assert.equal(meeting.mediaProperties.mediaDirection.sendAudio, true);
3622
3582
  }
3623
3583
 
3624
3584
  const checkVideoPublished = () => {
3585
+ assert.calledWith(MediaUtil.createMediaStream, [videoTrack]);
3586
+ assert.calledOnce(LocalCameraTrackConstructorStub);
3587
+
3625
3588
  assert.calledWith(createMuteStateStub, 'video', meeting, meeting.mediaProperties.mediaDirection);
3626
- assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, videoTrack, 'main');
3627
- assert.equal(meeting.mediaProperties.videoTrack, videoTrack);
3589
+ assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, fakeLocalCameraTrack);
3590
+ assert.equal(meeting.mediaProperties.videoTrack, fakeLocalCameraTrack);
3628
3591
  assert.equal(meeting.mediaProperties.mediaDirection.sendVideo, true);
3629
3592
  }
3630
3593
 
3631
3594
  const checkScreenShareVideoPublished = () => {
3632
3595
  assert.calledOnce(meeting.requestScreenShareFloor);
3633
- assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, videoShareTrack, 'slides');
3634
- assert.equal(meeting.mediaProperties.shareTrack, videoShareTrack);
3596
+
3597
+ assert.calledWith(MediaUtil.createMediaStream, [videoShareTrack]);
3598
+ assert.calledOnce(LocalDisplayTrackConstructorStub);
3599
+
3600
+ assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, fakeLocalDisplayTrack);
3601
+ assert.equal(meeting.mediaProperties.shareTrack, fakeLocalDisplayTrack);
3635
3602
  assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
3636
3603
  }
3637
3604
 
@@ -3685,21 +3652,21 @@ describe('plugin-meetings', () => {
3685
3652
  });
3686
3653
 
3687
3654
  const checkAudioUnpublished = () => {
3688
- assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, audioTrack, 'main');
3655
+ assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, fakeLocalMicrophoneTrack);
3689
3656
 
3690
3657
  assert.equal(meeting.mediaProperties.audioTrack, null);
3691
3658
  assert.equal(meeting.mediaProperties.mediaDirection.sendAudio, false);
3692
3659
  };
3693
3660
 
3694
3661
  const checkVideoUnpublished = () => {
3695
- assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, videoTrack, 'main');
3662
+ assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, fakeLocalCameraTrack);
3696
3663
 
3697
3664
  assert.equal(meeting.mediaProperties.videoTrack, null);
3698
3665
  assert.equal(meeting.mediaProperties.mediaDirection.sendVideo, false);
3699
3666
  }
3700
3667
 
3701
3668
  const checkScreenShareVideoUnpublished = () => {
3702
- assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, videoShareTrack, 'slides');
3669
+ assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, fakeLocalDisplayTrack);
3703
3670
 
3704
3671
  assert.calledOnce(meeting.requestScreenShareFloor);
3705
3672
 
@@ -3924,7 +3891,6 @@ describe('plugin-meetings', () => {
3924
3891
  });
3925
3892
  describe('#setLocalShareTrack', () => {
3926
3893
  it('should trigger a media:ready event with local share stream', () => {
3927
- let registeredListener = null;
3928
3894
  const track = {
3929
3895
  getSettings: sinon.stub().returns({
3930
3896
  aspectRatio: '1.7',
@@ -3934,11 +3900,17 @@ describe('plugin-meetings', () => {
3934
3900
  displaySurface: true,
3935
3901
  cursor: true,
3936
3902
  }),
3937
- addEventListener: sinon.stub().callsFake((event, listener) => {
3938
- registeredListener = listener;
3939
- }),
3940
3903
  };
3941
3904
 
3905
+ const listeners = {};
3906
+ const fakeLocalDisplayTrack = {
3907
+ on: sinon.stub().callsFake((event, listener) => {
3908
+ listeners[event] = listener;
3909
+ })
3910
+ };
3911
+ sinon.stub(InternalMediaCoreModule, 'LocalDisplayTrack').returns(fakeLocalDisplayTrack);
3912
+
3913
+
3942
3914
  meeting.mediaProperties.setLocalShareTrack = sinon.stub().returns(true);
3943
3915
  meeting.stopShare = sinon.stub().resolves(true);
3944
3916
  meeting.mediaProperties.mediaDirection = {};
@@ -3952,8 +3924,8 @@ describe('plugin-meetings', () => {
3952
3924
  );
3953
3925
  assert.calledOnce(meeting.mediaProperties.setLocalShareTrack);
3954
3926
  assert.equal(meeting.mediaProperties.localStream, undefined);
3955
- assert.isNotNull(registeredListener);
3956
- registeredListener();
3927
+ assert.isNotNull(listeners[LocalTrackEvents.Ended]);
3928
+ listeners[LocalTrackEvents.Ended]();
3957
3929
  assert.calledOnce(meeting.stopShare);
3958
3930
  });
3959
3931
  });
@@ -3969,6 +3941,7 @@ describe('plugin-meetings', () => {
3969
3941
  eventListeners[event] = listener;
3970
3942
  }),
3971
3943
  };
3944
+ MediaUtil.createMediaStream.returns({id: 'stream'});
3972
3945
  });
3973
3946
 
3974
3947
  it('should register for all the correct RoapMediaConnection events', () => {
@@ -3990,7 +3963,7 @@ describe('plugin-meetings', () => {
3990
3963
  assert.equal(TriggerProxy.trigger.getCall(1).args[2], 'media:ready');
3991
3964
  assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
3992
3965
  type: 'remoteAudio',
3993
- stream: true,
3966
+ stream: {id: 'stream'},
3994
3967
  });
3995
3968
 
3996
3969
  eventListeners[Event.REMOTE_TRACK_ADDED]({
@@ -4000,7 +3973,7 @@ describe('plugin-meetings', () => {
4000
3973
  assert.equal(TriggerProxy.trigger.getCall(2).args[2], 'media:ready');
4001
3974
  assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
4002
3975
  type: 'remoteVideo',
4003
- stream: true,
3976
+ stream: {id: 'stream'},
4004
3977
  });
4005
3978
 
4006
3979
  eventListeners[Event.REMOTE_TRACK_ADDED]({
@@ -4010,7 +3983,7 @@ describe('plugin-meetings', () => {
4010
3983
  assert.equal(TriggerProxy.trigger.getCall(3).args[2], 'media:ready');
4011
3984
  assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
4012
3985
  type: 'remoteShare',
4013
- stream: true,
3986
+ stream: {id: 'stream'},
4014
3987
  });
4015
3988
  });
4016
3989
 
@@ -19,8 +19,8 @@ describe('plugin-meetings', () => {
19
19
  beforeEach(() => {
20
20
  meeting = {
21
21
  mediaProperties: {
22
- audioTrack: 'fake audio track',
23
- videoTrack: 'fake video track',
22
+ audioTrack: {id: 'fake audio track', setMuted: sinon.stub()},
23
+ videoTrack: {id: 'fake video track', setMuted: sinon.stub()},
24
24
  },
25
25
  remoteMuted: false,
26
26
  unmuteAllowed: true,
@@ -38,7 +38,6 @@ describe('plugin-meetings', () => {
38
38
  originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
39
39
 
40
40
  MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves(fakeLocus);
41
- Media.setLocalTrack = sinon.stub();
42
41
  });
43
42
 
44
43
  afterEach(() => {
@@ -110,8 +109,8 @@ describe('plugin-meetings', () => {
110
109
  audio.handleServerLocalUnmuteRequired(meeting);
111
110
  await testUtils.flushPromises();
112
111
 
113
- // check that local track was enabled
114
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
112
+ // check that local track was unmuted
113
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
115
114
 
116
115
  // and local unmute was sent to server
117
116
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
@@ -161,8 +160,8 @@ describe('plugin-meetings', () => {
161
160
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
162
161
  assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
163
162
 
164
- // and local track should be enabled
165
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
163
+ // and local track should be unmuted
164
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
166
165
 
167
166
  assert.isFalse(audio.isMuted());
168
167
  assert.isFalse(audio.isSelf());
@@ -183,37 +182,37 @@ describe('plugin-meetings', () => {
183
182
  it('disables/enables the local audio track when audio is muted/unmuted', async () => {
184
183
  // mute
185
184
  audio.handleClientRequest(meeting, true);
186
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.audioTrack);
185
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, true);
187
186
 
188
- // even when calling mute when it's already muted should still call setLocalTrack
187
+ // even when calling mute when it's already muted should still call setMuted
189
188
  audio.handleClientRequest(meeting, true);
190
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.audioTrack);
189
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, true);
191
190
 
192
191
  // unmute
193
192
  audio.handleClientRequest(meeting, false);
194
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
193
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
195
194
 
196
- // even when calling unmute when it's already unmuted should still call setLocalTrack
195
+ // even when calling unmute when it's already unmuted should still call setMuted
197
196
  audio.handleClientRequest(meeting, false);
198
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
197
+ assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
199
198
  });
200
199
 
201
200
  it('disables/enables the local video track when video is muted/unmuted', async () => {
202
201
  // mute
203
202
  video.handleClientRequest(meeting, true);
204
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
203
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
205
204
 
206
- // even when calling mute when it's already muted should still call setLocalTrack
205
+ // even when calling mute when it's already muted should still call setMuted
207
206
  video.handleClientRequest(meeting, false);
208
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
207
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
209
208
 
210
209
  // unmute
211
210
  video.handleClientRequest(meeting, false);
212
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
211
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
213
212
 
214
- // even when calling unmute when it's already unmuted should still call setLocalTrack
213
+ // even when calling unmute when it's already unmuted should still call setMuted
215
214
  video.handleClientRequest(meeting, false);
216
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
215
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
217
216
  });
218
217
 
219
218
  it('returns correct value in isMuted()/isSelf() methods after client mute/unmute requests', async () => {
@@ -389,11 +388,11 @@ describe('plugin-meetings', () => {
389
388
  assert.isTrue(video.isSelf());
390
389
 
391
390
  // check local mute is done, but not remote one
392
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
391
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
393
392
  assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, true, meeting);
394
393
  assert.notCalled(meeting.members.muteMember);
395
394
 
396
- Media.setLocalTrack.resetHistory();
395
+ meeting.mediaProperties.videoTrack.setMuted.resetHistory();
397
396
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
398
397
  meeting.members.muteMember.resetHistory();
399
398
 
@@ -403,7 +402,7 @@ describe('plugin-meetings', () => {
403
402
  assert.isFalse(video.isMuted());
404
403
  assert.isFalse(video.isSelf());
405
404
 
406
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
405
+ assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
407
406
  assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, false, meeting);
408
407
  assert.notCalled(meeting.members.muteMember);
409
408
  });
@@ -26,6 +26,8 @@ describe('plugin-meetings', () => {
26
26
  },
27
27
  };
28
28
 
29
+ webex.boundedStorage.get = sinon.mock().returns(Promise.resolve(JSON.stringify({anycastEntryPoint: "aws-eu-west-1"})))
30
+
29
31
  meetingsRequest = new MeetingRequest(
30
32
  {},
31
33
  {
@@ -206,6 +208,31 @@ describe('plugin-meetings', () => {
206
208
  const requestParams = meetingsRequest.request.getCall(0).args[0];
207
209
 
208
210
  assert.deepEqual(requestParams.body.deviceCapabilities, undefined);
211
+
212
+ });
213
+
214
+ it('includes joinCookie correctly', async () => {
215
+ const locusUrl = 'locusURL';
216
+ const deviceUrl = 'deviceUrl';
217
+ const correlationId = 'random-uuid';
218
+ const roapMessage = 'roap-message';
219
+ const permissionToken = 'permission-token';
220
+
221
+ await meetingsRequest.joinMeeting({
222
+ locusUrl,
223
+ deviceUrl,
224
+ correlationId,
225
+ roapMessage,
226
+ permissionToken,
227
+ });
228
+ const requestParams = meetingsRequest.request.getCall(0).args[0];
229
+
230
+ assert.equal(requestParams.method, 'POST');
231
+ assert.equal(requestParams.uri, `${locusUrl}/participant?alternateRedirect=true`);
232
+ assert.deepEqual(requestParams.body.clientMediaPreferences, {
233
+ "joinCookie": {anycastEntryPoint: "aws-eu-west-1"},
234
+ "preferTranscoding": true
235
+ });
209
236
  });
210
237
  });
211
238
 
@@ -71,7 +71,9 @@ describe('plugin-meetings', () => {
71
71
  });
72
72
 
73
73
  const mockTrack = {
74
- getSettings: fakeDevice,
74
+ underlyingTrack: {
75
+ getSettings: fakeDevice,
76
+ }
75
77
  };
76
78
 
77
79
  it('#log - should log [info, warn, error, log] to console', () => {
@@ -22,8 +22,8 @@ describe('isAnyClusterReachable', () => {
22
22
 
23
23
  const result = await reachability.isAnyClusterReachable();
24
24
 
25
- assert.equal(result, expectedValue);
26
- };
25
+ assert.equal(result, expectedValue);
26
+ };
27
27
 
28
28
  it('returns true when udp is reachable', async () => {
29
29
  await checkIsClusterReachable({x: {udp: {reachable: 'true'}, tcp: {reachable: 'false'}}}, true);
@@ -66,19 +66,30 @@ describe('gatherReachability', () => {
66
66
  it('stores the reachability', async () => {
67
67
  const reachability = new Reachability(webex);
68
68
 
69
- const clusters = {some: 'clusters'};
70
- const reachabilityResults = {some: 'results'};
69
+ const reachabilityResults = {
70
+ clusters: {
71
+ clusterId: {
72
+ udp: 'testUDP',
73
+ },
74
+ },
75
+ }
76
+ const getClustersResult = {
77
+ clusters: {clusterId: 'cluster'},
78
+ joinCookie: {id: 'id'}
79
+ };
71
80
 
72
- reachability.reachabilityRequest.getClusters = sinon.stub().returns(clusters);
81
+ reachability.reachabilityRequest.getClusters = sinon.stub().returns(getClustersResult);
73
82
  (reachability as any).performReachabilityCheck = sinon.stub().returns(reachabilityResults)
74
83
 
75
84
  const result = await reachability.gatherReachability();
76
85
 
77
86
  assert.equal(result, reachabilityResults);
78
87
 
79
- const storedResult = await webex.boundedStorage.get('Reachability', 'reachability.result');
88
+ const storedResultForReachabilityResult = await webex.boundedStorage.get('Reachability', 'reachability.result');
89
+ const storedResultForJoinCookie = await webex.boundedStorage.get('Reachability', 'reachability.joinCookie');
80
90
 
81
- assert.equal(JSON.stringify(result), storedResult);
91
+ assert.equal(JSON.stringify(result), storedResultForReachabilityResult);
92
+ assert.equal(JSON.stringify(getClustersResult.joinCookie), storedResultForJoinCookie);
82
93
  });
83
94
 
84
95
  });
@@ -0,0 +1,66 @@
1
+ import sinon from 'sinon';
2
+ import {assert} from '@webex/test-helper-chai';
3
+ import MockWebex from '@webex/test-helper-mock-webex';
4
+ import Meetings from '@webex/plugin-meetings';
5
+ import ReachabilityRequest from '@webex/plugin-meetings/src/reachability/request';
6
+
7
+
8
+ describe('plugin-meetings/reachability', () => {
9
+ let reachabilityRequest;
10
+ let webex;
11
+
12
+ beforeEach(() => {
13
+ webex = new MockWebex({
14
+ children: {
15
+ meetings: Meetings,
16
+ },
17
+ });
18
+
19
+ webex.meetings.clientRegion = {
20
+ countryCode: 'US',
21
+ regionCode: 'WEST-COAST',
22
+ };
23
+
24
+ webex.internal = {
25
+ services: {
26
+ get: sinon.mock().returns('locusUrl'),
27
+ waitForCatalog: sinon.mock().returns(Promise.resolve({})),
28
+ },
29
+ };
30
+
31
+
32
+ reachabilityRequest = new ReachabilityRequest(webex);
33
+
34
+ });
35
+
36
+ describe('#getClusters', () => {
37
+ it('sends a GET request with the correct params', async () => {
38
+ webex.request = sinon.mock().returns(Promise.resolve({
39
+ body: {
40
+ clusterClasses: {
41
+ hybridMedia: ["clusterId"]
42
+ },
43
+ clusters: {"clusterId": {
44
+ udp: "testUDP"
45
+ }},
46
+ joinCookie: {anycastEntryPoint: "aws-eu-west-1"}
47
+ }
48
+ }));
49
+
50
+ const res = await reachabilityRequest.getClusters();
51
+
52
+ const requestParams = webex.request.getCall(0).args[0];
53
+
54
+ assert.equal(requestParams.method, 'GET');
55
+ assert.equal(requestParams.resource, `clusters`);
56
+ assert.equal(requestParams.api, 'calliopeDiscovery');
57
+ assert.equal(requestParams.shouldRefreshAccessToken, false);
58
+
59
+ assert.deepEqual(requestParams.qs, {
60
+ JCSupport: 1,
61
+ });
62
+ assert.deepEqual(res.clusters.clusterId, {udp: "testUDP", isVideoMesh: true})
63
+ assert.deepEqual(res.joinCookie, {anycastEntryPoint: "aws-eu-west-1"})
64
+ });
65
+ });
66
+ });