@webex/plugin-meetings 3.8.1 → 3.9.0-webinar5k.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -13
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +16 -3
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +1 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +26 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/hashTree/constants.js +23 -0
- package/dist/hashTree/constants.js.map +1 -0
- package/dist/hashTree/hashTree.js +516 -0
- package/dist/hashTree/hashTree.js.map +1 -0
- package/dist/hashTree/hashTreeParser.js +521 -0
- package/dist/hashTree/hashTreeParser.js.map +1 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +11 -3
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +331 -59
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/index.js +2 -2
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/brbState.js +17 -14
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +264 -125
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +2 -5
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +19 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +8 -11
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +6 -2
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/members/collection.js +13 -0
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +44 -23
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -3
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +18 -6
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +1 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +32 -2
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/index.js +5 -10
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/constants.d.ts +12 -0
- package/dist/types/controls-options-manager/enums.d.ts +2 -1
- package/dist/types/controls-options-manager/types.d.ts +4 -1
- package/dist/types/hashTree/constants.d.ts +8 -0
- package/dist/types/hashTree/hashTree.d.ts +128 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +152 -0
- package/dist/types/locus-info/index.d.ts +93 -3
- package/dist/types/meeting/brbState.d.ts +0 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
- package/dist/types/meeting/index.d.ts +36 -3
- package/dist/types/meeting/request.d.ts +9 -1
- package/dist/types/meeting/request.type.d.ts +74 -0
- package/dist/types/meeting/util.d.ts +3 -3
- package/dist/types/member/types.d.ts +1 -0
- package/dist/types/members/collection.d.ts +6 -0
- package/dist/types/members/index.d.ts +15 -3
- package/dist/types/members/request.d.ts +1 -1
- package/dist/types/members/util.d.ts +5 -2
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/sendSlotManager.d.ts +16 -0
- package/dist/types/reachability/index.d.ts +2 -2
- package/dist/webinar/index.js +1 -1
- package/package.json +26 -25
- package/src/constants.ts +16 -0
- package/src/controls-options-manager/enums.ts +1 -0
- package/src/controls-options-manager/types.ts +6 -1
- package/src/controls-options-manager/util.ts +31 -0
- package/src/hashTree/constants.ts +12 -0
- package/src/hashTree/hashTree.ts +460 -0
- package/src/hashTree/hashTreeParser.ts +556 -0
- package/src/locus-info/controlsUtils.ts +15 -0
- package/src/locus-info/index.ts +434 -58
- package/src/media/index.ts +2 -2
- package/src/meeting/brbState.ts +13 -9
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +193 -39
- package/src/meeting/muteState.ts +2 -6
- package/src/meeting/request.ts +16 -0
- package/src/meeting/request.type.ts +64 -0
- package/src/meeting/util.ts +17 -20
- package/src/meetings/index.ts +17 -3
- package/src/member/types.ts +1 -0
- package/src/members/collection.ts +11 -0
- package/src/members/index.ts +33 -7
- package/src/members/request.ts +2 -2
- package/src/members/util.ts +14 -3
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/sendSlotManager.ts +34 -2
- package/src/reachability/index.ts +5 -13
- package/test/unit/spec/controls-options-manager/util.js +58 -0
- package/test/unit/spec/hashTree/hashTree.ts +394 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +156 -0
- package/test/unit/spec/locus-info/controlsUtils.js +52 -0
- package/test/unit/spec/locus-info/index.js +547 -54
- package/test/unit/spec/media/index.ts +107 -0
- package/test/unit/spec/meeting/brbState.ts +23 -4
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +647 -46
- package/test/unit/spec/meeting/request.js +71 -0
- package/test/unit/spec/members/index.js +33 -10
- package/test/unit/spec/members/request.js +2 -2
- package/test/unit/spec/members/utils.js +27 -7
- package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
- package/test/unit/spec/reachability/index.ts +2 -6
- package/dist/annotation/annotation.types.d.ts +0 -42
- package/dist/annotation/constants.d.ts +0 -31
- package/dist/annotation/index.d.ts +0 -117
- package/dist/breakouts/breakout.d.ts +0 -8
- package/dist/breakouts/collection.d.ts +0 -5
- package/dist/breakouts/edit-lock-error.d.ts +0 -15
- package/dist/breakouts/events.d.ts +0 -8
- package/dist/breakouts/index.d.ts +0 -5
- package/dist/breakouts/request.d.ts +0 -22
- package/dist/breakouts/utils.d.ts +0 -15
- package/dist/common/browser-detection.d.ts +0 -9
- package/dist/common/collection.d.ts +0 -48
- package/dist/common/config.d.ts +0 -2
- package/dist/common/errors/captcha-error.d.ts +0 -15
- package/dist/common/errors/intent-to-join.d.ts +0 -16
- package/dist/common/errors/join-meeting.d.ts +0 -17
- package/dist/common/errors/media.d.ts +0 -15
- package/dist/common/errors/no-meeting-info.d.ts +0 -14
- package/dist/common/errors/parameter.d.ts +0 -15
- package/dist/common/errors/password-error.d.ts +0 -15
- package/dist/common/errors/permission.d.ts +0 -14
- package/dist/common/errors/reclaim-host-role-error.d.ts +0 -60
- package/dist/common/errors/reclaim-host-role-error.js +0 -158
- package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
- package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
- package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/common/errors/reconnection-in-progress.js +0 -35
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/common/errors/reconnection.d.ts +0 -15
- package/dist/common/errors/stats.d.ts +0 -15
- package/dist/common/errors/webex-errors.d.ts +0 -81
- package/dist/common/errors/webex-meetings-error.d.ts +0 -20
- package/dist/common/events/events-scope.d.ts +0 -17
- package/dist/common/events/events.d.ts +0 -12
- package/dist/common/events/trigger-proxy.d.ts +0 -2
- package/dist/common/events/util.d.ts +0 -2
- package/dist/common/logs/logger-config.d.ts +0 -2
- package/dist/common/logs/logger-proxy.d.ts +0 -2
- package/dist/common/logs/request.d.ts +0 -34
- package/dist/common/queue.d.ts +0 -32
- package/dist/config.d.ts +0 -73
- package/dist/constants.d.ts +0 -952
- package/dist/controls-options-manager/constants.d.ts +0 -4
- package/dist/controls-options-manager/enums.d.ts +0 -5
- package/dist/controls-options-manager/index.d.ts +0 -120
- package/dist/controls-options-manager/types.d.ts +0 -43
- package/dist/controls-options-manager/util.d.ts +0 -7
- package/dist/index.d.ts +0 -4
- package/dist/interceptors/index.d.ts +0 -2
- package/dist/interceptors/locusRetry.d.ts +0 -27
- package/dist/interpretation/collection.d.ts +0 -5
- package/dist/interpretation/index.d.ts +0 -5
- package/dist/interpretation/siLanguage.d.ts +0 -5
- package/dist/locus-info/controlsUtils.d.ts +0 -2
- package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
- package/dist/locus-info/fullState.d.ts +0 -2
- package/dist/locus-info/hostUtils.d.ts +0 -2
- package/dist/locus-info/index.d.ts +0 -269
- package/dist/locus-info/infoUtils.d.ts +0 -2
- package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
- package/dist/locus-info/parser.d.ts +0 -212
- package/dist/locus-info/selfUtils.d.ts +0 -2
- package/dist/media/index.d.ts +0 -32
- package/dist/media/properties.d.ts +0 -108
- package/dist/media/util.d.ts +0 -2
- package/dist/mediaQualityMetrics/config.d.ts +0 -233
- package/dist/mediaQualityMetrics/config.js +0 -513
- package/dist/mediaQualityMetrics/config.js.map +0 -1
- package/dist/meeting/effectsState.d.ts +0 -42
- package/dist/meeting/effectsState.js +0 -260
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/meeting/in-meeting-actions.d.ts +0 -79
- package/dist/meeting/index.d.ts +0 -1622
- package/dist/meeting/locusMediaRequest.d.ts +0 -74
- package/dist/meeting/muteState.d.ts +0 -116
- package/dist/meeting/request.d.ts +0 -257
- package/dist/meeting/request.type.d.ts +0 -11
- package/dist/meeting/state.d.ts +0 -9
- package/dist/meeting/util.d.ts +0 -2
- package/dist/meeting/voicea-meeting.d.ts +0 -16
- package/dist/meeting-info/collection.d.ts +0 -20
- package/dist/meeting-info/index.d.ts +0 -57
- package/dist/meeting-info/meeting-info-v2.d.ts +0 -93
- package/dist/meeting-info/request.d.ts +0 -22
- package/dist/meeting-info/util.d.ts +0 -2
- package/dist/meeting-info/utilv2.d.ts +0 -2
- package/dist/meetings/collection.d.ts +0 -23
- package/dist/meetings/index.d.ts +0 -296
- package/dist/meetings/meetings.types.d.ts +0 -4
- package/dist/meetings/request.d.ts +0 -27
- package/dist/meetings/util.d.ts +0 -18
- package/dist/member/index.d.ts +0 -148
- package/dist/member/member.types.d.ts +0 -11
- package/dist/member/member.types.js +0 -18
- package/dist/member/member.types.js.map +0 -1
- package/dist/member/types.d.ts +0 -32
- package/dist/member/util.d.ts +0 -2
- package/dist/members/collection.d.ts +0 -24
- package/dist/members/index.d.ts +0 -308
- package/dist/members/request.d.ts +0 -58
- package/dist/members/types.d.ts +0 -25
- package/dist/members/util.d.ts +0 -2
- package/dist/metrics/config.d.ts +0 -169
- package/dist/metrics/config.js +0 -289
- package/dist/metrics/config.js.map +0 -1
- package/dist/metrics/constants.d.ts +0 -59
- package/dist/metrics/index.d.ts +0 -152
- package/dist/multistream/mediaRequestManager.d.ts +0 -119
- package/dist/multistream/receiveSlot.d.ts +0 -68
- package/dist/multistream/receiveSlotManager.d.ts +0 -56
- package/dist/multistream/remoteMedia.d.ts +0 -72
- package/dist/multistream/remoteMediaGroup.d.ts +0 -49
- package/dist/multistream/remoteMediaManager.d.ts +0 -300
- package/dist/multistream/sendSlotManager.d.ts +0 -69
- package/dist/networkQualityMonitor/index.d.ts +0 -70
- package/dist/networkQualityMonitor/index.js +0 -226
- package/dist/networkQualityMonitor/index.js.map +0 -1
- package/dist/peer-connection-manager/index.d.ts +0 -6
- package/dist/peer-connection-manager/index.js +0 -671
- package/dist/peer-connection-manager/index.js.map +0 -1
- package/dist/peer-connection-manager/util.d.ts +0 -6
- package/dist/peer-connection-manager/util.js +0 -110
- package/dist/peer-connection-manager/util.js.map +0 -1
- package/dist/personal-meeting-room/index.d.ts +0 -47
- package/dist/personal-meeting-room/request.d.ts +0 -14
- package/dist/personal-meeting-room/util.d.ts +0 -2
- package/dist/reachability/clusterReachability.d.ts +0 -109
- package/dist/reachability/index.d.ts +0 -139
- package/dist/reachability/request.d.ts +0 -35
- package/dist/reachability/util.d.ts +0 -8
- package/dist/reactions/constants.d.ts +0 -3
- package/dist/reactions/reactions.d.ts +0 -4
- package/dist/reactions/reactions.type.d.ts +0 -32
- package/dist/reconnection-manager/index.d.ts +0 -112
- package/dist/recording-controller/enums.d.ts +0 -7
- package/dist/recording-controller/index.d.ts +0 -193
- package/dist/recording-controller/util.d.ts +0 -13
- package/dist/roap/collection.d.ts +0 -10
- package/dist/roap/collection.js +0 -63
- package/dist/roap/collection.js.map +0 -1
- package/dist/roap/handler.d.ts +0 -47
- package/dist/roap/handler.js +0 -279
- package/dist/roap/handler.js.map +0 -1
- package/dist/roap/index.d.ts +0 -116
- package/dist/roap/request.d.ts +0 -35
- package/dist/roap/state.d.ts +0 -9
- package/dist/roap/state.js +0 -127
- package/dist/roap/state.js.map +0 -1
- package/dist/roap/turnDiscovery.d.ts +0 -81
- package/dist/roap/util.d.ts +0 -2
- package/dist/roap/util.js +0 -76
- package/dist/roap/util.js.map +0 -1
- package/dist/rtcMetrics/constants.d.ts +0 -4
- package/dist/rtcMetrics/constants.js +0 -11
- package/dist/rtcMetrics/constants.js.map +0 -1
- package/dist/rtcMetrics/index.d.ts +0 -61
- package/dist/rtcMetrics/index.js +0 -197
- package/dist/rtcMetrics/index.js.map +0 -1
- package/dist/statsAnalyzer/global.d.ts +0 -118
- package/dist/statsAnalyzer/global.js +0 -127
- package/dist/statsAnalyzer/global.js.map +0 -1
- package/dist/statsAnalyzer/index.d.ts +0 -193
- package/dist/statsAnalyzer/index.js +0 -1019
- package/dist/statsAnalyzer/index.js.map +0 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +0 -22
- package/dist/statsAnalyzer/mqaUtil.js +0 -181
- package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
- package/dist/transcription/index.d.ts +0 -64
- package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
- package/dist/types/networkQualityMonitor/index.d.ts +0 -70
- package/dist/types/rtcMetrics/constants.d.ts +0 -4
- package/dist/types/rtcMetrics/index.d.ts +0 -71
- package/dist/types/statsAnalyzer/global.d.ts +0 -36
- package/dist/types/statsAnalyzer/index.d.ts +0 -217
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
- package/dist/webinar/collection.d.ts +0 -16
- package/dist/webinar/index.d.ts +0 -5
@@ -306,6 +306,20 @@ describe('plugin-meetings', () => {
|
|
306
306
|
);
|
307
307
|
});
|
308
308
|
|
309
|
+
it('should trigger the CONTROLS_POLLING_QA_CHANGED event when necessary', () => {
|
310
|
+
locusInfo.controls = {};
|
311
|
+
locusInfo.emitScoped = sinon.stub();
|
312
|
+
newControls.pollingQAControl = { enabled: true };
|
313
|
+
locusInfo.updateControls(newControls);
|
314
|
+
|
315
|
+
assert.calledWith(
|
316
|
+
locusInfo.emitScoped,
|
317
|
+
{file: 'locus-info', function: 'updateControls'},
|
318
|
+
LOCUSINFO.EVENTS.CONTROLS_POLLING_QA_CHANGED,
|
319
|
+
{state: newControls.pollingQAControl}
|
320
|
+
);
|
321
|
+
});
|
322
|
+
|
309
323
|
it('should keep the recording state to `IDLE`', () => {
|
310
324
|
locusInfo.controls = {
|
311
325
|
record: {
|
@@ -557,6 +571,34 @@ describe('plugin-meetings', () => {
|
|
557
571
|
);
|
558
572
|
});
|
559
573
|
|
574
|
+
it('should update the transcribe spoken language', () => {
|
575
|
+
locusInfo.emitScoped = sinon.stub();
|
576
|
+
locusInfo.controls = {
|
577
|
+
transcribe: {
|
578
|
+
transcribing: false,
|
579
|
+
caption: true,
|
580
|
+
spokenLanguage: 'en-US',
|
581
|
+
},
|
582
|
+
};
|
583
|
+
newControls.transcribe.transcribing = false;
|
584
|
+
newControls.transcribe.caption = true;
|
585
|
+
newControls.transcribe.spokenLanguage = 'fr';
|
586
|
+
|
587
|
+
locusInfo.updateControls(newControls);
|
588
|
+
|
589
|
+
assert.calledWith(
|
590
|
+
locusInfo.emitScoped,
|
591
|
+
{
|
592
|
+
file: 'locus-info',
|
593
|
+
function: 'updateControls',
|
594
|
+
},
|
595
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
596
|
+
{
|
597
|
+
spokenLanguage: 'fr',
|
598
|
+
}
|
599
|
+
);
|
600
|
+
});
|
601
|
+
|
560
602
|
it('should update the manual caption state', () => {
|
561
603
|
locusInfo.emitScoped = sinon.stub();
|
562
604
|
locusInfo.controls = {
|
@@ -730,7 +772,7 @@ describe('plugin-meetings', () => {
|
|
730
772
|
},
|
731
773
|
};
|
732
774
|
locusInfo.emitScoped = sinon.stub();
|
733
|
-
locusInfo.updateParticipants({});
|
775
|
+
locusInfo.updateParticipants({}, []);
|
734
776
|
|
735
777
|
// if this assertion fails, double-check the attributes used in
|
736
778
|
// the updateParticipants function in locus-info/index.js
|
@@ -748,6 +790,7 @@ describe('plugin-meetings', () => {
|
|
748
790
|
selfId: '2',
|
749
791
|
hostId: '3',
|
750
792
|
isReplace: undefined,
|
793
|
+
removedParticipantIds: [],
|
751
794
|
}
|
752
795
|
);
|
753
796
|
// note: in a real use case, recordingId, selfId, and hostId would all be the same
|
@@ -772,7 +815,7 @@ describe('plugin-meetings', () => {
|
|
772
815
|
};
|
773
816
|
|
774
817
|
locusInfo.emitScoped = sinon.stub();
|
775
|
-
locusInfo.updateParticipants({}, true);
|
818
|
+
locusInfo.updateParticipants({}, [], true);
|
776
819
|
|
777
820
|
assert.calledWith(
|
778
821
|
locusInfo.emitScoped,
|
@@ -788,6 +831,7 @@ describe('plugin-meetings', () => {
|
|
788
831
|
selfId: '2',
|
789
832
|
hostId: '3',
|
790
833
|
isReplace: true,
|
834
|
+
removedParticipantIds: [],
|
791
835
|
}
|
792
836
|
);
|
793
837
|
});
|
@@ -838,7 +882,7 @@ describe('plugin-meetings', () => {
|
|
838
882
|
];
|
839
883
|
|
840
884
|
locusInfo.emitScoped = sinon.stub();
|
841
|
-
locusInfo.updateParticipants(failureParticipant);
|
885
|
+
locusInfo.updateParticipants(failureParticipant, []);
|
842
886
|
assert.calledWith(
|
843
887
|
locusInfo.emitScoped,
|
844
888
|
{
|
@@ -2019,7 +2063,7 @@ describe('plugin-meetings', () => {
|
|
2019
2063
|
|
2020
2064
|
fakeLocus = {
|
2021
2065
|
meeting: true,
|
2022
|
-
participants:
|
2066
|
+
participants: [],
|
2023
2067
|
url: 'newLocusUrl',
|
2024
2068
|
syncUrl: 'newSyncUrl',
|
2025
2069
|
};
|
@@ -2066,6 +2110,38 @@ describe('plugin-meetings', () => {
|
|
2066
2110
|
assert.isFunction(locusParser.onDeltaAction);
|
2067
2111
|
});
|
2068
2112
|
|
2113
|
+
it("#updateLocusInfo invokes updateLocusUrl before updateMeetingInfo", () => {
|
2114
|
+
const callOrder = [];
|
2115
|
+
sinon.stub(locusInfo, "updateControls");
|
2116
|
+
sinon.stub(locusInfo, "updateConversationUrl");
|
2117
|
+
sinon.stub(locusInfo, "updateCreated");
|
2118
|
+
sinon.stub(locusInfo, "updateFullState");
|
2119
|
+
sinon.stub(locusInfo, "updateHostInfo");
|
2120
|
+
sinon.stub(locusInfo, "updateMeetingInfo").callsFake(() => {
|
2121
|
+
callOrder.push("updateMeetingInfo");
|
2122
|
+
});
|
2123
|
+
sinon.stub(locusInfo, "updateMediaShares");
|
2124
|
+
sinon.stub(locusInfo, "updateParticipantsUrl");
|
2125
|
+
sinon.stub(locusInfo, "updateReplace");
|
2126
|
+
sinon.stub(locusInfo, "updateSelf");
|
2127
|
+
sinon.stub(locusInfo, "updateLocusUrl").callsFake(() => {
|
2128
|
+
callOrder.push("updateLocusUrl");
|
2129
|
+
});
|
2130
|
+
sinon.stub(locusInfo, "updateAclUrl");
|
2131
|
+
sinon.stub(locusInfo, "updateBasequence");
|
2132
|
+
sinon.stub(locusInfo, "updateSequence");
|
2133
|
+
sinon.stub(locusInfo, "updateMemberShip");
|
2134
|
+
sinon.stub(locusInfo, "updateIdentifiers");
|
2135
|
+
sinon.stub(locusInfo, "updateEmbeddedApps");
|
2136
|
+
sinon.stub(locusInfo, "updateResources");
|
2137
|
+
sinon.stub(locusInfo, "compareAndUpdate");
|
2138
|
+
|
2139
|
+
locusInfo.updateLocusInfo(locus);
|
2140
|
+
|
2141
|
+
// Ensure updateLocusUrl is called before updateMeetingInfo if both are called
|
2142
|
+
assert.deepEqual(callOrder, ['updateLocusUrl', 'updateMeetingInfo']);
|
2143
|
+
});
|
2144
|
+
|
2069
2145
|
it('#updateLocusInfo ignores breakout LEFT message', () => {
|
2070
2146
|
const newLocus = {
|
2071
2147
|
self: {
|
@@ -2117,6 +2193,8 @@ describe('plugin-meetings', () => {
|
|
2117
2193
|
assert.notCalled(locusInfo.compareAndUpdate);
|
2118
2194
|
});
|
2119
2195
|
|
2196
|
+
|
2197
|
+
|
2120
2198
|
it('onFullLocus() updates the working-copy of locus parser', () => {
|
2121
2199
|
const eventType = 'fakeEvent';
|
2122
2200
|
|
@@ -2215,7 +2293,7 @@ describe('plugin-meetings', () => {
|
|
2215
2293
|
|
2216
2294
|
it('applyLocusDeltaData gets delta locus on DESYNC action if we have a syncUrl', () => {
|
2217
2295
|
const {DESYNC} = LocusDeltaParser.loci;
|
2218
|
-
const fakeDeltaLocus = {id: 'fake delta locus'};
|
2296
|
+
const fakeDeltaLocus = {baseSequence: {}, id: 'fake delta locus'};
|
2219
2297
|
const meeting = {
|
2220
2298
|
meetingRequest: {
|
2221
2299
|
getLocusDTO: sandbox.stub().resolves({body: fakeDeltaLocus}),
|
@@ -2350,25 +2428,22 @@ describe('plugin-meetings', () => {
|
|
2350
2428
|
};
|
2351
2429
|
});
|
2352
2430
|
|
2353
|
-
it('applyLocusDeltaData gets full locus on DESYNC action if we do not have a syncUrl and destroys the meeting if that fails', () => {
|
2431
|
+
it('applyLocusDeltaData gets full locus on DESYNC action if we do not have a syncUrl and destroys the meeting if that fails', async () => {
|
2354
2432
|
meeting.meetingRequest.getLocusDTO.rejects(new Error('fake error'));
|
2355
2433
|
|
2356
2434
|
locusInfo.locusParser.workingCopy = {}; // no syncUrl
|
2357
2435
|
|
2358
|
-
|
2359
|
-
// we will wait and stub it's last function to resolve this waiting promise.
|
2360
|
-
return new Promise((resolve) => {
|
2361
|
-
webex.meetings.destroy.callsFake(() => resolve());
|
2362
|
-
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2363
|
-
}).then(() => {
|
2364
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'fullSyncUrl'});
|
2436
|
+
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2365
2437
|
|
2366
|
-
|
2367
|
-
assert.notCalled(meeting.locusInfo.onFullLocus);
|
2368
|
-
assert.notCalled(locusInfo.locusParser.resume);
|
2438
|
+
await testUtils.flushPromises();
|
2369
2439
|
|
2370
|
-
|
2371
|
-
|
2440
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'fullSyncUrl'});
|
2441
|
+
|
2442
|
+
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
2443
|
+
assert.notCalled(meeting.locusInfo.onFullLocus);
|
2444
|
+
assert.notCalled(locusInfo.locusParser.resume);
|
2445
|
+
|
2446
|
+
assert.calledOnceWithExactly(webex.meetings.destroy, meeting, 'LOCUS_DTO_SYNC_FAILED');
|
2372
2447
|
});
|
2373
2448
|
|
2374
2449
|
it('applyLocusDeltaData first tries a delta sync on DESYNC action and if that fails, does a full locus sync', () => {
|
@@ -2405,44 +2480,67 @@ describe('plugin-meetings', () => {
|
|
2405
2480
|
});
|
2406
2481
|
});
|
2407
2482
|
|
2408
|
-
it('applyLocusDeltaData
|
2483
|
+
it('applyLocusDeltaData first tries a delta sync on DESYNC action and if that fails with 403, it does not do a full locus sync', async () => {
|
2484
|
+
const fake403Error = new Error('fake error');
|
2485
|
+
fake403Error.statusCode = 403;
|
2486
|
+
|
2487
|
+
meeting.meetingRequest.getLocusDTO.onCall(0).rejects(fake403Error);
|
2488
|
+
|
2489
|
+
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2490
|
+
|
2491
|
+
await testUtils.flushPromises();
|
2492
|
+
|
2493
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'deltaSyncUrl'});
|
2494
|
+
|
2495
|
+
assert.calledWith(sendBehavioralMetricStub, 'js_sdk_locus_delta_sync_failed', {
|
2496
|
+
correlationId: meeting.correlationId,
|
2497
|
+
url: 'deltaSyncUrl',
|
2498
|
+
reason: 'fake error',
|
2499
|
+
errorName: 'Error',
|
2500
|
+
stack: sinon.match.any,
|
2501
|
+
code: sinon.match.any,
|
2502
|
+
});
|
2503
|
+
|
2504
|
+
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
2505
|
+
assert.notCalled(meeting.locusInfo.onFullLocus);
|
2506
|
+
assert.notCalled(locusInfo.locusParser.resume);
|
2507
|
+
});
|
2508
|
+
|
2509
|
+
it('applyLocusDeltaData destroys the meeting if both delta sync and full sync fail', async () => {
|
2409
2510
|
meeting.meetingRequest.getLocusDTO.rejects(new Error('fake error'));
|
2410
2511
|
|
2411
|
-
|
2412
|
-
// we will wait and stub it's last function to resolve this waiting promise.
|
2413
|
-
return new Promise((resolve) => {
|
2414
|
-
webex.meetings.destroy.callsFake(() => resolve());
|
2415
|
-
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2416
|
-
}).then(() => {
|
2417
|
-
assert.calledTwice(meeting.meetingRequest.getLocusDTO);
|
2512
|
+
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2418
2513
|
|
2419
|
-
|
2420
|
-
{url: 'deltaSyncUrl'},
|
2421
|
-
]);
|
2422
|
-
assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[1].args, [
|
2423
|
-
{url: 'fullSyncUrl'},
|
2424
|
-
]);
|
2514
|
+
await testUtils.flushPromises();
|
2425
2515
|
|
2426
|
-
|
2427
|
-
correlationId: meeting.correlationId,
|
2428
|
-
url: 'deltaSyncUrl',
|
2429
|
-
reason: 'fake error',
|
2430
|
-
errorName: 'Error',
|
2431
|
-
stack: sinon.match.any,
|
2432
|
-
code: sinon.match.any,
|
2433
|
-
});
|
2516
|
+
assert.calledTwice(meeting.meetingRequest.getLocusDTO);
|
2434
2517
|
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2518
|
+
assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[0].args, [
|
2519
|
+
{url: 'deltaSyncUrl'},
|
2520
|
+
]);
|
2521
|
+
assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[1].args, [
|
2522
|
+
{url: 'fullSyncUrl'},
|
2523
|
+
]);
|
2438
2524
|
|
2439
|
-
|
2525
|
+
assert.calledWith(sendBehavioralMetricStub, 'js_sdk_locus_delta_sync_failed', {
|
2526
|
+
correlationId: meeting.correlationId,
|
2527
|
+
url: 'deltaSyncUrl',
|
2528
|
+
reason: 'fake error',
|
2529
|
+
errorName: 'Error',
|
2530
|
+
stack: sinon.match.any,
|
2531
|
+
code: sinon.match.any,
|
2440
2532
|
});
|
2533
|
+
|
2534
|
+
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
2535
|
+
assert.notCalled(meeting.locusInfo.onFullLocus);
|
2536
|
+
assert.notCalled(locusInfo.locusParser.resume);
|
2537
|
+
|
2538
|
+
assert.calledOnceWithExactly(webex.meetings.destroy, meeting, 'LOCUS_DTO_SYNC_FAILED');
|
2441
2539
|
});
|
2442
2540
|
});
|
2443
2541
|
|
2444
2542
|
it('onDeltaLocus handle delta data', () => {
|
2445
|
-
fakeLocus.participants =
|
2543
|
+
fakeLocus.participants = [];
|
2446
2544
|
const fakeBreakout = {
|
2447
2545
|
sessionId: 'sessionId',
|
2448
2546
|
groupId: 'groupId',
|
@@ -2459,17 +2557,15 @@ describe('plugin-meetings', () => {
|
|
2459
2557
|
};
|
2460
2558
|
locusInfo.updateParticipants = sinon.stub();
|
2461
2559
|
locusInfo.onDeltaLocus(fakeLocus);
|
2462
|
-
assert.calledWith(locusInfo.updateParticipants,
|
2560
|
+
assert.calledWith(locusInfo.updateParticipants, [], undefined, false);
|
2463
2561
|
|
2464
2562
|
fakeLocus.controls.breakout.sessionId = 'sessionId2';
|
2465
2563
|
locusInfo.onDeltaLocus(fakeLocus);
|
2466
|
-
assert.calledWith(locusInfo.updateParticipants,
|
2564
|
+
assert.calledWith(locusInfo.updateParticipants, [], undefined, true);
|
2467
2565
|
});
|
2468
2566
|
|
2469
2567
|
it('onDeltaLocus merges delta participants with existing participants', () => {
|
2470
|
-
const FAKE_DELTA_PARTICIPANTS = [
|
2471
|
-
{id: '1111'}, {id: '2222'}
|
2472
|
-
]
|
2568
|
+
const FAKE_DELTA_PARTICIPANTS = [{id: '1111'}, {id: '2222'}];
|
2473
2569
|
fakeLocus.participants = FAKE_DELTA_PARTICIPANTS;
|
2474
2570
|
|
2475
2571
|
sinon.spy(locusInfo, 'mergeParticipants');
|
@@ -2477,8 +2573,86 @@ describe('plugin-meetings', () => {
|
|
2477
2573
|
const existingParticipants = locusInfo.participants;
|
2478
2574
|
|
2479
2575
|
locusInfo.onDeltaLocus(fakeLocus);
|
2480
|
-
assert.calledOnceWithExactly(
|
2481
|
-
|
2576
|
+
assert.calledOnceWithExactly(
|
2577
|
+
locusInfo.mergeParticipants,
|
2578
|
+
existingParticipants,
|
2579
|
+
FAKE_DELTA_PARTICIPANTS
|
2580
|
+
);
|
2581
|
+
assert.calledWith(locusInfo.updateParticipants, FAKE_DELTA_PARTICIPANTS, undefined, false);
|
2582
|
+
});
|
2583
|
+
|
2584
|
+
[true, false].forEach((isDelta) =>
|
2585
|
+
it(`applyLocusDeltaData - handles empty ${
|
2586
|
+
isDelta ? 'delta' : 'full'
|
2587
|
+
} DTO in response`, async () => {
|
2588
|
+
const {DESYNC} = LocusDeltaParser.loci;
|
2589
|
+
const fakeFullLocusDto = {};
|
2590
|
+
const meeting = {
|
2591
|
+
meetingRequest: {
|
2592
|
+
getLocusDTO: sandbox.stub().resolves({body: fakeFullLocusDto}),
|
2593
|
+
},
|
2594
|
+
locusInfo: {
|
2595
|
+
onFullLocus: sandbox.stub(),
|
2596
|
+
handleLocusDelta: sandbox.stub(),
|
2597
|
+
},
|
2598
|
+
locusUrl: 'fake locus FULL url',
|
2599
|
+
};
|
2600
|
+
|
2601
|
+
sinon.stub(locusInfo.locusParser, 'resume').resolves();
|
2602
|
+
|
2603
|
+
if (isDelta) {
|
2604
|
+
locusInfo.locusParser.workingCopy = {syncUrl: 'fake locus DELTA url'};
|
2605
|
+
} else {
|
2606
|
+
locusInfo.locusParser.workingCopy = {}; // no syncUrl (to trigger FULL DTO request)
|
2607
|
+
}
|
2608
|
+
|
2609
|
+
await locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2610
|
+
|
2611
|
+
await testUtils.flushPromises();
|
2612
|
+
|
2613
|
+
if (isDelta) {
|
2614
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {
|
2615
|
+
url: 'fake locus DELTA url',
|
2616
|
+
});
|
2617
|
+
} else {
|
2618
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {
|
2619
|
+
url: 'fake locus FULL url',
|
2620
|
+
});
|
2621
|
+
}
|
2622
|
+
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
2623
|
+
assert.notCalled(meeting.locusInfo.onFullLocus);
|
2624
|
+
assert.calledOnce(locusInfo.locusParser.resume);
|
2625
|
+
})
|
2626
|
+
);
|
2627
|
+
|
2628
|
+
it(`applyLocusDeltaData - handles the case when we get FULL DTO when we asked for DELTA DTO`, async () => {
|
2629
|
+
const {DESYNC} = LocusDeltaParser.loci;
|
2630
|
+
const fakeFullLocusDto = {someStuff: 'data'}; // non-empty DTO, without baseSequence
|
2631
|
+
const meeting = {
|
2632
|
+
meetingRequest: {
|
2633
|
+
getLocusDTO: sandbox.stub().resolves({body: fakeFullLocusDto}),
|
2634
|
+
},
|
2635
|
+
locusInfo: {
|
2636
|
+
onFullLocus: sandbox.stub(),
|
2637
|
+
handleLocusDelta: sandbox.stub(),
|
2638
|
+
},
|
2639
|
+
locusUrl: 'fake locus FULL url',
|
2640
|
+
};
|
2641
|
+
|
2642
|
+
sinon.stub(locusInfo.locusParser, 'resume').resolves();
|
2643
|
+
|
2644
|
+
locusInfo.locusParser.workingCopy = {syncUrl: 'fake locus DELTA url'};
|
2645
|
+
|
2646
|
+
await locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
2647
|
+
|
2648
|
+
await testUtils.flushPromises();
|
2649
|
+
|
2650
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {
|
2651
|
+
url: 'fake locus DELTA url',
|
2652
|
+
});
|
2653
|
+
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
2654
|
+
assert.calledOnceWithExactly(meeting.locusInfo.onFullLocus, fakeFullLocusDto);
|
2655
|
+
assert.calledOnce(locusInfo.locusParser.resume);
|
2482
2656
|
});
|
2483
2657
|
});
|
2484
2658
|
|
@@ -2894,8 +3068,8 @@ describe('plugin-meetings', () => {
|
|
2894
3068
|
|
2895
3069
|
sinon.stub(locusInfo, 'updateParticipantDeltas');
|
2896
3070
|
sinon.stub(locusInfo, 'updateParticipants');
|
2897
|
-
sinon.stub(locusInfo, 'isMeetingActive')
|
2898
|
-
sinon.stub(locusInfo, 'handleOneOnOneEvent')
|
3071
|
+
sinon.stub(locusInfo, 'isMeetingActive');
|
3072
|
+
sinon.stub(locusInfo, 'handleOneOnOneEvent');
|
2899
3073
|
(updateLocusInfoStub = sinon.stub(locusInfo, 'updateLocusInfo'));
|
2900
3074
|
syncRequestStub = sinon.stub().resolves({body: {}});
|
2901
3075
|
|
@@ -2916,6 +3090,7 @@ describe('plugin-meetings', () => {
|
|
2916
3090
|
id: 'test person id',
|
2917
3091
|
},
|
2918
3092
|
},
|
3093
|
+
participants: [],
|
2919
3094
|
});
|
2920
3095
|
|
2921
3096
|
updateLocusInfoStub.resetHistory();
|
@@ -3064,6 +3239,7 @@ describe('plugin-meetings', () => {
|
|
3064
3239
|
await testUtils.flushPromises();
|
3065
3240
|
|
3066
3241
|
assert.calledOnceWithExactly(syncRequestStub, {url: mockMeeting.locusUrl});
|
3242
|
+
assert.calledOnce(updateLocusInfoStub);
|
3067
3243
|
assert.calledOnceWithExactly(updateLocusInfoStub, fullLocus);
|
3068
3244
|
});
|
3069
3245
|
|
@@ -3139,5 +3315,322 @@ describe('plugin-meetings', () => {
|
|
3139
3315
|
assert.calledWith(updateLocusInfoStub.getCall(2), deltaEvents[7]);
|
3140
3316
|
});
|
3141
3317
|
});
|
3318
|
+
|
3319
|
+
describe('Hash trees - webinar 5k', () => {
|
3320
|
+
let mockFullLocus;
|
3321
|
+
let clock;
|
3322
|
+
|
3323
|
+
beforeEach(() => {
|
3324
|
+
|
3325
|
+
sinon.stub(Math, 'random').returns(0.5); // to make sure the backoff timer is predictable
|
3326
|
+
|
3327
|
+
mockFullLocus = {
|
3328
|
+
dataSets: [
|
3329
|
+
{
|
3330
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f/session/a73e9f2c/datasets/main',
|
3331
|
+
root: '9bb9d5a911a74d53a915b4dfbec7329f',
|
3332
|
+
version: 51118,
|
3333
|
+
leafCount: 16,
|
3334
|
+
name: 'main',
|
3335
|
+
idleMs : 5000,
|
3336
|
+
backoff : {
|
3337
|
+
maxMs : 500,
|
3338
|
+
exponent : 0.5
|
3339
|
+
},
|
3340
|
+
},
|
3341
|
+
{
|
3342
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f/session/a73e9f2c/participant/713e9f99/datasets/self',
|
3343
|
+
root: '5b8cc7ffda1346d2bfb1c0b60b8ab601',
|
3344
|
+
version: 89891,
|
3345
|
+
leafCount: 1,
|
3346
|
+
name: 'self',
|
3347
|
+
idleMs : 10000,
|
3348
|
+
backoff : {
|
3349
|
+
maxMs : 500,
|
3350
|
+
exponent : 0.5
|
3351
|
+
},
|
3352
|
+
},
|
3353
|
+
{
|
3354
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f/session/a73e9f2c/datasets/atd-unmuted',
|
3355
|
+
root: '9279d2e149da43a1b8e2cd7cbf77f9f0',
|
3356
|
+
version: 91277,
|
3357
|
+
leafCount: 16,
|
3358
|
+
name: 'atd-unmuted',
|
3359
|
+
idleMs : 15000,
|
3360
|
+
backoff : {
|
3361
|
+
maxMs : 500,
|
3362
|
+
exponent : 0.5
|
3363
|
+
},
|
3364
|
+
},
|
3365
|
+
],
|
3366
|
+
locus: {
|
3367
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f',
|
3368
|
+
htMeta: {
|
3369
|
+
elementId: {
|
3370
|
+
type: 'LOCUS',
|
3371
|
+
id: 0,
|
3372
|
+
version: 5678,
|
3373
|
+
},
|
3374
|
+
dataSetNames: ['main'],
|
3375
|
+
},
|
3376
|
+
participants: [
|
3377
|
+
{
|
3378
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f/participant/11941033',
|
3379
|
+
person: {
|
3380
|
+
id: '111',
|
3381
|
+
name: '1st participant',
|
3382
|
+
},
|
3383
|
+
htMeta: {
|
3384
|
+
elementId: {
|
3385
|
+
type: 'PARTICIPANT',
|
3386
|
+
id: 2,
|
3387
|
+
version: 5678,
|
3388
|
+
},
|
3389
|
+
dataSetNames: ['atd-active', 'attendees', 'atd-unmuted'],
|
3390
|
+
},
|
3391
|
+
},
|
3392
|
+
{
|
3393
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f/participant/11941034',
|
3394
|
+
person: {
|
3395
|
+
id: '222',
|
3396
|
+
name: '2nd participant',
|
3397
|
+
},
|
3398
|
+
htMeta: {
|
3399
|
+
elementId: {
|
3400
|
+
type: 'PARTICIPANT',
|
3401
|
+
id: 3,
|
3402
|
+
version: 5678,
|
3403
|
+
},
|
3404
|
+
dataSetNames: ['attendees'],
|
3405
|
+
},
|
3406
|
+
},
|
3407
|
+
],
|
3408
|
+
self: {
|
3409
|
+
url: 'https://locus-a.wbx2.com/locus/api/v1/loci/97d64a5f/participant/11941033',
|
3410
|
+
visibleDataSets: ['main', 'self', 'atd-unmuted'],
|
3411
|
+
person: {
|
3412
|
+
id: '333',
|
3413
|
+
name: 'myself',
|
3414
|
+
},
|
3415
|
+
htMeta: {
|
3416
|
+
elementId: {
|
3417
|
+
type: 'SELF',
|
3418
|
+
id: 4,
|
3419
|
+
version: 5678,
|
3420
|
+
},
|
3421
|
+
dataSetNames: ['self'],
|
3422
|
+
},
|
3423
|
+
},
|
3424
|
+
},
|
3425
|
+
};
|
3426
|
+
|
3427
|
+
clock = sinon.useFakeTimers();
|
3428
|
+
|
3429
|
+
});
|
3430
|
+
|
3431
|
+
afterEach(() => {
|
3432
|
+
clock.restore();
|
3433
|
+
});
|
3434
|
+
|
3435
|
+
const getMaxBackoffTime = (dataSets) => {
|
3436
|
+
return Object.values(dataSets).reduce((max, dataSet) => {
|
3437
|
+
const maxBackOff = dataSet.idleMs + dataSet.backoff.maxMs;
|
3438
|
+
return Math.max(max, maxBackOff);
|
3439
|
+
}, 0);
|
3440
|
+
}
|
3441
|
+
|
3442
|
+
const waitForMaxPossibleBackoffTime = async (dataSets) => {
|
3443
|
+
const maxBackoffTime = getMaxBackoffTime(dataSets);
|
3444
|
+
clock.tick(maxBackoffTime);
|
3445
|
+
await testUtils.flushPromises();
|
3446
|
+
}
|
3447
|
+
|
3448
|
+
it('initializes hash trees correctly from initial full locus', () => {
|
3449
|
+
locusInfo.initialSetup(mockFullLocus.locus, mockFullLocus.dataSets);
|
3450
|
+
|
3451
|
+
// check that the hash tree parser is initialized correctly
|
3452
|
+
assert.isDefined(locusInfo.hashTreeParser);
|
3453
|
+
assert.deepEqual(Object.keys(locusInfo.hashTreeParser.dataSets), ['main', 'self', 'atd-unmuted']);
|
3454
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['main'].hashTree.getLeafData(0), [ { type: 'LOCUS', id: 0, version: 5678 } ]);
|
3455
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['self'].hashTree.getLeafData(0), [ { type: 'SELF', id: 4, version: 5678 } ]);
|
3456
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['atd-unmuted'].hashTree.getLeafData(2), [ { type: 'PARTICIPANT', id: 2, version: 5678 } ]);
|
3457
|
+
|
3458
|
+
// participant with id=3 is not part of any of our datasets, so should be undefined
|
3459
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['atd-unmuted'].hashTree.getLeafData(3), []);
|
3460
|
+
});
|
3461
|
+
|
3462
|
+
it('handles hash tree messages correctly', async () => {
|
3463
|
+
locusInfo.initialSetup(mockFullLocus.locus, mockFullLocus.dataSets);
|
3464
|
+
|
3465
|
+
// simulate a hash tree message for a participant
|
3466
|
+
locusInfo.parse(mockMeeting, {
|
3467
|
+
"locusUrl" : "https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2",
|
3468
|
+
"locusSessionId" : "fe3d019c-08ca-0f21-919f-f2cc646030ae",
|
3469
|
+
"dataSets" : [ {
|
3470
|
+
"url" : "https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2/session/fe3d019c-08ca-0f21-919f-f2cc646030ae/datasets/attendees",
|
3471
|
+
"name" : "attendees",
|
3472
|
+
"root" : "7cfc14bdae7909e6fe7acd37bebf66db",
|
3473
|
+
"version" : 4739733700975,
|
3474
|
+
"leafCount" : 16,
|
3475
|
+
"idleMs" : 5000,
|
3476
|
+
"backoff" : {
|
3477
|
+
"maxMs" : 500,
|
3478
|
+
"exponent" : 0.5
|
3479
|
+
}
|
3480
|
+
}, {
|
3481
|
+
"url" : "https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2/session/fe3d019c-08ca-0f21-919f-f2cc646030ae/datasets/atd-active",
|
3482
|
+
"name" : "atd-unmuted",
|
3483
|
+
"root" : "178bff6e3344f551a811712c57a9eac3",
|
3484
|
+
"version" : 5738696122316,
|
3485
|
+
"leafCount" : 4,
|
3486
|
+
"idleMs" : 5000,
|
3487
|
+
"backoff" : {
|
3488
|
+
"maxMs" : 500,
|
3489
|
+
"exponent" : 0.5
|
3490
|
+
}
|
3491
|
+
} ],
|
3492
|
+
"locusStateElements" : [ {
|
3493
|
+
"htMeta" : {
|
3494
|
+
"elementId" : {
|
3495
|
+
"type" : "PARTICIPANT",
|
3496
|
+
"id" : 2,
|
3497
|
+
"version" : 5679
|
3498
|
+
},
|
3499
|
+
"dataSetNames" : [ "attendees", "atd-unmuted" ]
|
3500
|
+
},
|
3501
|
+
"data" : "{\"isCreator\":false,\"url\":\"https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2/participant/18ef210c-234a-49ac-83d6-1803bc401bc9\",\"id\":\"18ef210c-234a-49ac-83d6-1803bc401bc9\",\"guest\":false,\"resourceGuest\":false,\"moderator\":false,\"panelist\":false}"
|
3502
|
+
}, {
|
3503
|
+
"htMeta" : {
|
3504
|
+
"elementId" : {
|
3505
|
+
"type" : "PARTICIPANT",
|
3506
|
+
"id" : 3,
|
3507
|
+
"version" : 999999
|
3508
|
+
},
|
3509
|
+
"dataSetNames" : [ "attendees" ]
|
3510
|
+
},
|
3511
|
+
"data" : "{\"isCreator\":false,\"url\":\"https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2/participant/29c0751a-7ada-40a1-94a4-eb5f5c80c863\",\"id\":\"29c0751a-7ada-40a1-94a4-eb5f5c80c863\",\"guest\":false,\"resourceGuest\":false,\"moderator\":false,\"panelist\":false}"
|
3512
|
+
} ]
|
3513
|
+
});
|
3514
|
+
|
3515
|
+
// main and self should be unchanged
|
3516
|
+
assert.deepEqual(Object.keys(locusInfo.hashTreeParser.dataSets), ['main', 'self', 'atd-unmuted']);
|
3517
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['main'].hashTree.getLeafData(0), [ { type: 'LOCUS', id: 0, version: 5678 } ]);
|
3518
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['self'].hashTree.getLeafData(0), [ { type: 'SELF', id: 4, version: 5678 } ]);
|
3519
|
+
|
3520
|
+
// participant should be updated
|
3521
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['atd-unmuted'].hashTree.getLeafData(2), [ { type: 'PARTICIPANT', id: 2, version: 5679 } ]);
|
3522
|
+
|
3523
|
+
// there should be no requests to Locus sent
|
3524
|
+
await waitForMaxPossibleBackoffTime(locusInfo.hashTreeParser.dataSets);
|
3525
|
+
assert.notCalled(webex.request);
|
3526
|
+
});
|
3527
|
+
|
3528
|
+
it('does a sync if hashes don\'t match after a timer fires', async () => {
|
3529
|
+
const atdUnmutedDataSetUrl = mockFullLocus.dataSets[2].url;
|
3530
|
+
|
3531
|
+
locusInfo.initialSetup(mockFullLocus.locus, mockFullLocus.dataSets);
|
3532
|
+
|
3533
|
+
// simulate a hash tree message for a participant
|
3534
|
+
locusInfo.parse(mockMeeting, {
|
3535
|
+
"locusUrl" : "https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2",
|
3536
|
+
"locusSessionId" : "fe3d019c-08ca-0f21-919f-f2cc646030ae",
|
3537
|
+
"dataSets" : [ {
|
3538
|
+
"url" : atdUnmutedDataSetUrl,
|
3539
|
+
"name" : "atd-unmuted",
|
3540
|
+
"root" : "deadbeef", // wrong to trigger a sync
|
3541
|
+
"version" : 5738696122316,
|
3542
|
+
"leafCount" : 4,
|
3543
|
+
"idleMs" : 25000,
|
3544
|
+
"backoff" : {
|
3545
|
+
"maxMs" : 500,
|
3546
|
+
"exponent" : 0.5
|
3547
|
+
}
|
3548
|
+
} ],
|
3549
|
+
"locusStateElements" : [ {
|
3550
|
+
"htMeta" : {
|
3551
|
+
"elementId" : {
|
3552
|
+
"type" : "PARTICIPANT",
|
3553
|
+
"id" : 2,
|
3554
|
+
"version" : 5679
|
3555
|
+
},
|
3556
|
+
"dataSetNames" : [ "attendees", "atd-unmuted" ]
|
3557
|
+
},
|
3558
|
+
"data" : "{\"isCreator\":false,\"url\":\"https://locus.wbx2.com/locus/api/v1/loci/dbe6eeb9-49c7-4727-bdb1-1c59fa6e56d2/participant/18ef210c-234a-49ac-83d6-1803bc401bc9\",\"id\":\"18ef210c-234a-49ac-83d6-1803bc401bc9\",\"guest\":false,\"resourceGuest\":false,\"moderator\":false,\"panelist\":false}"
|
3559
|
+
}]
|
3560
|
+
});
|
3561
|
+
|
3562
|
+
// main and self should be unchanged
|
3563
|
+
assert.deepEqual(Object.keys(locusInfo.hashTreeParser.dataSets), ['main', 'self', 'atd-unmuted']);
|
3564
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['main'].hashTree.getLeafData(0), [ { type: 'LOCUS', id: 0, version: 5678 } ]);
|
3565
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['self'].hashTree.getLeafData(0), [ { type: 'SELF', id: 4, version: 5678 } ]);
|
3566
|
+
|
3567
|
+
// participant should be updated
|
3568
|
+
assert.deepEqual(locusInfo.hashTreeParser.dataSets['atd-unmuted'].hashTree.getLeafData(2), [ { type: 'PARTICIPANT', id: 2, version: 5679 } ]);
|
3569
|
+
|
3570
|
+
await testUtils.flushPromises();
|
3571
|
+
|
3572
|
+
// the root hash doesn't match, but we shouldn't send a request to Locus for hashes just yet
|
3573
|
+
assert.notCalled(webex.request);
|
3574
|
+
|
3575
|
+
webex.request.callsFake(async (options) => {
|
3576
|
+
if (options?.method === 'GET' && options?.uri?.endsWith('/hashtree')) {
|
3577
|
+
return {
|
3578
|
+
body: {
|
3579
|
+
hashes: [
|
3580
|
+
'178bff6e3344f551a811712c57a9eac3',
|
3581
|
+
'b113a76304e3a7121afecfe1606ee1c1',
|
3582
|
+
'ae70773ebb3be3653209648071b9bdad',
|
3583
|
+
'99aa06d3014798d86001c324468d497f',
|
3584
|
+
'99aa06d3014798d86001c324468d497f',
|
3585
|
+
'deadbeef', // wrong hash that should cause the participant with id=2 to be deemed out of sync
|
3586
|
+
'99aa06d3014798d86001c324468d497f'
|
3587
|
+
]
|
3588
|
+
}
|
3589
|
+
};
|
3590
|
+
} else if (options?.method === 'POST' && options?.uri?.endsWith('/sync')) {
|
3591
|
+
return {
|
3592
|
+
body: {},
|
3593
|
+
statusCode: 202,
|
3594
|
+
};
|
3595
|
+
}
|
3596
|
+
return {};
|
3597
|
+
});
|
3598
|
+
|
3599
|
+
// only after timeout there should be requests to get hashes and sync sent to Locus
|
3600
|
+
await waitForMaxPossibleBackoffTime(locusInfo.hashTreeParser.dataSets);
|
3601
|
+
assert.calledTwice(webex.request);
|
3602
|
+
|
3603
|
+
const firstCallArgs = webex.request.getCall(0).args[0];
|
3604
|
+
const secondCallArgs = webex.request.getCall(1).args[0];
|
3605
|
+
|
3606
|
+
assert.deepEqual(firstCallArgs, {method: 'GET', uri: `${atdUnmutedDataSetUrl}/hashtree`});
|
3607
|
+
|
3608
|
+
assert.deepEqual(secondCallArgs, {method: 'POST', uri: `${atdUnmutedDataSetUrl}/sync`,
|
3609
|
+
body: {
|
3610
|
+
dataSet: {
|
3611
|
+
name: 'atd-unmuted',
|
3612
|
+
leafCount: 16,
|
3613
|
+
root: '178bff6e3344f551a811712c57a9eac3',
|
3614
|
+
},
|
3615
|
+
leafDataEntries: [{
|
3616
|
+
leafIndex: 2,
|
3617
|
+
elementIds: [
|
3618
|
+
{
|
3619
|
+
id: 2,
|
3620
|
+
type: "PARTICIPANT",
|
3621
|
+
version: 5679
|
3622
|
+
}
|
3623
|
+
],
|
3624
|
+
}]
|
3625
|
+
}
|
3626
|
+
});
|
3627
|
+
});
|
3628
|
+
|
3629
|
+
it('handles end meeting message correctly', async () => {
|
3630
|
+
});
|
3631
|
+
it('handles heartbeat messages correctly', async () => {
|
3632
|
+
});
|
3633
|
+
|
3634
|
+
});
|
3142
3635
|
});
|
3143
3636
|
});
|