@webex/plugin-meetings 3.0.0-beta.65 → 3.0.0-beta.67

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 (52) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +11 -1
  3. package/dist/breakouts/index.js.map +1 -1
  4. package/dist/constants.js +7 -2
  5. package/dist/constants.js.map +1 -1
  6. package/dist/locus-info/controlsUtils.js +15 -0
  7. package/dist/locus-info/controlsUtils.js.map +1 -1
  8. package/dist/locus-info/index.js +9 -6
  9. package/dist/locus-info/index.js.map +1 -1
  10. package/dist/meeting/index.js +1 -0
  11. package/dist/meeting/index.js.map +1 -1
  12. package/dist/meetings/collection.js +22 -0
  13. package/dist/meetings/collection.js.map +1 -1
  14. package/dist/meetings/index.js +91 -11
  15. package/dist/meetings/index.js.map +1 -1
  16. package/dist/meetings/util.js +32 -0
  17. package/dist/meetings/util.js.map +1 -1
  18. package/dist/members/collection.js +10 -0
  19. package/dist/members/collection.js.map +1 -1
  20. package/dist/members/index.js +21 -1
  21. package/dist/members/index.js.map +1 -1
  22. package/dist/multistream/mediaRequestManager.js +48 -6
  23. package/dist/multistream/mediaRequestManager.js.map +1 -1
  24. package/dist/types/constants.d.ts +3 -0
  25. package/dist/types/locus-info/index.d.ts +3 -3
  26. package/dist/types/meeting/index.d.ts +1 -0
  27. package/dist/types/meetings/collection.d.ts +8 -0
  28. package/dist/types/meetings/index.d.ts +18 -0
  29. package/dist/types/members/collection.d.ts +5 -0
  30. package/dist/types/members/index.d.ts +8 -0
  31. package/dist/types/multistream/mediaRequestManager.d.ts +17 -0
  32. package/package.json +18 -18
  33. package/src/breakouts/index.ts +13 -0
  34. package/src/constants.ts +3 -0
  35. package/src/locus-info/controlsUtils.ts +19 -0
  36. package/src/locus-info/index.ts +8 -5
  37. package/src/meeting/index.ts +1 -0
  38. package/src/meetings/collection.ts +20 -0
  39. package/src/meetings/index.ts +110 -2
  40. package/src/meetings/util.ts +38 -0
  41. package/src/members/collection.ts +8 -0
  42. package/src/members/index.ts +24 -1
  43. package/src/multistream/mediaRequestManager.ts +45 -3
  44. package/test/unit/spec/breakouts/breakout.ts +3 -2
  45. package/test/unit/spec/breakouts/index.ts +10 -0
  46. package/test/unit/spec/locus-info/controlsUtils.js +21 -0
  47. package/test/unit/spec/locus-info/index.js +63 -0
  48. package/test/unit/spec/meetings/collection.js +14 -0
  49. package/test/unit/spec/meetings/index.js +183 -6
  50. package/test/unit/spec/meetings/utils.js +46 -0
  51. package/test/unit/spec/members/index.js +38 -0
  52. package/test/unit/spec/multistream/mediaRequestManager.ts +55 -8
@@ -504,6 +504,7 @@ describe('plugin-meetings', () => {
504
504
  selfIdentity: '123',
505
505
  selfId: '2',
506
506
  hostId: '3',
507
+ isReplace: undefined,
507
508
  }
508
509
  );
509
510
  // note: in a real use case, recordingId, selfId, and hostId would all be the same
@@ -511,6 +512,43 @@ describe('plugin-meetings', () => {
511
512
  // are being correctly grabbed from locusInfo.parsedLocus within updateParticipants
512
513
  });
513
514
 
