@webex/plugin-meetings 3.12.0-next.60 → 3.12.0-next.62
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/hashTree/constants.js +4 -1
- package/dist/hashTree/constants.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +197 -49
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/utils.js +20 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +11 -2
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/index.js +6 -0
- package/dist/meeting/index.js.map +1 -1
- package/dist/types/hashTree/constants.d.ts +1 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +55 -4
- package/dist/types/hashTree/utils.d.ts +7 -0
- package/dist/types/locus-info/index.d.ts +5 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/hashTree/constants.ts +7 -0
- package/src/hashTree/hashTreeParser.ts +156 -23
- package/src/hashTree/utils.ts +19 -0
- package/src/locus-info/index.ts +4 -2
- package/src/meeting/index.ts +2 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +197 -2
- package/test/unit/spec/hashTree/utils.ts +37 -0
- package/test/unit/spec/locus-info/index.js +12 -0
- package/test/unit/spec/meeting/index.js +25 -5
|
@@ -2,6 +2,7 @@ import HashTreeParser, {
|
|
|
2
2
|
LocusInfoUpdateType,
|
|
3
3
|
MeetingEndedError,
|
|
4
4
|
LocusNotFoundError,
|
|
5
|
+
SyncAllBackoffType,
|
|
5
6
|
} from '@webex/plugin-meetings/src/hashTree/hashTreeParser';
|
|
6
7
|
import HashTree from '@webex/plugin-meetings/src/hashTree/hashTree';
|
|
7
8
|
import {expect} from '@webex/test-helper-chai';
|
|
@@ -4494,8 +4495,8 @@ describe('HashTreeParser', () => {
|
|
|
4494
4495
|
);
|
|
4495
4496
|
expect(mainSyncCallIndex).to.be.lessThan(selfSyncCallIndex);
|
|
4496
4497
|
|
|
4497
|
-
// Verify
|
|
4498
|
-
expect(parser.
|
|
4498
|
+
// Verify syncAllBackoffType is reset
|
|
4499
|
+
expect(parser.syncAllBackoffType).to.equal(SyncAllBackoffType.NONE);
|
|
4499
4500
|
});
|
|
4500
4501
|
|
|
4501
4502
|
it('should return immediately when state is stopped', async () => {
|
|
@@ -4560,6 +4561,200 @@ describe('HashTreeParser', () => {
|
|
|
4560
4561
|
expect(getHashtreeCalls).to.have.lengthOf(1);
|
|
4561
4562
|
});
|
|
4562
4563
|
|
|
4564
|
+
it('should sync only LLM datasets when onlyLLM=true', async () => {
|
|
4565
|
+
const parser = createHashTreeParser();
|
|
4566
|
+
|
|
4567
|
+
const mainUrl = parser.dataSets.main.url;
|
|
4568
|
+
const selfUrl = parser.dataSets.self.url;
|
|
4569
|
+
|
|
4570
|
+
mockGetHashesFromLocusResponse(
|
|
4571
|
+
mainUrl,
|
|
4572
|
+
new Array(16).fill(EMPTY_HASH),
|
|
4573
|
+
createDataSet('main', 16, 1100)
|
|
4574
|
+
);
|
|
4575
|
+
|
|
4576
|
+
const mainSyncDs = createDataSet('main', 16, 1100);
|
|
4577
|
+
mainSyncDs.root = parser.dataSets.main.hashTree.getRootHash();
|
|
4578
|
+
mockSendSyncRequestResponse(mainUrl, {
|
|
4579
|
+
dataSets: [mainSyncDs],
|
|
4580
|
+
visibleDataSetsUrl,
|
|
4581
|
+
locusUrl,
|
|
4582
|
+
locusStateElements: [],
|
|
4583
|
+
});
|
|
4584
|
+
|
|
4585
|
+
await parser.syncAllDatasets({onlyLLM: true});
|
|
4586
|
+
|
|
4587
|
+
// main is an LLM dataset, so it should have been synced
|
|
4588
|
+
assert.calledWith(webexRequest, sinon.match({method: 'GET', uri: `${mainUrl}/hashtree`}));
|
|
4589
|
+
|
|
4590
|
+
// self is NOT an LLM dataset, so it should NOT have been synced
|
|
4591
|
+
assert.neverCalledWith(webexRequest, sinon.match({method: 'POST', uri: `${selfUrl}/sync`}));
|
|
4592
|
+
assert.neverCalledWith(webexRequest, sinon.match({method: 'GET', uri: `${selfUrl}/hashtree`}));
|
|
4593
|
+
});
|
|
4594
|
+
|
|
4595
|
+
it('should upgrade scope from onlyLLM=true to all datasets when onlyLLM=false call arrives during backoff', async () => {
|
|
4596
|
+
// Make Math.random return 1 so backoff = 1^2 * 1000 = 1000ms (non-zero delay for interleaving)
|
|
4597
|
+
mathRandomStub.returns(1);
|
|
4598
|
+
|
|
4599
|
+
const parser = createHashTreeParser();
|
|
4600
|
+
|
|
4601
|
+
const mainUrl = parser.dataSets.main.url;
|
|
4602
|
+
const selfUrl = parser.dataSets.self.url;
|
|
4603
|
+
|
|
4604
|
+
mockGetHashesFromLocusResponse(
|
|
4605
|
+
mainUrl,
|
|
4606
|
+
new Array(16).fill(EMPTY_HASH),
|
|
4607
|
+
createDataSet('main', 16, 1100)
|
|
4608
|
+
);
|
|
4609
|
+
|
|
4610
|
+
const mainSyncDs = createDataSet('main', 16, 1100);
|
|
4611
|
+
mainSyncDs.root = parser.dataSets.main.hashTree.getRootHash();
|
|
4612
|
+
mockSendSyncRequestResponse(mainUrl, {
|
|
4613
|
+
dataSets: [mainSyncDs],
|
|
4614
|
+
visibleDataSetsUrl,
|
|
4615
|
+
locusUrl,
|
|
4616
|
+
locusStateElements: [],
|
|
4617
|
+
});
|
|
4618
|
+
|
|
4619
|
+
const selfSyncDs = createDataSet('self', 1, 2100);
|
|
4620
|
+
selfSyncDs.root = parser.dataSets.self.hashTree.getRootHash();
|
|
4621
|
+
mockSendSyncRequestResponse(selfUrl, {
|
|
4622
|
+
dataSets: [selfSyncDs],
|
|
4623
|
+
visibleDataSetsUrl,
|
|
4624
|
+
locusUrl,
|
|
4625
|
+
locusStateElements: [],
|
|
4626
|
+
});
|
|
4627
|
+
|
|
4628
|
+
// First call with onlyLLM=true starts backoff
|
|
4629
|
+
const promise1 = parser.syncAllDatasets({onlyLLM: true});
|
|
4630
|
+
expect(parser.syncAllBackoffType).to.equal(SyncAllBackoffType.ONLY_LLM);
|
|
4631
|
+
|
|
4632
|
+
// Second call with onlyLLM=false upgrades the scope during backoff
|
|
4633
|
+
const promise2 = parser.syncAllDatasets({onlyLLM: false});
|
|
4634
|
+
expect(parser.syncAllBackoffType).to.equal(SyncAllBackoffType.ALL);
|
|
4635
|
+
|
|
4636
|
+
// Advance clock past the backoff delay (1000ms)
|
|
4637
|
+
await clock.tickAsync(1000);
|
|
4638
|
+
|
|
4639
|
+
await promise1;
|
|
4640
|
+
await promise2;
|
|
4641
|
+
|
|
4642
|
+
// Both main (LLM) and self (non-LLM) should have been synced
|
|
4643
|
+
assert.calledWith(webexRequest, sinon.match({method: 'GET', uri: `${mainUrl}/hashtree`}));
|
|
4644
|
+
assert.calledWith(webexRequest, sinon.match({method: 'POST', uri: `${selfUrl}/sync`}));
|
|
4645
|
+
});
|
|
4646
|
+
|
|
4647
|
+
it('should not downgrade scope from onlyLLM=false when onlyLLM=true call arrives during backoff', async () => {
|
|
4648
|
+
// Make Math.random return 1 so backoff = 1^2 * 1000 = 1000ms (non-zero delay for interleaving)
|
|
4649
|
+
mathRandomStub.returns(1);
|
|
4650
|
+
|
|
4651
|
+
const parser = createHashTreeParser();
|
|
4652
|
+
|
|
4653
|
+
const mainUrl = parser.dataSets.main.url;
|
|
4654
|
+
const selfUrl = parser.dataSets.self.url;
|
|
4655
|
+
|
|
4656
|
+
mockGetHashesFromLocusResponse(
|
|
4657
|
+
mainUrl,
|
|
4658
|
+
new Array(16).fill(EMPTY_HASH),
|
|
4659
|
+
createDataSet('main', 16, 1100)
|
|
4660
|
+
);
|
|
4661
|
+
|
|
4662
|
+
const mainSyncDs = createDataSet('main', 16, 1100);
|
|
4663
|
+
mainSyncDs.root = parser.dataSets.main.hashTree.getRootHash();
|
|
4664
|
+
mockSendSyncRequestResponse(mainUrl, {
|
|
4665
|
+
dataSets: [mainSyncDs],
|
|
4666
|
+
visibleDataSetsUrl,
|
|
4667
|
+
locusUrl,
|
|
4668
|
+
locusStateElements: [],
|
|
4669
|
+
});
|
|
4670
|
+
|
|
4671
|
+
const selfSyncDs = createDataSet('self', 1, 2100);
|
|
4672
|
+
selfSyncDs.root = parser.dataSets.self.hashTree.getRootHash();
|
|
4673
|
+
mockSendSyncRequestResponse(selfUrl, {
|
|
4674
|
+
dataSets: [selfSyncDs],
|
|
4675
|
+
visibleDataSetsUrl,
|
|
4676
|
+
locusUrl,
|
|
4677
|
+
locusStateElements: [],
|
|
4678
|
+
});
|
|
4679
|
+
|
|
4680
|
+
// First call with onlyLLM=false starts backoff with all-datasets scope
|
|
4681
|
+
const promise1 = parser.syncAllDatasets({onlyLLM: false});
|
|
4682
|
+
expect(parser.syncAllBackoffType).to.equal(SyncAllBackoffType.ALL);
|
|
4683
|
+
|
|
4684
|
+
// Second call with onlyLLM=true should NOT downgrade the scope
|
|
4685
|
+
const promise2 = parser.syncAllDatasets({onlyLLM: true});
|
|
4686
|
+
expect(parser.syncAllBackoffType).to.equal(SyncAllBackoffType.ALL);
|
|
4687
|
+
|
|
4688
|
+
// Advance clock past the backoff delay (1000ms)
|
|
4689
|
+
await clock.tickAsync(1000);
|
|
4690
|
+
|
|
4691
|
+
await promise1;
|
|
4692
|
+
await promise2;
|
|
4693
|
+
|
|
4694
|
+
// Both main (LLM) and self (non-LLM) should have been synced (scope was not downgraded)
|
|
4695
|
+
assert.calledWith(webexRequest, sinon.match({method: 'GET', uri: `${mainUrl}/hashtree`}));
|
|
4696
|
+
assert.calledWith(webexRequest, sinon.match({method: 'POST', uri: `${selfUrl}/sync`}));
|
|
4697
|
+
});
|
|
4698
|
+
|
|
4699
|
+
it('should skip datasets that received messages during the backoff sleep', async () => {
|
|
4700
|
+
// Make Math.random return 1 so backoff = 1^2 * 1000 = 1000ms
|
|
4701
|
+
mathRandomStub.returns(1);
|
|
4702
|
+
|
|
4703
|
+
const parser = createHashTreeParser();
|
|
4704
|
+
|
|
4705
|
+
const mainUrl = parser.dataSets.main.url;
|
|
4706
|
+
const selfUrl = parser.dataSets.self.url;
|
|
4707
|
+
const atdUnmutedUrl = parser.dataSets['atd-unmuted'].url;
|
|
4708
|
+
|
|
4709
|
+
// Setup mocks only for self (main and atd-unmuted should be skipped)
|
|
4710
|
+
mockSendSyncRequestResponse(selfUrl, {
|
|
4711
|
+
dataSets: [createDataSet('self', 1, 2100)],
|
|
4712
|
+
visibleDataSetsUrl,
|
|
4713
|
+
locusUrl,
|
|
4714
|
+
locusStateElements: [],
|
|
4715
|
+
});
|
|
4716
|
+
|
|
4717
|
+
// Start syncAllDatasets - begins backoff sleep
|
|
4718
|
+
const promise = parser.syncAllDatasets();
|
|
4719
|
+
expect(parser.syncAllBackoffType).to.equal(SyncAllBackoffType.ALL);
|
|
4720
|
+
|
|
4721
|
+
// Simulate a normal message arriving for "main" during the backoff sleep
|
|
4722
|
+
parser.handleMessage({
|
|
4723
|
+
dataSets: [createDataSet('main', 16, 1100)],
|
|
4724
|
+
visibleDataSetsUrl,
|
|
4725
|
+
locusUrl,
|
|
4726
|
+
locusStateElements: [
|
|
4727
|
+
{
|
|
4728
|
+
htMeta: {
|
|
4729
|
+
elementId: {type: 'locus' as const, id: 0, version: 201},
|
|
4730
|
+
dataSetNames: ['main'],
|
|
4731
|
+
},
|
|
4732
|
+
data: {someData: 'value'},
|
|
4733
|
+
},
|
|
4734
|
+
],
|
|
4735
|
+
});
|
|
4736
|
+
|
|
4737
|
+
// Simulate a heartbeat message arriving for "atd-unmuted" during the backoff sleep
|
|
4738
|
+
parser.handleMessage(
|
|
4739
|
+
createHeartbeatMessage('atd-unmuted', 1, 1100, parser.dataSets['atd-unmuted'].root)
|
|
4740
|
+
);
|
|
4741
|
+
|
|
4742
|
+
// Advance clock past the backoff delay
|
|
4743
|
+
await clock.tickAsync(1000);
|
|
4744
|
+
await promise;
|
|
4745
|
+
|
|
4746
|
+
// main should NOT have been synced (it received a normal message during backoff)
|
|
4747
|
+
assert.neverCalledWith(webexRequest, sinon.match({method: 'GET', uri: `${mainUrl}/hashtree`}));
|
|
4748
|
+
assert.neverCalledWith(webexRequest, sinon.match({method: 'POST', uri: `${mainUrl}/sync`}));
|
|
4749
|
+
|
|
4750
|
+
// atd-unmuted should NOT have been synced (it received a heartbeat during backoff)
|
|
4751
|
+
assert.neverCalledWith(webexRequest, sinon.match({method: 'GET', uri: `${atdUnmutedUrl}/hashtree`}));
|
|
4752
|
+
assert.neverCalledWith(webexRequest, sinon.match({method: 'POST', uri: `${atdUnmutedUrl}/sync`}));
|
|
4753
|
+
|
|
4754
|
+
// self SHOULD have been synced (no messages received for it during backoff)
|
|
4755
|
+
assert.calledWith(webexRequest, sinon.match({method: 'POST', uri: `${selfUrl}/sync`}));
|
|
4756
|
+
});
|
|
4757
|
+
|
|
4563
4758
|
it('should skip datasets that do not have a hash tree', async () => {
|
|
4564
4759
|
// Create parser with metadata that only has main and self as visible (not atd-unmuted)
|
|
4565
4760
|
const metadataWithoutAtd = {
|
|
@@ -2,9 +2,11 @@ import {HashTreeObject, ObjectType} from '../../../../src/hashTree/types';
|
|
|
2
2
|
import {
|
|
3
3
|
deleteNestedObjectsWithHtMeta,
|
|
4
4
|
isSelf,
|
|
5
|
+
sleep,
|
|
5
6
|
sortByInitPriority,
|
|
6
7
|
} from '../../../../src/hashTree/utils';
|
|
7
8
|
import {DataSetNames, DATA_SET_INIT_PRIORITY} from '../../../../src/hashTree/constants';
|
|
9
|
+
import sinon from 'sinon';
|
|
8
10
|
|
|
9
11
|
import {assert} from '@webex/test-helper-chai';
|
|
10
12
|
|
|
@@ -224,4 +226,39 @@ describe('Hash Tree Utils', () => {
|
|
|
224
226
|
]);
|
|
225
227
|
});
|
|
226
228
|
});
|
|
229
|
+
|
|
230
|
+
describe('#sleep', () => {
|
|
231
|
+
let clock;
|
|
232
|
+
|
|
233
|
+
beforeEach(() => {
|
|
234
|
+
clock = sinon.useFakeTimers();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
afterEach(() => {
|
|
238
|
+
clock.restore();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
[0, -1, -100].forEach((ms) => {
|
|
242
|
+
it(`resolves immediately when ms is ${ms}`, async () => {
|
|
243
|
+
const result = sleep(ms);
|
|
244
|
+
|
|
245
|
+
assert.instanceOf(result, Promise);
|
|
246
|
+
await result;
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('resolves after the specified delay', async () => {
|
|
251
|
+
let resolved = false;
|
|
252
|
+
|
|
253
|
+
sleep(500).then(() => { resolved = true; });
|
|
254
|
+
|
|
255
|
+
assert.isFalse(resolved);
|
|
256
|
+
|
|
257
|
+
await clock.tickAsync(499);
|
|
258
|
+
assert.isFalse(resolved);
|
|
259
|
+
|
|
260
|
+
await clock.tickAsync(1);
|
|
261
|
+
assert.isTrue(resolved);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
227
264
|
});
|
|
@@ -3744,6 +3744,18 @@ describe('plugin-meetings', () => {
|
|
|
3744
3744
|
assert.calledOnce(parser1.syncAllDatasets);
|
|
3745
3745
|
});
|
|
3746
3746
|
|
|
3747
|
+
it('should forward options to each parser syncAllDatasets', async () => {
|
|
3748
|
+
const parser1 = {syncAllDatasets: sinon.stub().resolves()};
|
|
3749
|
+
const parser2 = {syncAllDatasets: sinon.stub().resolves()};
|
|
3750
|
+
locusInfo.hashTreeParsers.set('url1', {parser: parser1});
|
|
3751
|
+
locusInfo.hashTreeParsers.set('url2', {parser: parser2});
|
|
3752
|
+
|
|
3753
|
+
await locusInfo.syncAllHashTreeDatasets({onlyLLM: true});
|
|
3754
|
+
|
|
3755
|
+
assert.calledOnceWithExactly(parser1.syncAllDatasets, {onlyLLM: true});
|
|
3756
|
+
assert.calledOnceWithExactly(parser2.syncAllDatasets, {onlyLLM: true});
|
|
3757
|
+
});
|
|
3758
|
+
|
|
3747
3759
|
it('should await each parsers syncAllDatasets sequentially', async () => {
|
|
3748
3760
|
const callOrder = [];
|
|
3749
3761
|
const parser1 = {syncAllDatasets: sinon.stub().callsFake(() => {
|
|
@@ -2280,6 +2280,14 @@ describe('plugin-meetings', () => {
|
|
|
2280
2280
|
|
|
2281
2281
|
assert.notCalled(webex.internal.voicea.updateSubchannelSubscriptions);
|
|
2282
2282
|
});
|
|
2283
|
+
|
|
2284
|
+
it('calls syncAllHashTreeDatasets on locusInfo', () => {
|
|
2285
|
+
sinon.stub(meeting.locusInfo, 'syncAllHashTreeDatasets').resolves();
|
|
2286
|
+
|
|
2287
|
+
meeting.handleLLMOnline();
|
|
2288
|
+
|
|
2289
|
+
assert.calledOnceWithExactly(meeting.locusInfo.syncAllHashTreeDatasets, {onlyLLM: true});
|
|
2290
|
+
});
|
|
2283
2291
|
});
|
|
2284
2292
|
|
|
2285
2293
|
describe('#join', () => {
|
|
@@ -13769,7 +13777,7 @@ describe('plugin-meetings', () => {
|
|
|
13769
13777
|
meeting.joinedWith = {state: 'any other state'};
|
|
13770
13778
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
13771
13779
|
|
|
13772
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
13780
|
+
meeting.locusInfo = {syncAllHashTreeDatasets: sinon.stub().resolves(), url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
13773
13781
|
|
|
13774
13782
|
const result = await meeting.updateLLMConnection();
|
|
13775
13783
|
|
|
@@ -13781,6 +13789,7 @@ describe('plugin-meetings', () => {
|
|
|
13781
13789
|
it('returns undefined if llm is already connected and the locus url is unchanged', async () => {
|
|
13782
13790
|
meeting.joinedWith = {state: 'JOINED'};
|
|
13783
13791
|
meeting.locusInfo = {
|
|
13792
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
13784
13793
|
url: 'a url',
|
|
13785
13794
|
info: {datachannelUrl: 'a datachannel url'},
|
|
13786
13795
|
};
|
|
@@ -13817,7 +13826,7 @@ describe('plugin-meetings', () => {
|
|
|
13817
13826
|
});
|
|
13818
13827
|
it('connects if not already connected', async () => {
|
|
13819
13828
|
meeting.joinedWith = {state: 'JOINED'};
|
|
13820
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
13829
|
+
meeting.locusInfo = {syncAllHashTreeDatasets: sinon.stub().resolves(), url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
13821
13830
|
|
|
13822
13831
|
const result = await meeting.updateLLMConnection();
|
|
13823
13832
|
|
|
@@ -13829,6 +13838,7 @@ describe('plugin-meetings', () => {
|
|
|
13829
13838
|
undefined
|
|
13830
13839
|
);
|
|
13831
13840
|
assert.equal(result, 'something');
|
|
13841
|
+
assert.calledOnceWithExactly(meeting.locusInfo.syncAllHashTreeDatasets, {onlyLLM: true});
|
|
13832
13842
|
});
|
|
13833
13843
|
it('disconnects if the locus url has changed', async () => {
|
|
13834
13844
|
meeting.joinedWith = {state: 'JOINED'};
|
|
@@ -13837,6 +13847,7 @@ describe('plugin-meetings', () => {
|
|
|
13837
13847
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
13838
13848
|
|
|
13839
13849
|
meeting.locusInfo = {
|
|
13850
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
13840
13851
|
url: 'a different url',
|
|
13841
13852
|
info: {datachannelUrl: 'a datachannel url'},
|
|
13842
13853
|
self: {},
|
|
@@ -13890,6 +13901,7 @@ describe('plugin-meetings', () => {
|
|
|
13890
13901
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
13891
13902
|
|
|
13892
13903
|
meeting.locusInfo = {
|
|
13904
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
13893
13905
|
url: 'a url',
|
|
13894
13906
|
info: {datachannelUrl: 'a different datachannel url'},
|
|
13895
13907
|
self: {},
|
|
@@ -13941,7 +13953,7 @@ describe('plugin-meetings', () => {
|
|
|
13941
13953
|
webex.internal.llm.isConnected.returns(true);
|
|
13942
13954
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
13943
13955
|
|
|
13944
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
13956
|
+
meeting.locusInfo = {syncAllHashTreeDatasets: sinon.stub().resolves(), url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
13945
13957
|
|
|
13946
13958
|
const result = await meeting.updateLLMConnection();
|
|
13947
13959
|
|
|
@@ -13964,6 +13976,7 @@ describe('plugin-meetings', () => {
|
|
|
13964
13976
|
webex.internal.llm.disconnectLLM.rejects(disconnectError);
|
|
13965
13977
|
|
|
13966
13978
|
meeting.locusInfo = {
|
|
13979
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
13967
13980
|
url: 'a different url',
|
|
13968
13981
|
info: {datachannelUrl: 'a datachannel url'},
|
|
13969
13982
|
self: {},
|
|
@@ -13995,6 +14008,7 @@ describe('plugin-meetings', () => {
|
|
|
13995
14008
|
it('still need connect main session data channel when PS started', async () => {
|
|
13996
14009
|
meeting.joinedWith = {state: 'JOINED'};
|
|
13997
14010
|
meeting.locusInfo = {
|
|
14011
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
13998
14012
|
url: 'a url',
|
|
13999
14013
|
info: {
|
|
14000
14014
|
datachannelUrl: 'a datachannel url',
|
|
@@ -14015,6 +14029,7 @@ describe('plugin-meetings', () => {
|
|
|
14015
14029
|
it('passes dataChannelToken from LLM to registerAndConnect', async () => {
|
|
14016
14030
|
meeting.joinedWith = {state: 'JOINED'};
|
|
14017
14031
|
meeting.locusInfo = {
|
|
14032
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
14018
14033
|
url: 'a url',
|
|
14019
14034
|
info: {datachannelUrl: 'a datachannel url'},
|
|
14020
14035
|
};
|
|
@@ -14036,6 +14051,7 @@ describe('plugin-meetings', () => {
|
|
|
14036
14051
|
it('passes undefined token when LLM has no token stored', async () => {
|
|
14037
14052
|
meeting.joinedWith = {state: 'JOINED'};
|
|
14038
14053
|
meeting.locusInfo = {
|
|
14054
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
14039
14055
|
url: 'a url',
|
|
14040
14056
|
info: {datachannelUrl: 'a datachannel url'},
|
|
14041
14057
|
};
|
|
@@ -14057,6 +14073,7 @@ describe('plugin-meetings', () => {
|
|
|
14057
14073
|
it('does not pass token when data channel with jwt token is disabled', async () => {
|
|
14058
14074
|
meeting.joinedWith = {state: 'JOINED'};
|
|
14059
14075
|
meeting.locusInfo = {
|
|
14076
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
14060
14077
|
url: 'a url',
|
|
14061
14078
|
info: {datachannelUrl: 'a datachannel url'},
|
|
14062
14079
|
};
|
|
@@ -14099,6 +14116,7 @@ describe('plugin-meetings', () => {
|
|
|
14099
14116
|
webex.internal.llm.getLocusUrl.returns('owner-locus-url');
|
|
14100
14117
|
webex.internal.llm.getDatachannelUrl.returns('owner-dc-url');
|
|
14101
14118
|
meeting.locusInfo = {
|
|
14119
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
14102
14120
|
url: 'a different url',
|
|
14103
14121
|
info: {datachannelUrl: 'a different datachannel url'},
|
|
14104
14122
|
self: {},
|
|
@@ -14122,6 +14140,7 @@ describe('plugin-meetings', () => {
|
|
|
14122
14140
|
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
14123
14141
|
webex.internal.llm.disconnectLLM.rejects(new Error('disconnect failed'));
|
|
14124
14142
|
meeting.locusInfo = {
|
|
14143
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
14125
14144
|
url: 'a different url',
|
|
14126
14145
|
info: {datachannelUrl: 'a datachannel url'},
|
|
14127
14146
|
self: {},
|
|
@@ -14145,6 +14164,7 @@ describe('plugin-meetings', () => {
|
|
|
14145
14164
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
14146
14165
|
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
14147
14166
|
meeting.locusInfo = {
|
|
14167
|
+
syncAllHashTreeDatasets: sinon.stub().resolves(),
|
|
14148
14168
|
url: 'a different url',
|
|
14149
14169
|
info: {datachannelUrl: 'a datachannel url'},
|
|
14150
14170
|
self: {},
|
|
@@ -14175,7 +14195,7 @@ describe('plugin-meetings', () => {
|
|
|
14175
14195
|
meeting.joinedWith = {state: 'JOINED'};
|
|
14176
14196
|
webex.internal.llm.isConnected.returns(false);
|
|
14177
14197
|
webex.internal.llm.getOwnerMeetingId.returns(undefined);
|
|
14178
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
14198
|
+
meeting.locusInfo = {syncAllHashTreeDatasets: sinon.stub().resolves(), url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
14179
14199
|
|
|
14180
14200
|
await meeting.updateLLMConnection();
|
|
14181
14201
|
|
|
@@ -14191,7 +14211,7 @@ describe('plugin-meetings', () => {
|
|
|
14191
14211
|
meeting.joinedWith = {state: 'JOINED'};
|
|
14192
14212
|
webex.internal.llm.isConnected.returns(false);
|
|
14193
14213
|
webex.internal.llm.getOwnerMeetingId.returns('stale-owner-id');
|
|
14194
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
14214
|
+
meeting.locusInfo = {syncAllHashTreeDatasets: sinon.stub().resolves(), url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
14195
14215
|
|
|
14196
14216
|
await meeting.updateLLMConnection();
|
|
14197
14217
|
|