@webex/plugin-meetings 3.0.0-beta.111 → 3.0.0-beta.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/media/index.js +0 -21
  4. package/dist/media/index.js.map +1 -1
  5. package/dist/meeting/index.js +19 -0
  6. package/dist/meeting/index.js.map +1 -1
  7. package/dist/meeting/locusMediaRequest.js +288 -0
  8. package/dist/meeting/locusMediaRequest.js.map +1 -0
  9. package/dist/meeting/muteState.js +49 -34
  10. package/dist/meeting/muteState.js.map +1 -1
  11. package/dist/meeting/request.js +0 -39
  12. package/dist/meeting/request.js.map +1 -1
  13. package/dist/meeting/util.js +17 -18
  14. package/dist/meeting/util.js.map +1 -1
  15. package/dist/roap/index.js +4 -19
  16. package/dist/roap/index.js.map +1 -1
  17. package/dist/roap/request.js +23 -39
  18. package/dist/roap/request.js.map +1 -1
  19. package/dist/roap/turnDiscovery.js +2 -10
  20. package/dist/roap/turnDiscovery.js.map +1 -1
  21. package/dist/types/meeting/index.d.ts +3 -0
  22. package/dist/types/meeting/locusMediaRequest.d.ts +68 -0
  23. package/dist/types/meeting/muteState.d.ts +3 -2
  24. package/dist/types/meeting/request.d.ts +0 -18
  25. package/dist/types/roap/request.d.ts +6 -8
  26. package/dist/types/roap/turnDiscovery.d.ts +4 -1
  27. package/package.json +19 -19
  28. package/src/media/index.ts +0 -23
  29. package/src/meeting/index.ts +22 -0
  30. package/src/meeting/locusMediaRequest.ts +303 -0
  31. package/src/meeting/muteState.ts +24 -9
  32. package/src/meeting/request.ts +0 -46
  33. package/src/meeting/util.ts +15 -13
  34. package/src/roap/index.ts +4 -16
  35. package/src/roap/request.ts +22 -42
  36. package/src/roap/turnDiscovery.ts +2 -8
  37. package/test/unit/spec/meeting/locusMediaRequest.ts +414 -0
  38. package/test/unit/spec/meeting/muteState.js +97 -71
  39. package/test/unit/spec/meeting/utils.js +11 -37
  40. package/test/unit/spec/roap/index.ts +2 -37
  41. package/test/unit/spec/roap/request.ts +27 -57
  42. package/test/unit/spec/roap/turnDiscovery.ts +3 -5
@@ -1,7 +1,7 @@
1
1
  import sinon from 'sinon';
2
2
  import {assert} from '@webex/test-helper-chai';
3
3
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
4
- import {createMuteState} from '@webex/plugin-meetings/src/meeting/muteState';
4
+ import {createMuteState, MuteState} from '@webex/plugin-meetings/src/meeting/muteState';
5
5
  import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
6
6
  import {AUDIO, VIDEO} from '@webex/plugin-meetings/src/constants';
7
7
 
@@ -24,7 +24,7 @@ describe('plugin-meetings', () => {
24
24
  };
25
25
  };
26
26
 