515
+ it('should call with breakout control info', () => {
516
+ locusInfo.parsedLocus = {
517
+ controls: {
518
+ record: {
519
+ modifiedBy: '1',
520
+ },
521
+ },
522
+ self: {
523
+ selfIdentity: '123',
524
+ selfId: '2',
525
+ },
526
+ host: {
527
+ hostId: '3',
528
+ },
529
+ };
530
+
531
+ locusInfo.emitScoped = sinon.stub();
532
+ locusInfo.updateParticipants({}, true);
533
+
534
+ assert.calledWith(
535
+ locusInfo.emitScoped,
536
+ {
537
+ file: 'locus-info',
538
+ function: 'updateParticipants',
539
+ },
540
+ EVENTS.LOCUS_INFO_UPDATE_PARTICIPANTS,
541
+ {
542
+ participants: {},
543
+ recordingId: '1',
544
+ selfIdentity: '123',
545
+ selfId: '2',
546
+ hostId: '3',
547
+ isReplace: true,
548
+ }
549
+ );
550
+ });
551
+
514
552
  it('should update the deltaParticipants object', () => {
515
553
  const prev = locusInfo.deltaParticipants;
516
554
 
@@ -1444,6 +1482,31 @@ describe('plugin-meetings', () => {
1444
1482
  assert.calledOnce(locusInfo.locusParser.resume);
1445
1483
  });
1446
1484
  });
1485
+
1486
+ it('onDeltaLocus handle delta data', () => {
1487
+ fakeLocus.participants = {};
1488
+ const fakeBreakout = {
1489
+ sessionId: 'sessionId',
1490
+ groupId: 'groupId',
1491
+ };
1492
+
1493
+ fakeLocus.controls = {
1494
+ breakout: fakeBreakout
1495
+ };
1496
+ locusInfo.controls = {
1497
+ breakout: {
1498
+ sessionId: 'sessionId',
1499
+ groupId: 'groupId',
1500
+ }
1501
+ }
1502
+ locusInfo.updateParticipants = sinon.stub();
1503
+ locusInfo.onDeltaLocus(fakeLocus);
1504
+ assert.calledWith(locusInfo.updateParticipants, {}, false);
1505
+
1506
+ fakeBreakout.sessionId = 'sessionId2';
1507
+ locusInfo.onDeltaLocus(fakeLocus);
1508
+ assert.calledWith(locusInfo.updateParticipants, {}, false);
1509
+ });
1447
1510
  });
1448
1511
 
1449
1512
  describe('#handleOneonOneEvent', () => {
@@ -48,5 +48,19 @@ describe('plugin-meetings', () => {
48
48
  assert.deepEqual(meetingCollection.getByKey('value', 'test'), {value: 'test', id: uuid1});
49
49
  });
50
50
  });
51
+
52
+ describe('#getActiveBreakoutLocus', () => {
53
+ beforeEach(() => {
54
+ meetingCollection.meetings.test = {breakouts: {url: 'url', isActiveBreakout: true}, id: uuid1};
55
+ });
56
+ it('return null if empty breakoutUrl', () => {
57
+ assert.deepEqual(meetingCollection.getActiveBreakoutLocus(), null);
58
+ });
59
+
60
+ it('should get the meeting which joined breakout by breakoutUrl', () => {
61
+ assert.deepEqual(meetingCollection.getActiveBreakoutLocus('url'), {
62
+ breakouts: {url: 'url', isActiveBreakout: true}, id: uuid1});
63
+ });
64
+ });
51
65
  });
52
66
  });
@@ -11,6 +11,7 @@ import sinon from 'sinon';
11
11
  import uuid from 'uuid';
12
12
  import StaticConfig from '@webex/plugin-meetings/src/common/config';
13
13
  import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
14
+ import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
14
15
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
15
16
  import Meeting from '@webex/plugin-meetings/src/meeting';
