@webex/plugin-meetings 3.12.0-next.10 → 3.12.0-next.12
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/dist/aiEnableRequest/index.js +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/controls-options-manager/constants.js +11 -1
- package/dist/controls-options-manager/constants.js.map +1 -1
- package/dist/controls-options-manager/index.js +23 -21
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/util.js +91 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +36 -20
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +38 -14
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/util.js +1 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/types/controls-options-manager/constants.d.ts +6 -1
- package/dist/types/hashTree/hashTreeParser.d.ts +12 -2
- package/dist/types/locus-info/index.d.ts +8 -3
- package/dist/webinar/index.js +1 -1
- package/package.json +13 -13
- package/src/controls-options-manager/constants.ts +14 -1
- package/src/controls-options-manager/index.ts +26 -19
- package/src/controls-options-manager/util.ts +81 -1
- package/src/hashTree/hashTreeParser.ts +39 -22
- package/src/locus-info/index.ts +48 -24
- package/src/meeting/util.ts +1 -0
- package/test/unit/spec/controls-options-manager/index.js +114 -6
- package/test/unit/spec/controls-options-manager/util.js +165 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +59 -32
- package/test/unit/spec/locus-info/index.js +47 -22
- package/test/unit/spec/meeting/utils.js +4 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ControlsOptionsManager from '@webex/plugin-meetings/src/controls-options-manager';
|
|
2
2
|
import Util from '@webex/plugin-meetings/src/controls-options-manager/util';
|
|
3
|
+
import ParameterError from '@webex/plugin-meetings/src/common/errors/parameter';
|
|
3
4
|
import sinon from 'sinon';
|
|
4
5
|
import {assert} from '@webex/test-helper-chai';
|
|
5
6
|
import { HTTP_VERBS } from '@webex/plugin-meetings/src/constants';
|
|
@@ -76,6 +77,19 @@ describe('plugin-meetings', () => {
|
|
|
76
77
|
|
|
77
78
|
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
78
79
|
});
|
|
80
|
+
|
|
81
|
+
it('should send setMuteOnEntry to locusUrl without authorizingLocusUrl when in breakout', () => {
|
|
82
|
+
manager.setDisplayHints(['ENABLE_MUTE_ON_ENTRY']);
|
|
83
|
+
manager.mainLocusUrl = 'test/main';
|
|
84
|
+
|
|
85
|
+
const result = manager.setMuteOnEntry(true);
|
|
86
|
+
|
|
87
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
88
|
+
body: { muteOnEntry: { enabled: true } },
|
|
89
|
+
method: HTTP_VERBS.PATCH});
|
|
90
|
+
|
|
91
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
92
|
+
});
|
|
79
93
|
});
|
|
80
94
|
|
|
81
95
|
describe('setDisallowUnmute', () => {
|
|
@@ -118,6 +132,19 @@ describe('plugin-meetings', () => {
|
|
|
118
132
|
|
|
119
133
|
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
120
134
|
});
|
|
135
|
+
|
|
136
|
+
it('should send setDisallowUnmute to locusUrl without authorizingLocusUrl when in breakout', () => {
|
|
137
|
+
manager.setDisplayHints(['ENABLE_HARD_MUTE']);
|
|
138
|
+
manager.mainLocusUrl = 'test/main';
|
|
139
|
+
|
|
140
|
+
const result = manager.setDisallowUnmute(true);
|
|
141
|
+
|
|
142
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
143
|
+
body: { disallowUnmute: { enabled: true } },
|
|
144
|
+
method: HTTP_VERBS.PATCH});
|
|
145
|
+
|
|
146
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
147
|
+
});
|
|
121
148
|
});
|
|
122
149
|
});
|
|
123
150
|
|
|
@@ -138,6 +165,18 @@ describe('plugin-meetings', () => {
|
|
|
138
165
|
});
|
|
139
166
|
});
|
|
140
167
|
|
|
168
|
+
it('should reject with ParameterError when locusUrl is not set', () => {
|
|
169
|
+
const noLocusManager = new ControlsOptionsManager(request);
|
|
170
|
+
|
|
171
|
+
const result = noLocusManager.update({scope: 'audio', properties: {muted: true}});
|
|
172
|
+
|
|
173
|
+
assert.notCalled(request.request);
|
|
174
|
+
return assert.isRejected(result).then((err) => {
|
|
175
|
+
assert.instanceOf(err, ParameterError);
|
|
176
|
+
assert.match(err.message, /locusUrl.*must be defined/);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
141
180
|
it('should throw an error if the scope is not supported', () => {
|
|
142
181
|
const scope = 'invalid';
|
|
143
182
|
|
|
@@ -203,7 +242,7 @@ describe('plugin-meetings', () => {
|
|
|
203
242
|
});
|
|
204
243
|
});
|
|
205
244
|
|
|
206
|
-
it('should
|
|
245
|
+
it('should send audio controls to locusUrl without authorizingLocusUrl and non-audio to mainLocusUrl with authorizingLocusUrl when in breakout', () => {
|
|
207
246
|
const restorable = Util.canUpdate;
|
|
208
247
|
Util.canUpdate = sinon.stub().returns(true);
|
|
209
248
|
manager.mainLocusUrl = 'test/main';
|
|
@@ -213,15 +252,16 @@ describe('plugin-meetings', () => {
|
|
|
213
252
|
|
|
214
253
|
return manager.update(audio, reactions)
|
|
215
254
|
.then(() => {
|
|
255
|
+
// Audio controls go directly to current locusUrl (no cross-locus authorization)
|
|
216
256
|
assert.calledWith(request.request, {
|
|
217
|
-
uri: 'test/
|
|
257
|
+
uri: 'test/id/controls',
|
|
218
258
|
body: {
|
|
219
259
|
audio: audio.properties,
|
|
220
|
-
authorizingLocusUrl: 'test/id'
|
|
221
260
|
},
|
|
222
261
|
method: HTTP_VERBS.PATCH,
|
|
223
262
|
});
|
|
224
263
|
|
|
264
|
+
// Non-audio controls go to mainLocusUrl with authorizingLocusUrl
|
|
225
265
|
assert.calledWith(request.request, {
|
|
226
266
|
uri: 'test/main/controls',
|
|
227
267
|
body: {
|
|
@@ -234,6 +274,49 @@ describe('plugin-meetings', () => {
|
|
|
234
274
|
Util.canUpdate = restorable;
|
|
235
275
|
});
|
|
236
276
|
});
|
|
277
|
+
|
|
278
|
+
it('should send audio controls to locusUrl without authorizingLocusUrl when in breakout', () => {
|
|
279
|
+
const restorable = Util.canUpdate;
|
|
280
|
+
Util.canUpdate = sinon.stub().returns(true);
|
|
281
|
+
manager.mainLocusUrl = 'test/main';
|
|
282
|
+
|
|
283
|
+
const audio = {scope: 'audio', properties: {muted: true, disallowUnmute: false}};
|
|
284
|
+
|
|
285
|
+
return manager.update(audio)
|
|
286
|
+
.then(() => {
|
|
287
|
+
assert.calledWith(request.request, {
|
|
288
|
+
uri: 'test/id/controls',
|
|
289
|
+
body: {
|
|
290
|
+
audio: audio.properties,
|
|
291
|
+
},
|
|
292
|
+
method: HTTP_VERBS.PATCH,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
Util.canUpdate = restorable;
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('should send non-audio controls to mainLocusUrl with authorizingLocusUrl when in breakout', () => {
|
|
300
|
+
const restorable = Util.canUpdate;
|
|
301
|
+
Util.canUpdate = sinon.stub().returns(true);
|
|
302
|
+
manager.mainLocusUrl = 'test/main';
|
|
303
|
+
|
|
304
|
+
const reactions = {scope: 'reactions', properties: {enabled: true}};
|
|
305
|
+
|
|
306
|
+
return manager.update(reactions)
|
|
307
|
+
.then(() => {
|
|
308
|
+
assert.calledWith(request.request, {
|
|
309
|
+
uri: 'test/main/controls',
|
|
310
|
+
body: {
|
|
311
|
+
reactions: reactions.properties,
|
|
312
|
+
authorizingLocusUrl: 'test/id',
|
|
313
|
+
},
|
|
314
|
+
method: HTTP_VERBS.PATCH,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
Util.canUpdate = restorable;
|
|
318
|
+
});
|
|
319
|
+
});
|
|
237
320
|
});
|
|
238
321
|
|
|
239
322
|
describe('Mute/Unmute All', () => {
|
|
@@ -252,6 +335,18 @@ describe('plugin-meetings', () => {
|
|
|
252
335
|
})
|
|
253
336
|
});
|
|
254
337
|
|
|
338
|
+
it('should reject with ParameterError when locusUrl is not set', () => {
|
|
339
|
+
const noLocusManager = new ControlsOptionsManager(request);
|
|
340
|
+
|
|
341
|
+
const result = noLocusManager.setMuteAll(true, true, true);
|
|
342
|
+
|
|
343
|
+
assert.notCalled(request.request);
|
|
344
|
+
return assert.isRejected(result).then((err) => {
|
|
345
|
+
assert.instanceOf(err, ParameterError);
|
|
346
|
+
assert.match(err.message, /locusUrl.*must be defined/);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
255
350
|
it('rejects when correct display hint is not present mutedEnabled=false', () => {
|
|
256
351
|
const result = manager.setMuteAll(false, false, false);
|
|
257
352
|
|
|
@@ -340,14 +435,27 @@ describe('plugin-meetings', () => {
|
|
|
340
435
|
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
341
436
|
});
|
|
342
437
|
|
|
343
|
-
it('
|
|
438
|
+
it('should send setMuteAll to locusUrl without authorizingLocusUrl when in breakout', () => {
|
|
344
439
|
manager.setDisplayHints(['MUTE_ALL', 'DISABLE_HARD_MUTE', 'DISABLE_MUTE_ON_ENTRY']);
|
|
345
440
|
manager.mainLocusUrl = `test/main`;
|
|
346
441
|
|
|
347
442
|
const result = manager.setMuteAll(true, true, true, ['attendee']);
|
|
348
443
|
|
|
349
|
-
assert.calledWith(request.request, { uri: 'test/
|
|
350
|
-
body: { audio: { muted: true, disallowUnmute: true, muteOnEntry: true, roles: ['attendee'] }
|
|
444
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
445
|
+
body: { audio: { muted: true, disallowUnmute: true, muteOnEntry: true, roles: ['attendee'] } },
|
|
446
|
+
method: HTTP_VERBS.PATCH});
|
|
447
|
+
|
|
448
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should send setMuteAll with PANELIST role to locusUrl without authorizingLocusUrl when in breakout', () => {
|
|
452
|
+
manager.setDisplayHints(['MUTE_ALL', 'ENABLE_HARD_MUTE', 'ENABLE_MUTE_ON_ENTRY']);
|
|
453
|
+
manager.mainLocusUrl = `test/main`;
|
|
454
|
+
|
|
455
|
+
const result = manager.setMuteAll(true, true, true, ['PANELIST']);
|
|
456
|
+
|
|
457
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
458
|
+
body: { audio: { muted: true, disallowUnmute: true, muteOnEntry: true, roles: ['PANELIST'] } },
|
|
351
459
|
method: HTTP_VERBS.PATCH});
|
|
352
460
|
|
|
353
461
|
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
@@ -799,6 +799,171 @@ describe('plugin-meetings', () => {
|
|
|
799
799
|
);
|
|
800
800
|
});
|
|
801
801
|
});
|
|
802
|
+
|
|
803
|
+
describe('isAudioControl()', () => {
|
|
804
|
+
it('should return true when all body keys are audio control keys', () => {
|
|
805
|
+
assert.isTrue(ControlsOptionsUtil.isAudioControl({audio: {muted: true}}));
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
it('should return true when body has muteOnEntry key', () => {
|
|
809
|
+
assert.isTrue(ControlsOptionsUtil.isAudioControl({muteOnEntry: {enabled: true}}));
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
it('should return true when body has disallowUnmute key', () => {
|
|
813
|
+
assert.isTrue(ControlsOptionsUtil.isAudioControl({disallowUnmute: {enabled: true}}));
|
|
814
|
+
});
|
|
815
|
+
|
|
816
|
+
it('should return true when body has multiple audio control keys', () => {
|
|
817
|
+
assert.isTrue(ControlsOptionsUtil.isAudioControl({audio: {muted: true}, muteOnEntry: {enabled: true}, disallowUnmute: {enabled: true}}));
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
it('should return false when body has a non-audio control key', () => {
|
|
821
|
+
assert.isFalse(ControlsOptionsUtil.isAudioControl({raiseHand: {enabled: true}}));
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
it('should return false when body has a mix of audio and non-audio keys', () => {
|
|
825
|
+
assert.isFalse(ControlsOptionsUtil.isAudioControl({audio: {muted: true}, raiseHand: {enabled: true}}));
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
it('should return true for an empty body', () => {
|
|
829
|
+
assert.isTrue(ControlsOptionsUtil.isAudioControl({}));
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
describe('isBreakoutLocusUrl()', () => {
|
|
834
|
+
it('should return true when mainLocusUrl differs from locusUrl', () => {
|
|
835
|
+
assert.isTrue(ControlsOptionsUtil.isBreakoutLocusUrl('locus/breakout', 'locus/main'));
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
it('should return false when mainLocusUrl equals locusUrl', () => {
|
|
839
|
+
assert.isFalse(ControlsOptionsUtil.isBreakoutLocusUrl('locus/main', 'locus/main'));
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it('should return false when mainLocusUrl is undefined', () => {
|
|
843
|
+
assert.isFalse(ControlsOptionsUtil.isBreakoutLocusUrl('locus/breakout', undefined));
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
it('should return false when mainLocusUrl is null', () => {
|
|
847
|
+
assert.isFalse(ControlsOptionsUtil.isBreakoutLocusUrl('locus/breakout', null));
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
it('should return false when mainLocusUrl is empty string', () => {
|
|
851
|
+
assert.isFalse(ControlsOptionsUtil.isBreakoutLocusUrl('locus/breakout', ''));
|
|
852
|
+
});
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
describe('getControlsRequestParams()', () => {
|
|
856
|
+
const locusUrl = 'locus/breakout';
|
|
857
|
+
const mainLocusUrl = 'locus/main';
|
|
858
|
+
|
|
859
|
+
it('should return full request params targeting locusUrl when not in a breakout', () => {
|
|
860
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
861
|
+
body: {raiseHand: {enabled: true}},
|
|
862
|
+
locusUrl: 'locus/main',
|
|
863
|
+
mainLocusUrl: 'locus/main',
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
assert.equal(result.uri, 'locus/main/controls');
|
|
867
|
+
assert.deepEqual(result.body, {raiseHand: {enabled: true}});
|
|
868
|
+
assert.equal(result.method, 'PATCH');
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
it('should return mainLocusUrl with authorizingLocusUrl in body for non-audio controls in a breakout', () => {
|
|
872
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
873
|
+
body: {raiseHand: {enabled: true}},
|
|
874
|
+
locusUrl,
|
|
875
|
+
mainLocusUrl,
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
assert.equal(result.uri, 'locus/main/controls');
|
|
879
|
+
assert.deepEqual(result.body, {raiseHand: {enabled: true}, authorizingLocusUrl: locusUrl});
|
|
880
|
+
assert.equal(result.method, 'PATCH');
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
it('should return locusUrl without authorizingLocusUrl for audio controls in a breakout', () => {
|
|
884
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
885
|
+
body: {audio: {muted: true}},
|
|
886
|
+
locusUrl,
|
|
887
|
+
mainLocusUrl,
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
assert.equal(result.uri, 'locus/breakout/controls');
|
|
891
|
+
assert.deepEqual(result.body, {audio: {muted: true}});
|
|
892
|
+
assert.equal(result.method, 'PATCH');
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
it('should return locusUrl without authorizingLocusUrl for muteOnEntry in a breakout', () => {
|
|
896
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
897
|
+
body: {muteOnEntry: {enabled: true}},
|
|
898
|
+
locusUrl,
|
|
899
|
+
mainLocusUrl,
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
assert.equal(result.uri, 'locus/breakout/controls');
|
|
903
|
+
assert.deepEqual(result.body, {muteOnEntry: {enabled: true}});
|
|
904
|
+
assert.equal(result.method, 'PATCH');
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
it('should return locusUrl without authorizingLocusUrl for disallowUnmute in a breakout', () => {
|
|
908
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
909
|
+
body: {disallowUnmute: {enabled: true}},
|
|
910
|
+
locusUrl,
|
|
911
|
+
mainLocusUrl,
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
assert.equal(result.uri, 'locus/breakout/controls');
|
|
915
|
+
assert.deepEqual(result.body, {disallowUnmute: {enabled: true}});
|
|
916
|
+
assert.equal(result.method, 'PATCH');
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
it('should return locusUrl when mainLocusUrl is undefined', () => {
|
|
920
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
921
|
+
body: {raiseHand: {enabled: true}},
|
|
922
|
+
locusUrl,
|
|
923
|
+
mainLocusUrl: undefined,
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
assert.equal(result.uri, 'locus/breakout/controls');
|
|
927
|
+
assert.deepEqual(result.body, {raiseHand: {enabled: true}});
|
|
928
|
+
assert.equal(result.method, 'PATCH');
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
it('should return locusUrl when mainLocusUrl is null', () => {
|
|
932
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
933
|
+
body: {raiseHand: {enabled: true}},
|
|
934
|
+
locusUrl,
|
|
935
|
+
mainLocusUrl: null,
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
assert.equal(result.uri, 'locus/breakout/controls');
|
|
939
|
+
assert.deepEqual(result.body, {raiseHand: {enabled: true}});
|
|
940
|
+
assert.equal(result.method, 'PATCH');
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
it('should return locusUrl when mainLocusUrl is empty string', () => {
|
|
944
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
945
|
+
body: {raiseHand: {enabled: true}},
|
|
946
|
+
locusUrl,
|
|
947
|
+
mainLocusUrl: '',
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
assert.equal(result.uri, 'locus/breakout/controls');
|
|
951
|
+
assert.deepEqual(result.body, {raiseHand: {enabled: true}});
|
|
952
|
+
assert.equal(result.method, 'PATCH');
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
it('should return locusUrl for audio controls when not in a breakout', () => {
|
|
956
|
+
const result = ControlsOptionsUtil.getControlsRequestParams({
|
|
957
|
+
body: {audio: {muted: true}},
|
|
958
|
+
locusUrl: 'locus/main',
|
|
959
|
+
mainLocusUrl: 'locus/main',
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
assert.equal(result.uri, 'locus/main/controls');
|
|
963
|
+
assert.deepEqual(result.body, {audio: {muted: true}});
|
|
964
|
+
assert.equal(result.method, 'PATCH');
|
|
965
|
+
});
|
|
966
|
+
});
|
|
802
967
|
});
|
|
803
968
|
});
|
|
804
969
|
});
|
|
@@ -553,8 +553,7 @@ describe('HashTreeParser', () => {
|
|
|
553
553
|
);
|
|
554
554
|
|
|
555
555
|
// Verify callback was called with OBJECTS_UPDATED and correct updatedObjects list
|
|
556
|
-
|
|
557
|
-
assert.calledWith(callback, LocusInfoUpdateType.OBJECTS_UPDATED, {
|
|
556
|
+
assert.calledWith(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
558
557
|
updatedObjects: [
|
|
559
558
|
{
|
|
560
559
|
htMeta: {
|
|
@@ -824,7 +823,7 @@ describe('HashTreeParser', () => {
|
|
|
824
823
|
expect(parser.dataSets.self.version).to.equal(2100);
|
|
825
824
|
expect(parser.dataSets['atd-unmuted'].version).to.equal(3100);
|
|
826
825
|
|
|
827
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
826
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
828
827
|
updatedObjects: [
|
|
829
828
|
{
|
|
830
829
|
htMeta: {
|
|
@@ -955,7 +954,7 @@ describe('HashTreeParser', () => {
|
|
|
955
954
|
{type: 'ControlEntry', id: 10101, version: 100}
|
|
956
955
|
]);
|
|
957
956
|
|
|
958
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
957
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
959
958
|
updatedObjects: [
|
|
960
959
|
{
|
|
961
960
|
htMeta: {
|
|
@@ -1045,7 +1044,7 @@ describe('HashTreeParser', () => {
|
|
|
1045
1044
|
assert.calledOnceWithExactly(mainPutItemsSpy, [{type: 'locus', id: 0, version: 201}]);
|
|
1046
1045
|
|
|
1047
1046
|
// Verify callback was called only for known dataset
|
|
1048
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1047
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1049
1048
|
updatedObjects: [
|
|
1050
1049
|
{
|
|
1051
1050
|
htMeta: {
|
|
@@ -1145,7 +1144,7 @@ describe('HashTreeParser', () => {
|
|
|
1145
1144
|
assert.calledOnceWithExactly(selfPutItemSpy, {type: 'metadata', id: 5, version: 51});
|
|
1146
1145
|
|
|
1147
1146
|
// Verify callback was called with metadata object and removed dataset objects
|
|
1148
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1147
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1149
1148
|
updatedObjects: [
|
|
1150
1149
|
// updated metadata object:
|
|
1151
1150
|
{
|
|
@@ -1306,7 +1305,7 @@ describe('HashTreeParser', () => {
|
|
|
1306
1305
|
assert.notCalled(atdUnmutedPutItemsSpy);
|
|
1307
1306
|
|
|
1308
1307
|
// Verify callback was called with the updated object
|
|
1309
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1308
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1310
1309
|
updatedObjects: [
|
|
1311
1310
|
{
|
|
1312
1311
|
htMeta: {
|
|
@@ -1534,7 +1533,7 @@ describe('HashTreeParser', () => {
|
|
|
1534
1533
|
]);
|
|
1535
1534
|
|
|
1536
1535
|
// Verify callback was called with OBJECTS_UPDATED and all updated objects
|
|
1537
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1536
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1538
1537
|
updatedObjects: [
|
|
1539
1538
|
{
|
|
1540
1539
|
htMeta: {
|
|
@@ -1599,9 +1598,7 @@ describe('HashTreeParser', () => {
|
|
|
1599
1598
|
parser.handleMessage(sentinelMessage, 'sentinel message');
|
|
1600
1599
|
|
|
1601
1600
|
// Verify callback was called with MEETING_ENDED
|
|
1602
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1603
|
-
updatedObjects: undefined,
|
|
1604
|
-
});
|
|
1601
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1605
1602
|
|
|
1606
1603
|
// Verify that all timers were stopped
|
|
1607
1604
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -1623,9 +1620,7 @@ describe('HashTreeParser', () => {
|
|
|
1623
1620
|
parser.handleMessage(sentinelMessage, 'sentinel message');
|
|
1624
1621
|
|
|
1625
1622
|
// Verify callback was called with MEETING_ENDED
|
|
1626
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1627
|
-
updatedObjects: undefined,
|
|
1628
|
-
});
|
|
1623
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1629
1624
|
|
|
1630
1625
|
// Verify that all timers were stopped
|
|
1631
1626
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -1721,7 +1716,7 @@ describe('HashTreeParser', () => {
|
|
|
1721
1716
|
);
|
|
1722
1717
|
|
|
1723
1718
|
// Verify that callback was called with synced objects
|
|
1724
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1719
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1725
1720
|
updatedObjects: [
|
|
1726
1721
|
{
|
|
1727
1722
|
htMeta: {
|
|
@@ -1783,9 +1778,7 @@ describe('HashTreeParser', () => {
|
|
|
1783
1778
|
await clock.tickAsync(1000);
|
|
1784
1779
|
|
|
1785
1780
|
// Verify callback was called with MEETING_ENDED
|
|
1786
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1787
|
-
updatedObjects: undefined,
|
|
1788
|
-
});
|
|
1781
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1789
1782
|
|
|
1790
1783
|
// Verify all timers are stopped
|
|
1791
1784
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -1848,9 +1841,7 @@ describe('HashTreeParser', () => {
|
|
|
1848
1841
|
await clock.tickAsync(1000);
|
|
1849
1842
|
|
|
1850
1843
|
// Verify callback was called with MEETING_ENDED
|
|
1851
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1852
|
-
updatedObjects: undefined,
|
|
1853
|
-
});
|
|
1844
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1854
1845
|
|
|
1855
1846
|
// Verify all timers are stopped
|
|
1856
1847
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -2088,7 +2079,7 @@ describe('HashTreeParser', () => {
|
|
|
2088
2079
|
assert.equal(parser.dataSets.attendees.hashTree.numLeaves, 8);
|
|
2089
2080
|
|
|
2090
2081
|
// Verify callback was called with the metadata update (appears twice - processed once for visible dataset changes, once in main loop)
|
|
2091
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2082
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2092
2083
|
updatedObjects: [
|
|
2093
2084
|
{
|
|
2094
2085
|
htMeta: {
|
|
@@ -2366,9 +2357,7 @@ describe('HashTreeParser', () => {
|
|
|
2366
2357
|
await clock.tickAsync(0);
|
|
2367
2358
|
|
|
2368
2359
|
// Verify callback was called with MEETING_ENDED
|
|
2369
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
2370
|
-
updatedObjects: undefined,
|
|
2371
|
-
});
|
|
2360
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
2372
2361
|
});
|
|
2373
2362
|
|
|
2374
2363
|
it('handles removal of visible data set', async () => {
|
|
@@ -2431,7 +2420,7 @@ describe('HashTreeParser', () => {
|
|
|
2431
2420
|
assert.isUndefined(parser.dataSets['atd-unmuted'].timer);
|
|
2432
2421
|
|
|
2433
2422
|
// Verify callback was called with the metadata update and the removed objects (metadata appears twice - processed once for dataset changes, once in main loop)
|
|
2434
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2423
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2435
2424
|
updatedObjects: [
|
|
2436
2425
|
{
|
|
2437
2426
|
htMeta: {
|
|
@@ -3050,7 +3039,7 @@ describe('HashTreeParser', () => {
|
|
|
3050
3039
|
parser.handleMessage(updateMessage, 'update with newer version');
|
|
3051
3040
|
|
|
3052
3041
|
// Callback should be called with the update
|
|
3053
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3042
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3054
3043
|
updatedObjects: [
|
|
3055
3044
|
{
|
|
3056
3045
|
htMeta: {
|
|
@@ -3121,7 +3110,7 @@ describe('HashTreeParser', () => {
|
|
|
3121
3110
|
parser.handleMessage(removalMessage, 'removal of non-existent object');
|
|
3122
3111
|
|
|
3123
3112
|
// Callback should be called with the removal
|
|
3124
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3113
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3125
3114
|
updatedObjects: [
|
|
3126
3115
|
{
|
|
3127
3116
|
htMeta: {
|
|
@@ -3256,7 +3245,7 @@ describe('HashTreeParser', () => {
|
|
|
3256
3245
|
parser.handleMessage(mixedMessage, 'mixed updates');
|
|
3257
3246
|
|
|
3258
3247
|
// Callback should be called with only the valid updates (participant 1 v110 and participant 3 v10)
|
|
3259
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3248
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3260
3249
|
updatedObjects: [
|
|
3261
3250
|
{
|
|
3262
3251
|
htMeta: {
|
|
@@ -3434,9 +3423,7 @@ describe('HashTreeParser', () => {
|
|
|
3434
3423
|
parser.handleMessage(sentinelMessage as any, 'sentinel message');
|
|
3435
3424
|
|
|
3436
3425
|
// Callback should be called with MEETING_ENDED
|
|
3437
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
3438
|
-
updatedObjects: undefined,
|
|
3439
|
-
});
|
|
3426
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
3440
3427
|
});
|
|
3441
3428
|
});
|
|
3442
3429
|
|
|
@@ -3795,4 +3782,44 @@ describe('HashTreeParser', () => {
|
|
|
3795
3782
|
assert.notCalled(callback);
|
|
3796
3783
|
});
|
|
3797
3784
|
});
|
|
3785
|
+
|
|
3786
|
+
describe('#cleanUp', () => {
|
|
3787
|
+
it('should stop the parser, clear all timers and clear all dataSets', () => {
|
|
3788
|
+
const parser = createHashTreeParser();
|
|
3789
|
+
|
|
3790
|
+
// Send a message to set up sync timers via runSyncAlgorithm
|
|
3791
|
+
const message = {
|
|
3792
|
+
dataSets: [
|
|
3793
|
+
{
|
|
3794
|
+
...createDataSet('main', 16, 1100),
|
|
3795
|
+
root: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1',
|
|
3796
|
+
},
|
|
3797
|
+
],
|
|
3798
|
+
visibleDataSetsUrl,
|
|
3799
|
+
locusUrl,
|
|
3800
|
+
heartbeatIntervalMs: 5000,
|
|
3801
|
+
locusStateElements: [
|
|
3802
|
+
{
|
|
3803
|
+
htMeta: {
|
|
3804
|
+
elementId: {type: 'locus' as const, id: 0, version: 201},
|
|
3805
|
+
dataSetNames: ['main'],
|
|
3806
|
+
},
|
|
3807
|
+
data: {someData: 'value'},
|
|
3808
|
+
},
|
|
3809
|
+
],
|
|
3810
|
+
};
|
|
3811
|
+
|
|
3812
|
+
parser.handleMessage(message, 'setup timers');
|
|
3813
|
+
|
|
3814
|
+
// Verify timers were set by handleMessage
|
|
3815
|
+
expect(parser.dataSets.main.timer).to.not.be.undefined;
|
|
3816
|
+
expect(parser.dataSets.main.heartbeatWatchdogTimer).to.not.be.undefined;
|
|
3817
|
+
|
|
3818
|
+
parser.cleanUp();
|
|
3819
|
+
|
|
3820
|
+
expect(parser.state).to.equal('stopped');
|
|
3821
|
+
expect(parser.visibleDataSets).to.deep.equal([]);
|
|
3822
|
+
expect(parser.dataSets).to.deep.equal({});
|
|
3823
|
+
});
|
|
3824
|
+
});
|
|
3798
3825
|
});
|