27
- beforeEach(() => {
27
+ beforeEach(async () => {
28
28
  meeting = {
29
29
  mediaProperties: {
30
30
  audioTrack: createFakeLocalTrack('fake audio track'),
@@ -44,12 +44,14 @@ describe('plugin-meetings', () => {
44
44
  },
45
45
  };
46
46
 
47
- audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
48
- video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
49
-
50
47
  originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
51
48
 
52
49
  MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves(fakeLocus);
50
+
51
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
52
+ video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
53
+
54
+ await testUtils.flushPromises();
53
55
  });
54
56
 
55
57
  afterEach(() => {
@@ -70,8 +72,11 @@ describe('plugin-meetings', () => {
70
72
  it('takes into account current remote mute status when instantiated', async () => {
71
73
  // simulate being already remote muted
72
74
  meeting.remoteMuted = true;
73
- // create a new MuteState intance
74
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
75
+
76
+ // create a new MuteState instance
77
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
78
+
79
+ await testUtils.flushPromises();
75
80
 
76
81
  assert.isTrue(audio.isMuted());
77
82
  assert.isFalse(audio.isSelf());
@@ -79,8 +84,10 @@ describe('plugin-meetings', () => {
79
84
  // now check the opposite case
80
85
  meeting.remoteMuted = false;
81
86
 
82
- // create a new MuteState intance
83
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
87
+ // create a new MuteState instance
88
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
89
+
90
+ await testUtils.flushPromises();
84
91
 
85
92
  assert.isFalse(audio.isMuted());
86
93
  assert.isFalse(audio.isSelf());
@@ -92,7 +99,9 @@ describe('plugin-meetings', () => {
92
99
  meeting.unmuteVideoAllowed = false;
93
100
 
94
101
  // create a new video MuteState instance
95
- video = createMuteState(VIDEO, meeting, {sendVideo: true});
102
+ video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
103
+
104
+ await testUtils.flushPromises();
96
105
 
97
106
  assert.isFalse(video.isMuted());
98
107
  assert.isFalse(video.state.server.remoteMute);
@@ -127,7 +136,7 @@ describe('plugin-meetings', () => {
127
136
 
128
137
  // and local unmute was sent to server
129
138
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
130
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
139
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
131
140
 
132
141
  assert.isFalse(audio.isMuted());
133
142
  assert.isFalse(audio.isSelf());
@@ -171,7 +180,7 @@ describe('plugin-meetings', () => {
171
180
 
172
181
  // local unmute should be sent to server
173
182
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
174
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
183
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
175
184
 
176
185
  // and local track should be unmuted
177
186
  assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
@@ -198,7 +207,7 @@ describe('plugin-meetings', () => {
198
207
 
199
208
  // and local unmute was sent to server
200
209
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
201
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, false, meeting);
210
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
202
211
 
203
212
  assert.isFalse(video.isMuted());
204
213
  assert.isFalse(video.isSelf());
@@ -208,8 +217,10 @@ describe('plugin-meetings', () => {
208
217
  it('does not consider remote mute status for audio', async () => {
209
218
  // simulate being already remote muted
210
219
  meeting.remoteMuted = true;
211
- // create a new MuteState intance
212
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
220
+ // create a new MuteState instance
221
+ audio = createMuteState(AUDIO, meeting, {sendAudio: true}, true);
222
+
223
+ await testUtils.flushPromises();
213
224
 
214
225
  assert.isFalse(audio.isLocallyMuted());
215
226
  });
@@ -217,8 +228,10 @@ describe('plugin-meetings', () => {
217
228
  it('does not consider remote mute status for video', async () => {
218
229
  // simulate being already remote muted
219
230
  meeting.remoteVideoMuted = true;
220
- // create a new MuteState intance
221
- video = createMuteState(VIDEO, meeting, {sendVideo: true});
231
+ // create a new MuteState instance
232
+ video = createMuteState(VIDEO, meeting, {sendVideo: true}, true);
233
+
234
+ await testUtils.flushPromises();
222
235
 
223
236
  assert.isFalse(video.isLocallyMuted());
224
237
  });
@@ -422,7 +435,7 @@ describe('plugin-meetings', () => {
422
435
  await testUtils.flushPromises();
423
436
 
424
437
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
425
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, undefined, meeting);
438
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
426
439
 
427
440
  // now allow the first request to complete
428
441
  serverResponseResolve();
@@ -431,9 +444,7 @@ describe('plugin-meetings', () => {
431
444
 
432
445
  // that should trigger the second server request to be sent
433
446
  assert.calledTwice(MeetingUtil.remoteUpdateAudioVideo);
434
- assert.strictEqual(false, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[0]);
435
- assert.strictEqual(undefined, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[1]);
436
- assert.strictEqual(meeting, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[2]);
447
+ assert.deepEqual([meeting, false, undefined], MeetingUtil.remoteUpdateAudioVideo.getCall(1).args);
437
448
 
438
449
  serverResponseResolve();
439
450
  await testUtils.flushPromises();
@@ -464,7 +475,7 @@ describe('plugin-meetings', () => {
464
475
 
465
476
  // check local mute is done, but not remote one
466
477
  assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
467
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, true, meeting);
478
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
468
479
  assert.notCalled(meeting.members.muteMember);
469
480
 
470
481
  meeting.mediaProperties.videoTrack.setMuted.resetHistory();
@@ -478,33 +489,33 @@ describe('plugin-meetings', () => {
478
489
  assert.isFalse(video.isSelf());
479
490
 
480
491
  assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
481
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, false, meeting);
492
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
482
493
  assert.notCalled(meeting.members.muteMember);
483
494
  });
484
495
 
485
- it('sends correct audio value when sending local mute for video', async () => {
496
+ it('sends undefined value for the other media type when sending local mute', async () => {
486
497
  // make sure the meeting object has mute state machines for both audio and video
487
498
  meeting.audio = audio;
488
499
  meeting.video = video;
489
500
 
490
- // mute audio -> request sent to server should have video unmuted
501
+ // mute audio -> the call to remoteUpdateAudioVideo should have video undefined
491
502
  await audio.handleClientRequest(meeting, true);
492
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, false, meeting);
503
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
493
504
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
494
505
 
495
- // now mute video -> request sent to server should have mute for both audio and video
506
+ // now mute video -> the call to remoteUpdateAudioVideo should have mute for video and undefined for audio
496
507
  await video.handleClientRequest(meeting, true);
497
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, true, meeting);
508
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
498
509
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
499
510
 
500
- // now unmute the audio -> request sent to server should still have video muted
511
+ // now unmute the audio -> the call to remoteUpdateAudioVideo should have video undefined
501
512
  await audio.handleClientRequest(meeting, false);
502
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, true, meeting);
513
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
503
514
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
504
515
 
505
- // unmute video -> request sent to server should have both audio and video unmuted
516
+ // unmute video -> the call to remoteUpdateAudioVideo should have both audio undefined
506
517
  await video.handleClientRequest(meeting, false);
507
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, false, meeting);
518
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
508
519
  });
509
520
  });
510
521
  });
@@ -527,8 +538,7 @@ describe('#init, #handleLocalTrackChange', () => {
527
538
  };
528
539
  };
529
540
 
530
- const setup = (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
531
-
541
+ const setupMeeting = (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
532
542
  const remoteMuteField = mediaType === AUDIO ? 'remoteMuted' : 'remoteVideoMuted';
533
543
 
534
544
  meeting = {
@@ -548,10 +558,19 @@ describe('#init, #handleLocalTrackChange', () => {
548
558
  muteMember: sinon.stub().resolves(),
549
559
  },
550
560
  };
561
+ };
562
+
563
+ const setup = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
564
+
565
+ setupMeeting(mediaType, remoteMuted, muted, defineTracks);
551
566
 
552
567
  const direction = mediaType === AUDIO ? {sendAudio: true} : {sendVideo: true};
553
- sinon.spy(MeetingUtil, 'remoteUpdateAudioVideo');
568
+
554
569
  muteState = createMuteState(mediaType, meeting, direction, false);
570
+
571
+ await testUtils.flushPromises();
572
+
573
+ MeetingUtil.remoteUpdateAudioVideo.resetHistory();
555
574
  }
556
575
 
557
576
  const setupSpies = (mediaType) => {
@@ -574,15 +593,22 @@ describe('#init, #handleLocalTrackChange', () => {
574
593
 
575
594
  tests.forEach(({mediaType, title}) =>
576
595
  describe(title, () => {
596
+ let originalRemoteUpdateAudioVideo;
597
+
598
+ beforeEach(() => {
599
+ originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
600
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves({info: 'fake locus'});
601
+ });
577
602
 
578
603
  afterEach(() => {
604
+ MeetingUtil.remoteUpdateAudioVideo = originalRemoteUpdateAudioVideo;
579
605
  sinon.restore();
580
606
  });
581
607
 
582
608
  describe('#handleLocalTrackChange',() => {
583
609
 
584
610
  it('calls init()', async () => {
585
- setup(mediaType);
611
+ await setup(mediaType);
586
612
  const spy = sinon.spy(muteState, 'init');
587
613
  muteState.handleLocalTrackChange(meeting);
588
614
  assert.calledOnceWithExactly(spy, meeting);
@@ -591,52 +617,56 @@ describe('#init, #handleLocalTrackChange', () => {
591
617
 
592
618
  describe('#init', () => {
593
619
 
594
- afterEach(() => {
595
- sinon.restore();
596
- });
620
+ // does the setup by calling new MuteState() so that MuteState.init() doesn't get called
621
+ const setupWithoutInit = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
622
+
623
+ setupMeeting(mediaType, remoteMuted, muted, defineTracks);
624
+
625
+ muteState = new MuteState(mediaType, meeting, false);
626
+ }
597
627
 
598
628
  it('nothing goes bad when track is undefined', async () => {
599
- setup(mediaType, false, false, false);
629
+ await setupWithoutInit(mediaType, false, false, false);
600
630
  setupSpies(mediaType);
601
-
631
+
602
632
  muteState.init(meeting);
603
-
633
+
604
634
  assert.isFalse(muteState.state.client.localMute);
605
635
  });
606
-
636
+
607
637
  it('tests when track muted is true and remoteMuted is false', async () => {
608
- setup(mediaType, false, true);
638
+ await setupWithoutInit(mediaType, false, true);
609
639
  setupSpies(mediaType);
610
-
640
+
611
641
  muteState.init(meeting);
612
-
642
+
613
643
  assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
614
644
  assert.notCalled(setServerMutedSpy);
615
- assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
645
+ assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
616
646
  assert.isTrue(muteState.state.client.localMute);
617
647
  });
618
648
 
619
-
649
+
620
650
  it('tests when track muted is false and remoteMuted is false', async () => {
621
- setup(mediaType, false, false);
651
+ await setupWithoutInit(mediaType, false, false);
622
652
  setupSpies(mediaType);
623
653
  muteState.state.server.localMute = true;
624
-
654
+
625
655
  muteState.init(meeting);
626
-
656
+
627
657
  assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
628
658
  assert.notCalled(setServerMutedSpy);
629
659
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
630
660
  assert.isFalse(muteState.state.client.localMute);
631
661
  });
632
-
662
+
633
663
  it('tests when remoteMuted is true', async () => {
634
664
  // testing that muteLocalTrack is called
635
- setup(mediaType, true);
665
+ await setupWithoutInit(mediaType, true);
636
666
  setupSpies(mediaType);
637
667
 
638
668
  muteState.init(meeting);
639
-
669
+
640
670
  assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
641
671
  assert.calledOnceWithExactly(setServerMutedSpy, true, 'remotelyMuted');
642
672
  });
@@ -644,13 +674,9 @@ describe('#init, #handleLocalTrackChange', () => {
644
674
 
645
675
  describe('#handleLocalTrackMuteStateChange', () => {
646
676
 
647
- afterEach(() => {
648
- sinon.restore();
649
- });
650
-
651
- it('checks when ignoreMuteStateChange is true nothing changes', () => {
652
- setup(mediaType, false, false);
653
- muteState.ignoreMuteStateChange= true;
677
+ it('checks when ignoreMuteStateChange is true nothing changes', async () => {
678
+ await setup(mediaType, false, false);
679
+ muteState.ignoreMuteStateChange = true;
654
680
 
655
681
  muteState.handleLocalTrackMuteStateChange(meeting, true);
656
682
  assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
@@ -658,16 +684,16 @@ describe('#init, #handleLocalTrackChange', () => {
658
684
  assert.isFalse(muteState.state.client.localMute);
659
685
  });
660
686
 
661
- it('tests localMute - true to false', () => {
662
- setup(mediaType, false, true);
687
+ it('tests localMute - true to false', async () => {
688
+ await setup(mediaType, false, true);
663
689
 
664
690
  muteState.handleLocalTrackMuteStateChange(meeting, false);
665
691
  assert.equal(muteState.state.client.localMute, false);
666
692
  assert.called(MeetingUtil.remoteUpdateAudioVideo);
667
693
  });
668
694
 
669
- it('tests localMute - false to true', () => {
670
- setup(mediaType, false, false);
695
+ it('tests localMute - false to true', async () => {
696
+ await setup(mediaType, false, false);
671
697
 
672
698
  muteState.handleLocalTrackMuteStateChange(meeting, true);
673
699
  assert.equal(muteState.state.client.localMute, true);
@@ -681,8 +707,8 @@ describe('#init, #handleLocalTrackChange', () => {
681
707
  sinon.restore();
682
708
  });
683
709
 
684
- it('checks when sdkOwnsLocalTrack is false', () => {
685
- setup(mediaType);
710
+ it('checks when sdkOwnsLocalTrack is false', async () => {
711
+ await setup(mediaType);
686
712
  setupSpies(mediaType);
687
713
  muteState.sdkOwnsLocalTrack= false;
688
714
 
@@ -691,8 +717,8 @@ describe('#init, #handleLocalTrackChange', () => {
691
717
  assert.notCalled(setMutedSpy);
692
718
  });
693
719
 
694
- it('checks when sdkOwnsLocalTrack is true', () => {
695
- setup(mediaType);
720
+ it('checks when sdkOwnsLocalTrack is true', async () => {
721
+ await setup(mediaType);
696
722
  setupSpies(mediaType);
697
723
  muteState.sdkOwnsLocalTrack= true;
698
724
 
@@ -701,8 +727,8 @@ describe('#init, #handleLocalTrackChange', () => {
701
727
  assert.calledOnceWithExactly(setMutedSpy, muteState.state.client.localMute);
702
728
  });
703
729
 
704
- it('checks nothing explodes when tracks are undefined', () => {
705
- setup(mediaType, false, false, false);
730
+ it('checks nothing explodes when tracks are undefined', async () => {
731
+ await setup(mediaType, false, false, false);
706
732
  setupSpies(mediaType);
707
733
  muteState.sdkOwnsLocalTrack= true;
708
734
 
@@ -134,50 +134,24 @@ describe('plugin-meetings', () => {
134
134
  });
135
135
 
136
136
  describe('remoteUpdateAudioVideo', () => {
137
- it('#Should call meetingRequest.remoteAudioVideoToggle with correct parameters (multistream)', async () => {
137
+ it('#Should call meetingRequest.locusMediaRequest with correct parameters', async () => {
138
138
  const meeting = {
139
- correlationId: 'correlation id',
140
- isMultistream: true,
141
- mediaId: '12345',
142
- meetingJoinUrl: 'meetingJoinUrl',
143
- locusUrl: 'locusUrl',
144
- deviceUrl: 'some device url',
145
- selfId: 'self id',
146
- meetingRequest: {
147
- remoteAudioVideoToggle: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
148
- },
149
- };
150
-
151
- await MeetingUtil.remoteUpdateAudioVideo(true, false, meeting);
152
-
153
- assert.calledOnce(meeting.meetingRequest.remoteAudioVideoToggle);
154
- const parameter = meeting.meetingRequest.remoteAudioVideoToggle.getCall(0).args[0];
155
-
156
- assert.equal(parameter.locusUrl, 'locusUrl');
157
- assert.equal(parameter.selfId, 'self id');
158
- assert.equal(parameter.correlationId, 'correlation id');
159
- assert.equal(parameter.deviceUrl, 'some device url');
160
- assert.deepEqual(parameter.localMedias, [
161
- {localSdp: '{"audioMuted":true,"videoMuted":false}', mediaId: '12345'},
162
- ]);
163
- assert.equal(parameter.preferTranscoding, false);
164
- });
165
-
166
- it('#Should call meetingRequest.remoteAudioVideoToggle with preferTranscoding:true for non multistream connections', async () => {
167
- const meeting = {
168
- isMultistream: false,
169
139
  mediaId: '12345',
170
- meetingRequest: {
171
- remoteAudioVideoToggle: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
140
+ selfUrl: 'self url',
141
+ locusMediaRequest: {
142
+ send: sinon.stub().resolves({body: {}, headers: {}}),
172
143
  },
173
144
  };
174
145
 
175
- await MeetingUtil.remoteUpdateAudioVideo(true, false, meeting);
146
+ await MeetingUtil.remoteUpdateAudioVideo(meeting, true, false);
176
147
 
177
- assert.calledOnce(meeting.meetingRequest.remoteAudioVideoToggle);
178
- const parameter = meeting.meetingRequest.remoteAudioVideoToggle.getCall(0).args[0];
148
+ assert.calledOnce(meeting.locusMediaRequest.send);
149
+ const parameter = meeting.locusMediaRequest.send.getCall(0).args[0];
179
150
 
180
- assert.equal(parameter.preferTranscoding, true);
151
+ assert.equal(parameter.type, 'LocalMute');
152
+ assert.equal(parameter.selfUrl, 'self url');
153
+ assert.equal(parameter.mediaId, '12345');
154
+ assert.deepEqual(parameter.muteOptions, {audioMuted: true, videoMuted :false});
181
155
  });
182
156
  });
183
157
 
@@ -54,6 +54,7 @@ describe('Roap', () => {
54
54
  },
55
55
  setRoapSeq: sinon.stub(),
56
56
  config: {experimental: {enableTurnDiscovery: false}},
57
+ locusMediaRequest: {fake: true},
57
58
  webex: { meetings: { reachability: { isAnyClusterReachable: () => true}}},
58
59
  };
59
60
 
@@ -99,48 +100,12 @@ describe('Roap', () => {
99
100
  assert.calledOnce(sendRoapStub);
100
101
  assert.calledWith(sendRoapStub, {
101
102
  roapMessage: expectedRoapMessage,
102
- correlationId: meeting.correlationId,
103
103
  locusSelfUrl: meeting.selfUrl,
104
104
  mediaId: expectEmptyMediaId ? '' : meeting.mediaId,
105
- audioMuted: meeting.audio?.isLocallyMuted(),
106
- videoMuted: meeting.video?.isLocallyMuted(),
107
105
  meetingId: meeting.id,
108
- preferTranscoding: true,
106
+ locusMediaRequest: meeting.locusMediaRequest,
109
107
  });
110
108
  })
111
109
  );
112
- it('sends roap request with preferTranscoding=false for multistream meetings', async () => {
113
- const roap = new Roap({}, {parent: 'fake'});
114
-
115
- meeting.isMultistream = true;
116
-
117
- await roap.sendRoapMediaRequest({
118
- meeting,
119
- sdp: 'sdp',
120
- reconnect: false,
121
- seq: 10,
122
- tieBreaker: 1,
123
- });
124
-
125
- const expectedRoapMessage = {
126
- messageType: 'OFFER',
127
- sdps: ['sdp'],
128
- version: '2',
129
- seq: 10,
130
- tieBreaker: 1,
131
- };
132
-
133
- assert.calledOnce(sendRoapStub);
134
- assert.calledWith(sendRoapStub, {
135
- roapMessage: expectedRoapMessage,
136
- correlationId: meeting.correlationId,
137
- locusSelfUrl: meeting.selfUrl,
138
- mediaId: meeting.mediaId,
139
- audioMuted: meeting.audio.isLocallyMuted(),
140
- videoMuted: meeting.video.isLocallyMuted(),
141
- meetingId: meeting.id,
142
- preferTranscoding: false,
143
- });
144
- });
145
110
  });
146
111
  });
@@ -108,36 +108,39 @@ describe('plugin-meetings/roap', () => {
108
108
 
109
109
  describe('sendRoap', () => {
110
110
  it('includes joinCookie in the request correctly', async () => {
111
+ const locusMediaRequest = { send: sinon.stub().resolves({body: {locus: {}}})};
112
+
111
113
  await roapRequest.sendRoap({
112
114
  locusSelfUrl: locusUrl,
113
115
  mediaId: 'mediaId',
114
116
  roapMessage: {
115
117
  seq: 'seq',
116
118
  },
119
+ locusMediaRequest,
117
120
  });
118
121
 
119
- const requestParams = roapRequest.request.getCall(0).args[0];
120
- assert.equal(requestParams.method, 'PUT');
121
- assert.equal(requestParams.uri, `${locusUrl}/media`);
122
- assert.deepEqual(requestParams.body.localMedias, [
123
- {
124
- localSdp:
125
- '{"roapMessage":{"seq":"seq"},"audioMuted":false,"videoMuted":false,"reachability":{"clusterId":{"udp":"test"}}}',
126
- mediaId: 'mediaId',
127
- },
128
- ]);
129
- assert.deepEqual(requestParams.body.clientMediaPreferences, {
122
+ const requestParams = locusMediaRequest.send.getCall(0).args[0];
123
+ assert.deepEqual(requestParams, {
124
+ type: 'RoapMessage',
125
+ selfUrl: locusUrl,
130
126
  joinCookie: {
131
127
  anycastEntryPoint: 'aws-eu-west-1',
132
128
  },
133
- preferTranscoding: true,
129
+ mediaId: 'mediaId',
130
+ roapMessage: {
131
+ seq: 'seq',
132
+ },
133
+ reachability: {clusterId:{udp:"test"}},
134
134
  });
135
135
  });
136
136
  });
137
137
 
138
138
  it('calls attachReachabilityData when sendRoap', async () => {
139
+ const locusMediaRequest = { send: sinon.stub().resolves({body: {locus: {}}})};
140
+
139
141
  const newSdp = {
140
142
  new: 'sdp',
143
+ reachability: { someResult: 'whatever' }
141
144
  };
142
145
 
143
146
  roapRequest.attachReachabilityData = sinon.stub().returns(
@@ -148,70 +151,37 @@ describe('plugin-meetings/roap', () => {
148
151
  },
149
152
  })
150
153
  );
151
- webex.request.returns(
152
- Promise.resolve({
153
- body: {
154
- locus: {},
155
- },
156
- })
157
- );
158
154
 
159
- const result = await roapRequest.sendRoap({
155
+ await roapRequest.sendRoap({
160
156
  roapMessage: {
161
157
  seq: 1,
162
158
  },
163
159
  locusSelfUrl: 'locusSelfUrl',
164
160
  mediaId: 'mediaId',
165
- correlationId: 'correlationId',
166
- audioMuted: true,
167
- videoMuted: true,
168
161
  meetingId: 'meetingId',
169
162
  preferTranscoding: true,
163
+ locusMediaRequest
170
164
  });
171
165
 
172
- const requestParams = roapRequest.request.getCall(0).args[0];
166
+ const requestParams = locusMediaRequest.send.getCall(0).args[0];
173
167
 
174
168
  assert.deepEqual(requestParams, {
175
- uri: 'locusSelfUrl/media',
176
- method: 'PUT',
177
- body: {
178
- device: {
179
- url: 'url',
180
- deviceType: undefined,
181
- },
182
- correlationId: 'correlationId',
183
- localMedias: [
184
- {
185
- localSdp: JSON.stringify(newSdp),
186
- mediaId: 'mediaId',
187
- },
188
- ],
189
- clientMediaPreferences: {
190
- joinCookie: {
191
- anycastEntryPoint: 'aws-eu-west-1',
192
- },
193
- preferTranscoding: true,
194
- },
169
+ type: 'RoapMessage',
170
+ selfUrl: 'locusSelfUrl',
171
+ joinCookie: {
172
+ anycastEntryPoint: 'aws-eu-west-1',
173
+ },
174
+ mediaId: 'mediaId',
175
+ roapMessage: {
176
+ seq: 1,
195
177
  },
178
+ reachability: { someResult: 'whatever' },
196
179
  });
197
180
 
198
181
  assert.calledOnceWithExactly(roapRequest.attachReachabilityData, {
199
182
  roapMessage: {
200
183
  seq: 1,
201
184
  },
202
- audioMuted: true,
203
- videoMuted: true,
204
- });
205
-
206
- assert.deepEqual(result, {
207
- locus: {
208
- fullState: {
209
- lastActive: 'lastActive',
210
- },
211
- id: '',
212
- roapSeq: 1,
213
- url: 'url/path',
214
- }
215
185
  });
216
186
  });
217
187
  });
@@ -51,7 +51,8 @@ describe('TurnDiscovery', () => {
51
51
  }),
52
52
  updateMediaConnections: sinon.stub(),
53
53
  webex: {meetings: {reachability: {isAnyClusterReachable: () => Promise.resolve(false)}}},
54
- isMultistream: false
54
+ isMultistream: false,
55
+ locusMediaRequest: { fake: true },
55
56
  };
56
57
  });
57
58
 
@@ -74,13 +75,10 @@ describe('TurnDiscovery', () => {
74
75
  version: '2',
75
76
  seq: expectedSeq,
76
77
  },
77
- correlationId: testMeeting.correlationId,
78
78
  locusSelfUrl: testMeeting.selfUrl,
79
79
  mediaId: expectedMediaId,
80
- audioMuted: testMeeting.audio?.isLocallyMuted(),
81
- videoMuted: testMeeting.video?.isLocallyMuted(),
82
80
  meetingId: testMeeting.id,
83
- preferTranscoding: !testMeeting.isMultistream
81
+ locusMediaRequest: testMeeting.locusMediaRequest
84
82
  });
85
83
 
86
84
  if (messageType === 'TURN_DISCOVERY_REQUEST') {