16
17
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
@@ -478,7 +479,7 @@ describe('plugin-meetings', () => {
478
479
  it('tests the sync meeting calls for not existing meeting', async () => {
479
480
  await webex.meetings.syncMeetings();
480
481
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
481
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
482
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
482
483
  assert.calledOnce(initialSetup);
483
484
  assert.calledOnce(webex.meetings.create);
484
485
  assert.calledWith(webex.meetings.request.getActiveMeetings);
@@ -709,6 +710,7 @@ describe('plugin-meetings', () => {
709
710
  });
710
711
  describe('there was not a meeting', () => {
711
712
  let initialSetup;
713
+ const webExMeetingId = '123456';
712
714
 
713
715
  beforeEach(() => {
714
716
  initialSetup = sinon.stub().returns(true);
@@ -735,12 +737,16 @@ describe('plugin-meetings', () => {
735
737
  callbackAddress: uri1,
736
738
  },
737
739
  },
740
+ info: {
741
+ webExMeetingId
742
+ },
738
743
  },
739
744
  eventType: 'locus.difference',
740
745
  locusUrl: url1,
741
746
  });
742
- assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
747
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
743
748
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
749
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
744
750
  assert.calledOnce(initialSetup);
745
751
  assert.calledWith(initialSetup, {
746
752
  id: uuid1,
@@ -754,6 +760,9 @@ describe('plugin-meetings', () => {
754
760
  callbackAddress: uri1,
755
761
  },
756
762
  },
763
+ info: {
764
+ webExMeetingId
765
+ },
757
766
  });
758
767
  });
759
768
  it('should setup the meeting by difference event without replaces', async () => {
@@ -765,12 +774,16 @@ describe('plugin-meetings', () => {
765
774
  callbackAddress: uri1,
766
775
  },
767
776
  },
777
+ info: {
778
+ webExMeetingId
779
+ },
768
780
  },
769
781
  eventType: 'locus.difference',
770
782
  locusUrl: url1,
771
783
  });
772
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
784
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
773
785
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
786
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
774
787
  assert.calledOnce(initialSetup);
775
788
  assert.calledWith(initialSetup, {
776
789
  id: uuid1,
@@ -779,6 +792,9 @@ describe('plugin-meetings', () => {
779
792
  callbackAddress: uri1,
780
793
  },
781
794
  },
795
+ info: {
796
+ webExMeetingId
797
+ },
782
798
  });
783
799
  });
784
800
  it('should setup the meeting by a not difference event', async () => {
@@ -790,12 +806,16 @@ describe('plugin-meetings', () => {
790
806
  callbackAddress: uri1,
791
807
  },
792
808
  },
809
+ info: {
810
+ webExMeetingId
811
+ },
793
812
  },
794
813
  eventType: test1,
795
814
  locusUrl: url1,
796
815
  });
797
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
816
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
798
817
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
818
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
799
819
  assert.calledOnce(initialSetup);
800
820
  assert.calledWith(initialSetup, {
801
821
  id: uuid1,
@@ -804,6 +824,9 @@ describe('plugin-meetings', () => {
804
824
  callbackAddress: uri1,
805
825
  },
806
826
  },
827
+ info: {
828
+ webExMeetingId
829
+ },
807
830
  });
808
831
  });
809
832
 
