@webex/plugin-meetings 3.11.0 → 3.12.0-next.2
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 +184 -0
- package/dist/aiEnableRequest/index.js.map +1 -0
- package/dist/aiEnableRequest/utils.js +36 -0
- package/dist/aiEnableRequest/utils.js.map +1 -0
- package/dist/annotation/index.js +14 -5
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/config.js +7 -2
- package/dist/config.js.map +1 -1
- package/dist/constants.js +28 -6
- package/dist/constants.js.map +1 -1
- package/dist/hashTree/constants.js +3 -1
- package/dist/hashTree/constants.js.map +1 -1
- package/dist/hashTree/hashTree.js +18 -0
- package/dist/hashTree/hashTree.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +850 -410
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/types.js +4 -2
- package/dist/hashTree/types.js.map +1 -1
- package/dist/hashTree/utils.js +10 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/constant.js +12 -0
- package/dist/interceptors/constant.js.map +1 -0
- package/dist/interceptors/dataChannelAuthToken.js +290 -0
- package/dist/interceptors/dataChannelAuthToken.js.map +1 -0
- package/dist/interceptors/index.js +7 -0
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/utils.js +27 -0
- package/dist/interceptors/utils.js.map +1 -0
- package/dist/interpretation/index.js +2 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +5 -3
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +522 -131
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +1 -0
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +57 -1
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +4 -2
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +7 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1173 -877
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +50 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +133 -3
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +117 -48
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +10 -0
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +9 -60
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +11 -0
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/index.js +18 -10
- package/dist/reachability/index.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +0 -1
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/types/aiEnableRequest/index.d.ts +5 -0
- package/dist/types/aiEnableRequest/utils.d.ts +2 -0
- package/dist/types/config.d.ts +4 -0
- package/dist/types/constants.d.ts +23 -1
- package/dist/types/hashTree/constants.d.ts +1 -0
- package/dist/types/hashTree/hashTree.d.ts +7 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +122 -14
- package/dist/types/hashTree/types.d.ts +3 -0
- package/dist/types/hashTree/utils.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/interceptors/constant.d.ts +5 -0
- package/dist/types/interceptors/dataChannelAuthToken.d.ts +43 -0
- package/dist/types/interceptors/index.d.ts +2 -1
- package/dist/types/interceptors/utils.d.ts +1 -0
- package/dist/types/locus-info/index.d.ts +60 -8
- package/dist/types/locus-info/types.d.ts +7 -0
- package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
- package/dist/types/media/properties.d.ts +2 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +61 -7
- package/dist/types/meeting/request.d.ts +16 -1
- package/dist/types/meeting/request.type.d.ts +5 -0
- package/dist/types/meeting/util.d.ts +31 -0
- package/dist/types/meetings/index.d.ts +4 -2
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +5 -0
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +0 -23
- package/dist/types/reactions/reactions.type.d.ts +1 -0
- package/dist/types/webinar/utils.d.ts +6 -0
- package/dist/webinar/index.js +291 -91
- package/dist/webinar/index.js.map +1 -1
- package/dist/webinar/utils.js +25 -0
- package/dist/webinar/utils.js.map +1 -0
- package/package.json +24 -23
- package/src/aiEnableRequest/README.md +84 -0
- package/src/aiEnableRequest/index.ts +170 -0
- package/src/aiEnableRequest/utils.ts +25 -0
- package/src/annotation/index.ts +27 -7
- package/src/config.ts +4 -0
- package/src/constants.ts +29 -1
- package/src/hashTree/constants.ts +1 -0
- package/src/hashTree/hashTree.ts +17 -0
- package/src/hashTree/hashTreeParser.ts +745 -252
- package/src/hashTree/types.ts +4 -0
- package/src/hashTree/utils.ts +9 -0
- package/src/index.ts +8 -1
- package/src/interceptors/constant.ts +6 -0
- package/src/interceptors/dataChannelAuthToken.ts +170 -0
- package/src/interceptors/index.ts +2 -1
- package/src/interceptors/utils.ts +16 -0
- package/src/interpretation/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +579 -113
- package/src/locus-info/selfUtils.ts +1 -0
- package/src/locus-info/types.ts +8 -0
- package/src/media/MediaConnectionAwaiter.ts +41 -1
- package/src/media/properties.ts +3 -1
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +291 -76
- package/src/meeting/request.ts +42 -0
- package/src/meeting/request.type.ts +6 -0
- package/src/meeting/util.ts +160 -2
- package/src/meetings/index.ts +157 -44
- package/src/member/index.ts +10 -0
- package/src/member/util.ts +12 -0
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +4 -54
- package/src/multistream/remoteMediaManager.ts +13 -0
- package/src/reachability/index.ts +9 -0
- package/src/reactions/reactions.type.ts +1 -0
- package/src/reconnection-manager/index.ts +0 -1
- package/src/webinar/index.ts +191 -6
- package/src/webinar/utils.ts +16 -0
- package/test/unit/spec/aiEnableRequest/index.ts +981 -0
- package/test/unit/spec/aiEnableRequest/utils.ts +130 -0
- package/test/unit/spec/annotation/index.ts +69 -7
- package/test/unit/spec/hashTree/hashTree.ts +66 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +2225 -189
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +210 -0
- package/test/unit/spec/interceptors/utils.ts +75 -0
- package/test/unit/spec/locus-info/controlsUtils.js +29 -0
- package/test/unit/spec/locus-info/index.js +1134 -55
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
- package/test/unit/spec/media/properties.ts +12 -3
- package/test/unit/spec/meeting/in-meeting-actions.ts +8 -2
- package/test/unit/spec/meeting/index.js +829 -115
- package/test/unit/spec/meeting/request.js +70 -0
- package/test/unit/spec/meeting/utils.js +438 -26
- package/test/unit/spec/meetings/index.js +653 -32
- package/test/unit/spec/member/index.js +28 -4
- package/test/unit/spec/member/util.js +65 -27
- package/test/unit/spec/multistream/mediaRequestManager.ts +2 -85
- package/test/unit/spec/multistream/remoteMediaManager.ts +30 -0
- package/test/unit/spec/reachability/index.ts +23 -0
- package/test/unit/spec/reconnection-manager/index.js +4 -8
- package/test/unit/spec/webinar/index.ts +474 -37
- package/test/unit/spec/webinar/utils.ts +39 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
import {getAIEnablementApprover} from '../../../../src/aiEnableRequest/utils';
|
|
3
|
+
import {Meeting} from '../../../../src';
|
|
4
|
+
|
|
5
|
+
describe('AI Enable Request Utils', () => {
|
|
6
|
+
describe('#getAIEnablementApprover', () => {
|
|
7
|
+
const createMember = (id, roles, canApproveAIEnablement) => ({
|
|
8
|
+
id,
|
|
9
|
+
roles,
|
|
10
|
+
canApproveAIEnablement,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const createMeeting = (members) =>
|
|
14
|
+
({
|
|
15
|
+
members: {
|
|
16
|
+
membersCollection: {
|
|
17
|
+
members: members.reduce((acc, member) => {
|
|
18
|
+
acc[member.id] = member;
|
|
19
|
+
return acc;
|
|
20
|
+
}, {}),
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
} as Meeting);
|
|
24
|
+
|
|
25
|
+
it('should return host id when host has moderator role and canApproveAIEnablement', () => {
|
|
26
|
+
const host = createMember('host-123', {moderator: true, cohost: false}, true);
|
|
27
|
+
const member1 = createMember('member-456', {moderator: false, cohost: false}, false);
|
|
28
|
+
const meeting = createMeeting([host, member1]);
|
|
29
|
+
|
|
30
|
+
const result = getAIEnablementApprover(meeting);
|
|
31
|
+
|
|
32
|
+
assert.equal(result, 'host-123');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return null when host exists but does not have canApproveAIEnablement', () => {
|
|
36
|
+
const host = createMember('host-123', {moderator: true, cohost: false}, false);
|
|
37
|
+
const member1 = createMember('member-456', {moderator: false, cohost: false}, false);
|
|
38
|
+
const meeting = createMeeting([host, member1]);
|
|
39
|
+
|
|
40
|
+
const result = getAIEnablementApprover(meeting);
|
|
41
|
+
|
|
42
|
+
assert.isNull(result);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return first cohost id (alphabetically) when host does not have capability but cohosts do', () => {
|
|
46
|
+
const host = createMember('host-123', {moderator: true, cohost: false}, false);
|
|
47
|
+
const cohost1 = createMember('cohost-zzz', {moderator: false, cohost: true}, true);
|
|
48
|
+
const cohost2 = createMember('cohost-aaa', {moderator: false, cohost: true}, true);
|
|
49
|
+
const cohost3 = createMember('cohost-mmm', {moderator: false, cohost: true}, true);
|
|
50
|
+
const meeting = createMeeting([host, cohost1, cohost2, cohost3]);
|
|
51
|
+
|
|
52
|
+
const result = getAIEnablementApprover(meeting);
|
|
53
|
+
|
|
54
|
+
assert.equal(result, 'cohost-aaa');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should return null when no host exists and no cohosts have capability', () => {
|
|
58
|
+
const member1 = createMember('member-123', {moderator: false, cohost: false}, false);
|
|
59
|
+
const member2 = createMember('member-456', {moderator: false, cohost: false}, false);
|
|
60
|
+
const meeting = createMeeting([member1, member2]);
|
|
61
|
+
|
|
62
|
+
const result = getAIEnablementApprover(meeting);
|
|
63
|
+
|
|
64
|
+
assert.isNull(result);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should return null when cohosts exist but none have canApproveAIEnablement', () => {
|
|
68
|
+
const host = createMember('host-123', {moderator: true, cohost: false}, false);
|
|
69
|
+
const cohost1 = createMember('cohost-111', {moderator: false, cohost: true}, false);
|
|
70
|
+
const cohost2 = createMember('cohost-222', {moderator: false, cohost: true}, false);
|
|
71
|
+
const meeting = createMeeting([host, cohost1, cohost2]);
|
|
72
|
+
|
|
73
|
+
const result = getAIEnablementApprover(meeting);
|
|
74
|
+
|
|
75
|
+
assert.isNull(result);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should prioritize host over cohosts even if cohosts have capability', () => {
|
|
79
|
+
const host = createMember('host-zzz', {moderator: true, cohost: false}, true);
|
|
80
|
+
const cohost1 = createMember('cohost-aaa', {moderator: false, cohost: true}, true);
|
|
81
|
+
const meeting = createMeeting([cohost1, host]);
|
|
82
|
+
|
|
83
|
+
const result = getAIEnablementApprover(meeting);
|
|
84
|
+
|
|
85
|
+
assert.equal(result, 'host-zzz');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should handle a single cohost with capability when no host has capability', () => {
|
|
89
|
+
const host = createMember('host-123', {moderator: true, cohost: false}, false);
|
|
90
|
+
const cohost = createMember('cohost-999', {moderator: false, cohost: true}, true);
|
|
91
|
+
const meeting = createMeeting([host, cohost]);
|
|
92
|
+
|
|
93
|
+
const result = getAIEnablementApprover(meeting);
|
|
94
|
+
|
|
95
|
+
assert.equal(result, 'cohost-999');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should handle empty members collection', () => {
|
|
99
|
+
const meeting = createMeeting([]);
|
|
100
|
+
|
|
101
|
+
const result = getAIEnablementApprover(meeting);
|
|
102
|
+
|
|
103
|
+
assert.isNull(result);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should correctly sort cohosts by id string (not numeric)', () => {
|
|
107
|
+
const host = createMember('host-123', {moderator: true, cohost: false}, false);
|
|
108
|
+
const cohost1 = createMember('cohost-20', {moderator: false, cohost: true}, true);
|
|
109
|
+
const cohost2 = createMember('cohost-100', {moderator: false, cohost: true}, true);
|
|
110
|
+
const cohost3 = createMember('cohost-3', {moderator: false, cohost: true}, true);
|
|
111
|
+
const meeting = createMeeting([host, cohost1, cohost2, cohost3]);
|
|
112
|
+
|
|
113
|
+
const result = getAIEnablementApprover(meeting);
|
|
114
|
+
|
|
115
|
+
// Alphabetically: "cohost-100" < "cohost-20" < "cohost-3"
|
|
116
|
+
assert.equal(result, 'cohost-100');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should handle members with both moderator and cohost roles', () => {
|
|
120
|
+
// If someone is both moderator and cohost with capability, they should be found as host
|
|
121
|
+
const hostCohost = createMember('host-cohost-123', {moderator: true, cohost: true}, true);
|
|
122
|
+
const member = createMember('member-456', {moderator: false, cohost: false}, false);
|
|
123
|
+
const meeting = createMeeting([hostCohost, member]);
|
|
124
|
+
|
|
125
|
+
const result = getAIEnablementApprover(meeting);
|
|
126
|
+
|
|
127
|
+
assert.equal(result, 'host-cohost-123');
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -7,6 +7,7 @@ import LLMChannel from '@webex/internal-plugin-llm';
|
|
|
7
7
|
|
|
8
8
|
import AnnotationService from '../../../../src/annotation/index';
|
|
9
9
|
import {ANNOTATION_RELAY_TYPES, ANNOTATION_REQUEST_TYPE, EVENT_TRIGGERS} from '../../../../src/annotation/constants';
|
|
10
|
+
import {LLM_PRACTICE_SESSION} from '../../../../src/constants';
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
describe('live-annotation', () => {
|
|
@@ -28,6 +29,7 @@ describe('live-annotation', () => {
|
|
|
28
29
|
annotationService = webex.internal.annotation;
|
|
29
30
|
annotationService.connect = sinon.stub().resolves(true);
|
|
30
31
|
annotationService.webex.internal.llm.isConnected = sinon.stub().returns(true);
|
|
32
|
+
annotationService.webex.internal.llm.getSocket = sinon.stub().returns(undefined);
|
|
31
33
|
annotationService.webex.internal.llm.getBinding = sinon.stub().returns(undefined);
|
|
32
34
|
annotationService.webex.internal.llm.getLocusUrl = sinon.stub().returns(locusUrl);
|
|
33
35
|
annotationService.approvalUrl = 'url/approval';
|
|
@@ -183,7 +185,13 @@ describe('live-annotation', () => {
|
|
|
183
185
|
|
|
184
186
|
annotationService.listenToEvents();
|
|
185
187
|
|
|
186
|
-
assert.
|
|
188
|
+
assert.calledWithExactly(spy.firstCall, 'event:relay.event', sinon.match.func, sinon.match.object);
|
|
189
|
+
assert.calledWithExactly(
|
|
190
|
+
spy.secondCall,
|
|
191
|
+
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
192
|
+
sinon.match.func,
|
|
193
|
+
sinon.match.object
|
|
194
|
+
);
|
|
187
195
|
});
|
|
188
196
|
|
|
189
197
|
});
|
|
@@ -226,14 +234,11 @@ describe('live-annotation', () => {
|
|
|
226
234
|
});
|
|
227
235
|
|
|
228
236
|
describe('sendStrokeData', () => {
|
|
237
|
+
let strokeData;
|
|
229
238
|
|
|
230
239
|
beforeEach(async () => {
|
|
231
240
|
annotationService.webex.internal.llm.socket = new MockWebSocket();
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
it('works on publish Stroke Data', async () => {
|
|
236
|
-
const strokeData = {
|
|
241
|
+
strokeData = {
|
|
237
242
|
content: {
|
|
238
243
|
"contentsBuffer": [{
|
|
239
244
|
"contentArray": [{
|
|
@@ -249,8 +254,11 @@ describe('live-annotation', () => {
|
|
|
249
254
|
shareInstanceId: '7fa6fe07-dcb1-41ad-973d-7bcf65fab55d',
|
|
250
255
|
encryptionKeyUrl: "encryptionKeyUrl",
|
|
251
256
|
version: '1',
|
|
252
|
-
}
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
|
|
253
260
|
|
|
261
|
+
it('works on publish Stroke Data', async () => {
|
|
254
262
|
annotationService.publishEncrypted(strokeData.content, strokeData);
|
|
255
263
|
|
|
256
264
|
const sendObject = {
|
|
@@ -283,6 +291,49 @@ describe('live-annotation', () => {
|
|
|
283
291
|
assert.calledOnceWithExactly(annotationService.webex.internal.llm.socket.send, sendObject);
|
|
284
292
|
});
|
|
285
293
|
|
|
294
|
+
it('uses the practice-session socket and binding only when the practice-session session is connected', () => {
|
|
295
|
+
const practiceSocket = new MockWebSocket();
|
|
296
|
+
|
|
297
|
+
annotationService.webex.internal.llm.isConnected.callsFake((sessionId) =>
|
|
298
|
+
sessionId === LLM_PRACTICE_SESSION
|
|
299
|
+
);
|
|
300
|
+
annotationService.webex.internal.llm.getSocket
|
|
301
|
+
.withArgs(LLM_PRACTICE_SESSION)
|
|
302
|
+
.returns(practiceSocket);
|
|
303
|
+
annotationService.webex.internal.llm.getBinding
|
|
304
|
+
.withArgs(LLM_PRACTICE_SESSION)
|
|
305
|
+
.returns('practice-binding');
|
|
306
|
+
|
|
307
|
+
annotationService.publishEncrypted(strokeData.content, strokeData);
|
|
308
|
+
|
|
309
|
+
assert.calledOnce(practiceSocket.send);
|
|
310
|
+
assert.notCalled(annotationService.webex.internal.llm.socket.send);
|
|
311
|
+
|
|
312
|
+
const sent = practiceSocket.send.getCall(0).args[0];
|
|
313
|
+
assert.equal(sent.recipients.route, 'practice-binding');
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('falls back to the default socket and binding when the practice-session socket exists but is not connected', () => {
|
|
317
|
+
const practiceSocket = new MockWebSocket();
|
|
318
|
+
|
|
319
|
+
annotationService.webex.internal.llm.isConnected.callsFake((sessionId) => !sessionId);
|
|
320
|
+
annotationService.webex.internal.llm.getSocket
|
|
321
|
+
.withArgs(LLM_PRACTICE_SESSION)
|
|
322
|
+
.returns(practiceSocket);
|
|
323
|
+
annotationService.webex.internal.llm.getBinding
|
|
324
|
+
.withArgs(LLM_PRACTICE_SESSION)
|
|
325
|
+
.returns('practice-binding');
|
|
326
|
+
annotationService.webex.internal.llm.getBinding.returns('default-binding');
|
|
327
|
+
|
|
328
|
+
annotationService.publishEncrypted(strokeData.content, strokeData);
|
|
329
|
+
|
|
330
|
+
assert.notCalled(practiceSocket.send);
|
|
331
|
+
assert.calledOnce(annotationService.webex.internal.llm.socket.send);
|
|
332
|
+
|
|
333
|
+
const sent = annotationService.webex.internal.llm.socket.send.getCall(0).args[0];
|
|
334
|
+
assert.equal(sent.recipients.route, 'default-binding');
|
|
335
|
+
});
|
|
336
|
+
|
|
286
337
|
});
|
|
287
338
|
|
|
288
339
|
|
|
@@ -441,10 +492,21 @@ describe('live-annotation', () => {
|
|
|
441
492
|
annotationService.eventDataProcessor,
|
|
442
493
|
annotationService
|
|
443
494
|
);
|
|
495
|
+
assert.calledWith(
|
|
496
|
+
llmOn,
|
|
497
|
+
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
498
|
+
annotationService.eventDataProcessor,
|
|
499
|
+
annotationService
|
|
500
|
+
);
|
|
444
501
|
assert.match(annotationService.hasSubscribedToEvents, true);
|
|
445
502
|
|
|
446
503
|
annotationService.deregisterEvents();
|
|
447
504
|
assert.calledWith(llmOff, 'event:relay.event', annotationService.eventDataProcessor);
|
|
505
|
+
assert.calledWith(
|
|
506
|
+
llmOff,
|
|
507
|
+
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
508
|
+
annotationService.eventDataProcessor
|
|
509
|
+
);
|
|
448
510
|
assert.calledWith(
|
|
449
511
|
mercuryOff,
|
|
450
512
|
'event:locus.approval_request',
|
|
@@ -652,4 +652,70 @@ describe('HashTree', () => {
|
|
|
652
652
|
expect(() => hashTree.computeLeafHash(2)).to.not.throw();
|
|
653
653
|
});
|
|
654
654
|
});
|
|
655
|
+
|
|
656
|
+
describe('getItemVersion', () => {
|
|
657
|
+
it('should return version when item exists', () => {
|
|
658
|
+
const items: LeafDataItem[] = [
|
|
659
|
+
{type: 'participant', id: 1, version: 5},
|
|
660
|
+
{type: 'self', id: 2, version: 10},
|
|
661
|
+
];
|
|
662
|
+
const hashTree = new HashTree(items, 4);
|
|
663
|
+
|
|
664
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.equal(5);
|
|
665
|
+
expect(hashTree.getItemVersion(2, 'self')).to.equal(10);
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
it('should return undefined when item does not exist', () => {
|
|
669
|
+
const items: LeafDataItem[] = [{type: 'participant', id: 1, version: 5}];
|
|
670
|
+
const hashTree = new HashTree(items, 4);
|
|
671
|
+
|
|
672
|
+
expect(hashTree.getItemVersion(999, 'participant')).to.be.undefined;
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it('should return undefined when type does not match', () => {
|
|
676
|
+
const items: LeafDataItem[] = [{type: 'participant', id: 1, version: 5}];
|
|
677
|
+
const hashTree = new HashTree(items, 4);
|
|
678
|
+
|
|
679
|
+
expect(hashTree.getItemVersion(1, 'self')).to.be.undefined;
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('should return undefined for tree with 0 leaves', () => {
|
|
683
|
+
const hashTree = new HashTree([], 0);
|
|
684
|
+
|
|
685
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.be.undefined;
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
it('should return correct version when multiple items exist in same leaf', () => {
|
|
689
|
+
const items: LeafDataItem[] = [
|
|
690
|
+
{type: 'participant', id: 1, version: 3}, // leaf 1 (1 % 2 = 1)
|
|
691
|
+
{type: 'self', id: 3, version: 7}, // leaf 1 (3 % 2 = 1)
|
|
692
|
+
{type: 'locus', id: 5, version: 12}, // leaf 1 (5 % 2 = 1)
|
|
693
|
+
];
|
|
694
|
+
const hashTree = new HashTree(items, 2);
|
|
695
|
+
|
|
696
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.equal(3);
|
|
697
|
+
expect(hashTree.getItemVersion(3, 'self')).to.equal(7);
|
|
698
|
+
expect(hashTree.getItemVersion(5, 'locus')).to.equal(12);
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
it('should return updated version after item is updated', () => {
|
|
702
|
+
const hashTree = new HashTree([{type: 'participant', id: 1, version: 5}], 4);
|
|
703
|
+
|
|
704
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.equal(5);
|
|
705
|
+
|
|
706
|
+
hashTree.putItem({type: 'participant', id: 1, version: 10});
|
|
707
|
+
|
|
708
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.equal(10);
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
it('should return undefined after item is removed', () => {
|
|
712
|
+
const hashTree = new HashTree([{type: 'participant', id: 1, version: 5}], 4);
|
|
713
|
+
|
|
714
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.equal(5);
|
|
715
|
+
|
|
716
|
+
hashTree.removeItem({type: 'participant', id: 1, version: 5});
|
|
717
|
+
|
|
718
|
+
expect(hashTree.getItemVersion(1, 'participant')).to.be.undefined;
|
|
719
|
+
});
|
|
720
|
+
});
|
|
655
721
|
});
|