@webex/plugin-meetings 3.11.0-next.21 → 3.11.0-next.23

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.
@@ -329,6 +329,16 @@ describe('plugin-meetings', () => {
329
329
  htMeta: {elementId: {type: 'mediashare', id: 'fake-ht-mediaShare-2', version: 1}},
330
330
  },
331
331
  ];
332
+ locusInfo.embeddedApps = [
333
+ {
334
+ id: 'fake-embedded-app-1',
335
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-1', version: 1}},
336
+ },
337
+ {
338
+ id: 'fake-embedded-app-2',
339
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-2', version: 1}},
340
+ },
341
+ ];
332
342
  locusInfo.meetings = {id: 'fake-meetings'};
333
343
  locusInfo.participants = [
334
344
  {id: 'fake-participant-1', name: 'Participant One'},
@@ -364,6 +374,16 @@ describe('plugin-meetings', () => {
364
374
  htMeta: {elementId: {type: 'mediashare', id: 'fake-ht-mediaShare-2', version: 1}},
365
375
  },
366
376
  ],
377
+ embeddedApps: [
378
+ {
379
+ id: 'fake-embedded-app-1',
380
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-1', version: 1}},
381
+ },
382
+ {
383
+ id: 'fake-embedded-app-2',
384
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-2', version: 1}},
385
+ },
386
+ ],
367
387
  meetings: {id: 'fake-meetings'},
368
388
  jsSdkMeta: {removedParticipantIds: []},
369
389
  participants: [], // empty means there were no participant updates
@@ -540,6 +560,7 @@ describe('plugin-meetings', () => {
540
560
  self: {id: 'fake-self'},
541
561
  links: {id: 'fake-links'},
542
562
  mediaShares: expectedLocusInfo.mediaShares,
563
+ embeddedApps: expectedLocusInfo.embeddedApps,
543
564
  // and now the new fields
544
565
  ...newLocus,
545
566
  htMeta: newLocusHtMeta,
@@ -572,6 +593,7 @@ describe('plugin-meetings', () => {
572
593
  self: 'new-self',
573
594
  participants: 'new-participants',
574
595
  mediaShares: 'new-mediaShares',
596
+ embeddedApps: 'new-embeddedApps',
575
597
  },
576
598
  },
577
599
  ],
@@ -587,6 +609,7 @@ describe('plugin-meetings', () => {
587
609
  self: {id: 'fake-self'},
588
610
  links: {id: 'fake-links'},
589
611
  mediaShares: expectedLocusInfo.mediaShares,
612
+ embeddedApps: expectedLocusInfo.embeddedApps,
590
613
  participants: [], // empty means there were no participant updates
591
614
  jsSdkMeta: {removedParticipantIds: []}, // no participants were removed
592
615
  ...newLocus,
@@ -622,6 +645,7 @@ describe('plugin-meetings', () => {
622
645
  self: {id: 'fake-self'},
623
646
  links: {id: 'fake-links'},
624
647
  mediaShares: expectedLocusInfo.mediaShares,
648
+ embeddedApps: expectedLocusInfo.embeddedApps,
625
649
  // and now the new fields
626
650
  ...newLocus,
627
651
  htMeta: newLocusHtMeta,
@@ -761,6 +785,39 @@ describe('plugin-meetings', () => {
761
785
  });
762
786
  });
763
787
 
788
+ it('should process locus update correctly when called with updated EMBEDDEDAPP objects', () => {
789
+ const newEmbeddedApp = {
790
+ id: 'new-embedded-app-3',
791
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-3', version: 100}},
792
+ };
793
+ const updatedEmbeddedApp2 = {
794
+ id: 'fake-embedded-app-2',
795
+ someNewProp: 'newValue',
796
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-2', version: 100}},
797
+ };
798
+ // simulate an update from the HashTreeParser (normally this would be triggered by incoming locus messages)
799
+ // with 1 embedded app added, 1 updated, and 1 removed
800
+ locusInfoUpdateCallback(OBJECTS_UPDATED, {
801
+ updatedObjects: [
802
+ {htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-1'}}, data: null},
803
+ {
804
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-2'}},
805
+ data: updatedEmbeddedApp2,
806
+ },
807
+ {
808
+ htMeta: {elementId: {type: 'embeddedapp', id: 'fake-ht-embeddedApp-3'}},
809
+ data: newEmbeddedApp,
810
+ },
811
+ ],
812
+ });
813
+
814
+ // check onDeltaLocus() was called with correctly updated locus info
815
+ assert.calledOnceWithExactly(onDeltaLocusStub, {
816
+ ...expectedLocusInfo,
817
+ embeddedApps: [updatedEmbeddedApp2, newEmbeddedApp],
818
+ });
819
+ });
820
+
764
821
  it('should process locus update correctly when called with a combination of various updated objects', () => {
765
822
  const newSelf = {
766
823
  id: 'new-self',
@@ -2958,28 +3015,28 @@ describe('plugin-meetings', () => {
2958
3015
  assert.isFunction(locusParser.onDeltaAction);
2959
3016
  });
2960
3017
 
2961
- it("#updateLocusInfo invokes updateLocusUrl before updateMeetingInfo", () => {
3018
+ it('#updateLocusInfo invokes updateLocusUrl before updateMeetingInfo', () => {
2962
3019
  const callOrder = [];
2963
- sinon.stub(locusInfo, "updateControls");
2964
- sinon.stub(locusInfo, "updateConversationUrl");
2965
- sinon.stub(locusInfo, "updateCreated");
2966
- sinon.stub(locusInfo, "updateFullState");
2967
- sinon.stub(locusInfo, "updateHostInfo");
2968
- sinon.stub(locusInfo, "updateMeetingInfo").callsFake(() => {
2969
- callOrder.push("updateMeetingInfo");
3020
+ sinon.stub(locusInfo, 'updateControls');
3021
+ sinon.stub(locusInfo, 'updateConversationUrl');
3022
+ sinon.stub(locusInfo, 'updateCreated');
3023
+ sinon.stub(locusInfo, 'updateFullState');
3024
+ sinon.stub(locusInfo, 'updateHostInfo');
3025
+ sinon.stub(locusInfo, 'updateMeetingInfo').callsFake(() => {
3026
+ callOrder.push('updateMeetingInfo');
2970
3027
  });
2971
- sinon.stub(locusInfo, "updateMediaShares");
2972
- sinon.stub(locusInfo, "updateReplaces");
2973
- sinon.stub(locusInfo, "updateSelf");
2974
- sinon.stub(locusInfo, "updateLocusUrl").callsFake(() => {
2975
- callOrder.push("updateLocusUrl");
3028
+ sinon.stub(locusInfo, 'updateMediaShares');
3029
+ sinon.stub(locusInfo, 'updateReplaces');
3030
+ sinon.stub(locusInfo, 'updateSelf');
3031
+ sinon.stub(locusInfo, 'updateLocusUrl').callsFake(() => {
3032
+ callOrder.push('updateLocusUrl');
2976
3033
  });
2977
- sinon.stub(locusInfo, "updateAclUrl");
2978
- sinon.stub(locusInfo, "updateBasequence");
2979
- sinon.stub(locusInfo, "updateSequence");
2980
- sinon.stub(locusInfo, "updateEmbeddedApps");
2981
- sinon.stub(locusInfo, "updateLinks");
2982
- sinon.stub(locusInfo, "compareAndUpdate");
3034
+ sinon.stub(locusInfo, 'updateAclUrl');
3035
+ sinon.stub(locusInfo, 'updateBasequence');
3036
+ sinon.stub(locusInfo, 'updateSequence');
3037
+ sinon.stub(locusInfo, 'updateEmbeddedApps');
3038
+ sinon.stub(locusInfo, 'updateLinks');
3039
+ sinon.stub(locusInfo, 'compareAndUpdate');
2983
3040
 
2984
3041
  locusInfo.updateLocusInfo(locus);
2985
3042
 
@@ -3035,7 +3092,7 @@ describe('plugin-meetings', () => {
3035
3092
  it('#updateLocusInfo puts the Locus DTO top level properties at the right place in LocusInfo class', () => {
3036
3093
  // this test verifies that the top-level properties of Locus DTO are copied
3037
3094
  // into LocusInfo class and set as top level properties too
3038
- // this is important, because the code handling Locus hass trees relies on it, see updateFromHashTree()
3095
+ // this is important, because the code handling Locus hash trees relies on it, see updateFromHashTree()
3039
3096
  const info = {id: 'info id'};
3040
3097
  const fullState = {id: 'fullState id'};
3041
3098
  const links = {services: {id: 'service links'}, resources: {id: 'resource links'}};
@@ -3903,7 +3960,7 @@ describe('plugin-meetings', () => {
3903
3960
 
3904
3961
  describe('#updateLocusUrl', () => {
3905
3962
  it('trigger LOCUS_INFO_UPDATE_URL event with isMainLocus is true as default', () => {
3906
- const fakeUrl = "https://fake.com/locus";
3963
+ const fakeUrl = 'https://fake.com/locus';
3907
3964
  locusInfo.emitScoped = sinon.stub();
3908
3965
  locusInfo.updateLocusUrl(fakeUrl);
3909
3966
 
@@ -3916,12 +3973,12 @@ describe('plugin-meetings', () => {
3916
3973
  EVENTS.LOCUS_INFO_UPDATE_URL,
3917
3974
  {
3918
3975
  url: fakeUrl,
3919
- isMainLocus: true
3920
- },
3976
+ isMainLocus: true,
3977
+ }
3921
3978
  );
3922
3979
  });
3923
3980
  it('trigger LOCUS_INFO_UPDATE_URL event with isMainLocus is false', () => {
3924
- const fakeUrl = "https://fake.com/locus";
3981
+ const fakeUrl = 'https://fake.com/locus';
3925
3982
  locusInfo.emitScoped = sinon.stub();
3926
3983
  locusInfo.updateLocusUrl(fakeUrl, false);
3927
3984
 
@@ -3934,8 +3991,8 @@ describe('plugin-meetings', () => {
3934
3991
  EVENTS.LOCUS_INFO_UPDATE_URL,
3935
3992
  {
3936
3993
  url: fakeUrl,
3937
- isMainLocus: false
3938
- },
3994
+ isMainLocus: false,
3995
+ }
3939
3996
  );
3940
3997
  });
3941
3998
  });
@@ -3987,8 +4044,8 @@ describe('plugin-meetings', () => {
3987
4044
 
3988
4045
  sinon.stub(locusInfo, 'updateParticipants');
3989
4046
  sinon.stub(locusInfo, 'isMeetingActive');
3990
- sinon.stub(locusInfo, 'handleOneOnOneEvent');
3991
- (updateLocusInfoStub = sinon.stub(locusInfo, 'updateLocusInfo'));
4047
+ sinon.stub(locusInfo, 'handleOneOnOneEvent');
4048
+ updateLocusInfoStub = sinon.stub(locusInfo, 'updateLocusInfo');
3992
4049
  syncRequestStub = sinon.stub().resolves({body: {}});
3993
4050
 
3994
4051
  mockMeeting.locusInfo = locusInfo;
@@ -965,6 +965,36 @@ describe('RemoteMediaManager', () => {
965
965
  );
966
966
  });
967
967
 
968
+ it('allocates 25 video slots for AllEqual25 layout', async () => {
969
+ const config = cloneDeep(DefaultTestConfiguration);
970
+ config.video.layouts['AllEqual25'] = {
971
+ activeSpeakerVideoPaneGroups: [
972
+ {id: 'main', numPanes: 25, size: 'best', priority: 255},
973
+ ],
974
+ };
975
+ config.video.initialLayoutId = 'AllEqual25';
976
+
977
+ let slotCount = 0;
978
+ fakeReceiveSlotManager.allocateSlot.callsFake((mediaType: MediaType) => {
979
+ if (mediaType === MediaType.VideoMain) {
980
+ slotCount += 1;
981
+ return Promise.resolve(new FakeSlot(mediaType, `fake video ${slotCount}`));
982
+ }
983
+ return Promise.resolve(fakeAudioSlot);
984
+ });
985
+
986
+ remoteMediaManager = new RemoteMediaManager(
987
+ fakeReceiveSlotManager,
988
+ fakeMediaRequestManagers,
989
+ config
990
+ );
991
+
992
+ await remoteMediaManager.start();
993
+
994
+ assert.strictEqual(remoteMediaManager.getLayoutId(), 'AllEqual25');
995
+ assert.strictEqual(remoteMediaManager.slots.video.activeSpeaker.length, 25);
996
+ });
997
+
968
998
  it('releases slots when switching to layout that requires less active speaker slots', async () => {
969
999
  // start with "AllEqual" layout that needs just 9 video slots
970
1000
  const config = cloneDeep(DefaultTestConfiguration);