@@ -826,7 +849,7 @@ describe('plugin-meetings', () => {
826
849
 
827
850
  it('should not try to match USM meetings by conversation url', async () => {
828
851
  await webex.meetings.handleLocusEvent(generateFakeLocusData(true));
829
- assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
852
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
830
853
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
831
854
  'locusUrl',
832
855
  url1,
@@ -843,7 +866,7 @@ describe('plugin-meetings', () => {
843
866
  });
844
867
  it('should try to match non-USM meetings by conversation url', async () => {
845
868
  await webex.meetings.handleLocusEvent(generateFakeLocusData(false));
846
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
869
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
847
870
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
848
871
  'locusUrl',
849
872
  url1,
@@ -1368,5 +1391,159 @@ describe('plugin-meetings', () => {
1368
1391
  );
1369
1392
  });
1370
1393
  });
1394
+
1395
+ describe('#isNeedHandleMainLocus', () => {
1396
+ let meeting;
1397
+ let newLocus;
1398
+ beforeEach(() => {
1399
+ meeting = {
1400
+ controls: {},
1401
+ self: {},
1402
+ };
1403
+ newLocus = {
1404
+ controls: {},
1405
+ self: {},
1406
+ }
1407
+ });
1408
+ afterEach(() => {
1409
+ sinon.restore();
1410
+ });
1411
+ it('check normal case will return true', () => {
1412
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1413
+ LoggerProxy.logger.log = sinon.stub();
1414
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1415
+ assert.equal(result, true);
1416
+ assert.calledWith(
1417
+ LoggerProxy.logger.log,
1418
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1419
+ );
1420
+ });
1421
+
1422
+ it('check self joined and joined on this device, return true', () => {
1423
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1424
+ newLocus.self.state = 'JOINED';
1425
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1426
+
1427
+ LoggerProxy.logger.log = sinon.stub();
1428
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1429
+ assert.equal(result, true);
1430
+ assert.calledWith(
1431
+ LoggerProxy.logger.log,
1432
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
1433
+ );
1434
+ });
1435
+
1436
+ it('if newLocus replaceAt time is expired, then return false', () => {
1437
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({joinedWith: {replaces: [{
1438
+ replaceAt: '2023-03-27T02:17:02.506Z',
1439
+ }]}});
1440
+ newLocus.self.state = 'JOINED';
1441
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1442
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1443
+ replaces: [{
1444
+ replaceAt: '2023-03-27T02:17:01.506Z'
1445
+ }]
1446
+ })
1447
+
1448
+ LoggerProxy.logger.log = sinon.stub();
1449
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1450
+ assert.equal(result, false);
1451
+ assert.calledWith(
1452
+ LoggerProxy.logger.log,
1453
+ `Meetings:index#isNeedHandleMainLocus --> this is expired main joined status locus_dto replacedAt 2023-03-27T02:17:01.506Z bo replacedAt 2023-03-27T02:17:02.506Z`
1454
+ );
1455
+ });
1456
+
1457
+ it('check current is in breakout join with this device, return false', () => {
1458
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1459
+ joinedWith: {
1460
+ correlationId: '111',
1461
+ },
1462
+ });
1463
+ newLocus.controls.breakout = {url: 'url'};
1464
+ meeting.correlationId = '111';
1465
+
1466
+ LoggerProxy.logger.log = sinon.stub();
1467
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1468
+ assert.equal(result, false);
1469
+ assert.calledWith(
1470
+ LoggerProxy.logger.log,
1471
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: url`
1472
+ );
1473
+ });
1474
+
1475
+ it('check self is moved and removed, return false', () => {
1476
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1477
+ newLocus.self.state = 'LEFT';
1478
+ newLocus.self.reason = 'MOVED';
1479
+ newLocus.self.removed = true;
1480
+ LoggerProxy.logger.log = sinon.stub();
1481
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1482
+ assert.equal(result, false);
1483
+ assert.calledWith(
1484
+ LoggerProxy.logger.log,
1485
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status, not need to handle'
1486
+ );
1487
+ });
1488
+ });
1489
+
1490
+ describe('#isNeedHandleLocusDTO', () => {
1491
+ let meeting;
1492
+ let newLocus;
1493
+ beforeEach(() => {
1494
+ meeting = {
1495
+ controls: {},
1496
+ self: {},
1497
+ };
1498
+ newLocus = {
1499
+ controls: {},
1500
+ self: {},
1501
+ }
1502
+ });
1503
+ afterEach(() => {
1504
+ sinon.restore();
1505
+ });
1506
+ it('initial DTO , joined breakout session, return true', () => {
1507
+ newLocus.controls.breakout = {
1508
+ sessionType: 'BREAKOUT',
1509
+ };
1510
+ newLocus.self.state = 'JOINED';
1511
+ newLocus.fullState = {
1512
+ active: true,
1513
+ };
1514
+ LoggerProxy.logger.log = sinon.stub();
1515
+ const result = webex.meetings.isNeedHandleLocusDTO(null, newLocus);
1516
+ assert.equal(result, true);
1517
+ assert.calledWith(
1518
+ LoggerProxy.logger.log,
1519
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: true`
1520
+ );
1521
+ });
1522
+ it('others go to check isNeedHandleMainLocus', () => {
1523
+ newLocus.controls.breakout = {
1524
+ sessionType: 'MAIN',
1525
+ };
1526
+ newLocus.self.state = 'JOINED';
1527
+
1528
+ LoggerProxy.logger.log = sinon.stub();
1529
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1530
+ assert.equal(result, true);
1531
+ assert.calledWith(
1532
+ LoggerProxy.logger.log,
1533
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1534
+ );
1535
+ });
1536
+ it('joined breakout session, self status is moved, return false', () => {
1537
+ newLocus.controls.breakout = {
1538
+ sessionType: 'BREAKOUT',
1539
+ };
1540
+ newLocus.self.state = 'LEFT';
1541
+ newLocus.self.reason = 'MOVED';
1542
+
1543
+ LoggerProxy.logger.log = sinon.stub();
1544
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1545
+ assert.equal(result, false);
1546
+ });
1547
+ });
1371
1548
  });
1372
1549
  });
@@ -62,5 +62,51 @@ describe('plugin-meetings', () => {
62
62
  assert.equal(MeetingsUtil.parseDefaultSiteFromMeetingPreferences(userPreferences), '');
63
63
  });
64
64
  });
65
+
66
+ describe('#getThisDevice', () => {
67
+ it('return null if no devices in self', () => {
68
+ const newLocus = {};
69
+ assert.equal(MeetingsUtil.getThisDevice(newLocus), null);
70
+ });
71
+ it('return first device as this device', () => {
72
+ const newLocus = {
73
+ self: {
74
+ devices: [{state: 'JOINED'}]
75
+ }
76
+ };
77
+ assert.deepEqual(MeetingsUtil.getThisDevice(newLocus), {state: 'JOINED'});
78
+ })
79
+ });
80
+
81
+ describe('#joinedOnThisDevice', () => {
82
+ it('return false if no devices in self', () => {
83
+ const newLocus = {};
84
+ assert.equal(MeetingsUtil.joinedOnThisDevice(null, newLocus), false);
85
+ });
86
+ it('return true if joined on this device', () => {
87
+ const newLocus = {
88
+ self: {
89
+ devices: [{state: 'JOINED', correlationId: '111'}]
90
+ }
91
+ };
92
+ const meeting = {
93
+ correlationId: '111'
94
+ };
95
+
96
+ assert.equal(MeetingsUtil.joinedOnThisDevice(meeting, newLocus), true);
97
+ });
98
+ it('return true if selfMoved on this device', () => {
99
+ const newLocus = {
100
+ self: {
101
+ devices: [{state: 'LEFT', reason: 'MOVED', correlationId: '111'}]
102
+ }
103
+ };
104
+ const meeting = {
105
+ correlationId: '111'
106
+ };
107
+
108
+ assert.equal(MeetingsUtil.joinedOnThisDevice(meeting, newLocus), true);
109
+ });
110
+ });
65
111
  });
66
112
  });
@@ -14,6 +14,8 @@ import ParameterError from '@webex/plugin-meetings/src/common/errors/parameter';
14
14
  import Meetings from '@webex/plugin-meetings';
15
15
  import Members from '@webex/plugin-meetings/src/members';
16
16
  import MembersUtil from '@webex/plugin-meetings/src/members/util';
17
+ import Trigger from '@webex/plugin-meetings/src/common/events/trigger-proxy';
18
+ import {EVENT_TRIGGERS} from "@webex/plugin-meetings/src/constants";
17
19
 
18
20
  const {assert} = chai;
19
21
 
@@ -205,6 +207,42 @@ describe('plugin-meetings', () => {
205
207
  });
206
208
  });
207
209
 
210
+ describe('#clearMembers', () => {
211
+ it('should send clear event if clear members', () => {
212
+ const members = createMembers({url: url1});
213
+ members.membersCollection.setAll(fakeMembersCollection);
214
+ Trigger.trigger = sinon.stub();
215
+ members.clearMembers();
216
+ assert.deepEqual(members.membersCollection.members, {});
217
+ assert.calledWith(Trigger.trigger, members, {
218
+ file: 'members',
219
+ function: 'clearMembers',
220
+ }, EVENT_TRIGGERS.MEMBERS_CLEAR, {})
221
+ });
222
+ });
223
+ describe('#locusParticipantsUpdate', () => {
224
+ it('should send member update event with session info', () => {
225
+ const members = createMembers({url: url1});
226
+ Trigger.trigger = sinon.stub();
227
+ const fakePayload = {
228
+ participants: {
229
+ forEach: sinon.stub(),
230
+ },
231
+ isReplace: true,
232
+ };
233
+
234
+ members.locusParticipantsUpdate(fakePayload);
235
+
236
+ assert.calledWith(Trigger.trigger, members, {
237
+ file: 'members',
238
+ function: 'locusParticipantsUpdate',
239
+ }, EVENT_TRIGGERS.MEMBERS_UPDATE, {
240
+ delta: {added: [], updated: []},
241
+ full: {},
242
+ isReplace: true,
243
+ })
244
+ });
245
+ });
208
246
  describe('#sendDialPadKey', () => {
209
247
  it('should throw a rejection when calling sendDialPadKey with no tones', async () => {
210
248
  const members = createMembers({url: url1});
@@ -552,28 +552,28 @@ describe('MediaRequestManager', () => {
552
552
  ]);
553
553
  });
554
554
 
555
- it('clears all the requests on reset()', () => {
555
+ it('avoids sending duplicate requests and clears all the requests on reset()', () => {
556
556
  // send some requests and commit them one by one
557
- addReceiverSelectedRequest(1500, fakeReceiveSlots[0], RECEIVER_SELECTED_MAX_FS, true);
558
- addReceiverSelectedRequest(1501, fakeReceiveSlots[1], RECEIVER_SELECTED_MAX_FS, true);
557
+ addReceiverSelectedRequest(1500, fakeReceiveSlots[0], RECEIVER_SELECTED_MAX_FS, false);
558
+ addReceiverSelectedRequest(1501, fakeReceiveSlots[1], RECEIVER_SELECTED_MAX_FS, false);
559
559
  addActiveSpeakerRequest(
560
560
  255,
561
561
  [fakeReceiveSlots[2], fakeReceiveSlots[3], fakeReceiveSlots[4]],
562
562
  ACTIVE_SPEAKER_MAX_FS,
563
- true
563
+ false
564
564
  );
565
565
  addActiveSpeakerRequest(
566
566
  254,
567
567
  [fakeReceiveSlots[5], fakeReceiveSlots[6], fakeReceiveSlots[7]],
568
568
  ACTIVE_SPEAKER_MAX_FS,
569
- true
569
+ false
570
570
  );
571
571
 
572
- sendMediaRequestsCallback.resetHistory();
572
+ // nothing should be sent out as we didn't commit the requests
573
+ assert.notCalled(sendMediaRequestsCallback);
573
574
 
574
- // check that when calling commit() all requests are re-sent again
575
- mediaRequestManager.commit();
576
575
 
576
+ mediaRequestManager.commit();
577
577
  checkMediaRequestsSent([
578
578
  {
579
579
  policy: 'receiver-selected',
@@ -601,6 +601,13 @@ describe('MediaRequestManager', () => {
601
601
  },
602
602
  ]);
603
603
 
604
+
605
+ // check that when calling commit()
606
+ // all requests are not re-sent again (avoid duplicate requests)
607
+ mediaRequestManager.commit();
608
+
609
+ assert.notCalled(sendMediaRequestsCallback);
610
+
604
611
  // now reset everything
605
612
  mediaRequestManager.reset();
606
613
 
@@ -609,6 +616,46 @@ describe('MediaRequestManager', () => {
609
616
  checkMediaRequestsSent([]);
610
617
  });
611
618
 
619
+ it('makes sure to call requests correctly after reset was called and another request was added', () => {
620
+ addReceiverSelectedRequest(1500, fakeReceiveSlots[0], RECEIVER_SELECTED_MAX_FS, false);
621
+
622
+ assert.notCalled(sendMediaRequestsCallback);
623
+
624
+
625
+ mediaRequestManager.commit();
626
+ checkMediaRequestsSent([
627
+ {
628
+ policy: 'receiver-selected',
629
+ csi: 1500,
630
+ receiveSlot: fakeWcmeSlots[0],
631
+ maxFs: RECEIVER_SELECTED_MAX_FS,
632
+ },
633
+ ]);
634
+
635
+ // now reset everything
636
+ mediaRequestManager.reset();
637
+
638
+ // calling commit now should not cause any requests to be sent out
639
+ mediaRequestManager.commit();
640
+ checkMediaRequestsSent([]);
641
+
642
+ //add new request
643
+ addReceiverSelectedRequest(1501, fakeReceiveSlots[1], RECEIVER_SELECTED_MAX_FS, false);
644
+
645
+ // commit
646
+ mediaRequestManager.commit();
647
+
648
+ // check the new request was sent
649
+ checkMediaRequestsSent([
650
+ {
651
+ policy: 'receiver-selected',
652
+ csi: 1501,
653
+ receiveSlot: fakeWcmeSlots[1],
654
+ maxFs: RECEIVER_SELECTED_MAX_FS,
655
+ },
656
+ ])
657
+ })
658
+
612
659
  it('re-sends media requests after degradation preferences are set', () => {
613
660
  // set max macroblocks limit
614
661
  mediaRequestManager.setDegradationPreferences({maxMacroblocksLimit: 32400});