@webex/plugin-meetings 3.11.0-next.29 → 3.11.0-next.30
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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/index.js +2 -1
- 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 +233 -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/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.js +109 -26
- 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/types/interceptors/constant.d.ts +5 -0
- package/dist/types/interceptors/dataChannelAuthToken.d.ts +35 -0
- package/dist/types/interceptors/index.d.ts +2 -1
- package/dist/types/meeting/index.d.ts +19 -0
- package/dist/types/meeting/request.d.ts +16 -1
- package/dist/types/meeting/request.type.d.ts +5 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/index.ts +6 -1
- package/src/interceptors/constant.ts +6 -0
- package/src/interceptors/dataChannelAuthToken.ts +142 -0
- package/src/interceptors/index.ts +2 -1
- package/src/meeting/index.ts +73 -3
- package/src/meeting/request.ts +42 -0
- package/src/meeting/request.type.ts +6 -0
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +141 -0
- package/test/unit/spec/meeting/index.js +250 -59
- package/test/unit/spec/meeting/request.js +64 -0
|
@@ -123,7 +123,6 @@ import {EVENT_TRIGGERS as VOICEAEVENTS} from '@webex/internal-plugin-voicea';
|
|
|
123
123
|
import {createBrbState} from '@webex/plugin-meetings/src/meeting/brbState';
|
|
124
124
|
import JoinForbiddenError from '../../../../src/common/errors/join-forbidden-error';
|
|
125
125
|
import {EventEmitter} from 'stream';
|
|
126
|
-
|
|
127
126
|
describe('plugin-meetings', () => {
|
|
128
127
|
const logger = {
|
|
129
128
|
info: () => {},
|
|
@@ -265,6 +264,7 @@ describe('plugin-meetings', () => {
|
|
|
265
264
|
stopReachability: sinon.stub(),
|
|
266
265
|
isSubnetReachable: sinon.stub().returns(true),
|
|
267
266
|
};
|
|
267
|
+
webex.internal.llm.isDataChannelTokenEnabled = sinon.stub().resolves(false)
|
|
268
268
|
webex.internal.llm.on = sinon.stub();
|
|
269
269
|
webex.internal.newMetrics.callDiagnosticLatencies = new CallDiagnosticLatencies(
|
|
270
270
|
{},
|
|
@@ -12579,16 +12579,20 @@ describe('plugin-meetings', () => {
|
|
|
12579
12579
|
webex.internal.llm.isConnected = sinon.stub().returns(false);
|
|
12580
12580
|
webex.internal.llm.getLocusUrl = sinon.stub();
|
|
12581
12581
|
webex.internal.llm.getDatachannelUrl = sinon.stub();
|
|
12582
|
-
webex.internal.llm.registerAndConnect = sinon
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
webex.internal.llm.
|
|
12586
|
-
|
|
12587
|
-
|
|
12582
|
+
webex.internal.llm.registerAndConnect = sinon.stub().resolves('something');
|
|
12583
|
+
webex.internal.llm.disconnectLLM = sinon.stub().resolves();
|
|
12584
|
+
webex.internal.llm.on = sinon.stub();
|
|
12585
|
+
webex.internal.llm.off = sinon.stub();
|
|
12586
|
+
webex.internal.llm.getDatachannelToken = sinon.stub().returns(undefined);
|
|
12587
|
+
webex.internal.llm.setDatachannelToken = sinon.stub();
|
|
12588
|
+
|
|
12588
12589
|
meeting.processRelayEvent = sinon.stub();
|
|
12590
|
+
meeting.processLocusLLMEvent = sinon.stub();
|
|
12591
|
+
meeting.clearLLMHealthCheckTimer = sinon.stub();
|
|
12592
|
+
meeting.startLLMHealthCheckTimer = sinon.stub();
|
|
12593
|
+
|
|
12589
12594
|
meeting.webinar.isJoinPracticeSessionDataChannel = sinon.stub().returns(false);
|
|
12590
12595
|
});
|
|
12591
|
-
|
|
12592
12596
|
it('does not connect if the call is not joined yet', async () => {
|
|
12593
12597
|
meeting.joinedWith = {state: 'any other state'};
|
|
12594
12598
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
@@ -12602,31 +12606,21 @@ describe('plugin-meetings', () => {
|
|
|
12602
12606
|
assert.equal(result, undefined);
|
|
12603
12607
|
assert.notCalled(meeting.webex.internal.llm.on);
|
|
12604
12608
|
});
|
|
12605
|
-
|
|
12606
12609
|
it('returns undefined if llm is already connected and the locus url is unchanged', async () => {
|
|
12607
12610
|
meeting.joinedWith = {state: 'JOINED'};
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12613
|
-
|
|
12614
|
-
const result = await meeting.updateLLMConnection();
|
|
12615
|
-
|
|
12616
|
-
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
12617
|
-
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
12618
|
-
assert.equal(result, undefined);
|
|
12619
|
-
assert.notCalled(meeting.webex.internal.llm.on);
|
|
12620
|
-
});
|
|
12621
|
-
|
|
12622
|
-
it('connects if not already connected', async () => {
|
|
12623
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
12624
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12611
|
+
meeting.locusInfo = {
|
|
12612
|
+
url: 'a url',
|
|
12613
|
+
info: {datachannelUrl: 'a datachannel url'}
|
|
12614
|
+
};
|
|
12625
12615
|
|
|
12626
12616
|
const result = await meeting.updateLLMConnection();
|
|
12627
|
-
|
|
12628
12617
|
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
12629
|
-
assert.
|
|
12618
|
+
assert.calledWithExactly(
|
|
12619
|
+
webex.internal.llm.registerAndConnect,
|
|
12620
|
+
'a url',
|
|
12621
|
+
'a datachannel url',
|
|
12622
|
+
undefined
|
|
12623
|
+
);
|
|
12630
12624
|
assert.equal(result, 'something');
|
|
12631
12625
|
assert.calledWithExactly(
|
|
12632
12626
|
meeting.webex.internal.llm.off,
|
|
@@ -12649,27 +12643,49 @@ describe('plugin-meetings', () => {
|
|
|
12649
12643
|
meeting.processLocusLLMEvent
|
|
12650
12644
|
);
|
|
12651
12645
|
});
|
|
12646
|
+
it('connects if not already connected', async () => {
|
|
12647
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
12648
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12652
12649
|
|
|
12653
|
-
|
|
12650
|
+
const result = await meeting.updateLLMConnection();
|
|
12651
|
+
|
|
12652
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
12653
|
+
assert.calledWithExactly(
|
|
12654
|
+
webex.internal.llm.registerAndConnect,
|
|
12655
|
+
'a url',
|
|
12656
|
+
'a datachannel url',
|
|
12657
|
+
undefined
|
|
12658
|
+
);
|
|
12659
|
+
assert.equal(result, 'something');
|
|
12660
|
+
});
|
|
12661
|
+
it('disconnects if the locus url has changed', async () => {
|
|
12654
12662
|
meeting.joinedWith = {state: 'JOINED'};
|
|
12663
|
+
|
|
12655
12664
|
webex.internal.llm.isConnected.returns(true);
|
|
12656
12665
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
12657
|
-
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
12658
12666
|
|
|
12659
|
-
meeting.locusInfo = {
|
|
12667
|
+
meeting.locusInfo = {
|
|
12668
|
+
url: 'a different url',
|
|
12669
|
+
info: {datachannelUrl: 'a datachannel url'},
|
|
12670
|
+
self: {}
|
|
12671
|
+
};
|
|
12660
12672
|
|
|
12661
12673
|
const result = await meeting.updateLLMConnection();
|
|
12662
12674
|
|
|
12663
|
-
assert.
|
|
12664
|
-
|
|
12665
|
-
reason: 'done (permanent)'
|
|
12666
|
-
|
|
12667
|
-
|
|
12675
|
+
assert.calledWithExactly(
|
|
12676
|
+
webex.internal.llm.disconnectLLM,
|
|
12677
|
+
{code: 3050, reason: 'done (permanent)'}
|
|
12678
|
+
);
|
|
12679
|
+
|
|
12680
|
+
assert.calledWithExactly(
|
|
12668
12681
|
webex.internal.llm.registerAndConnect,
|
|
12669
12682
|
'a different url',
|
|
12670
|
-
'a datachannel url'
|
|
12683
|
+
'a datachannel url',
|
|
12684
|
+
undefined
|
|
12671
12685
|
);
|
|
12686
|
+
|
|
12672
12687
|
assert.equal(result, 'something');
|
|
12688
|
+
|
|
12673
12689
|
assert.calledWithExactly(
|
|
12674
12690
|
meeting.webex.internal.llm.off,
|
|
12675
12691
|
'event:relay.event',
|
|
@@ -12681,6 +12697,7 @@ describe('plugin-meetings', () => {
|
|
|
12681
12697
|
meeting.processLocusLLMEvent
|
|
12682
12698
|
);
|
|
12683
12699
|
assert.callCount(meeting.webex.internal.llm.off, 4);
|
|
12700
|
+
|
|
12684
12701
|
assert.calledWithExactly(
|
|
12685
12702
|
meeting.webex.internal.llm.on,
|
|
12686
12703
|
'event:relay.event',
|
|
@@ -12692,27 +12709,33 @@ describe('plugin-meetings', () => {
|
|
|
12692
12709
|
meeting.processLocusLLMEvent
|
|
12693
12710
|
);
|
|
12694
12711
|
});
|
|
12695
|
-
|
|
12696
|
-
it('disconnects it first if the data channel url has changed', async () => {
|
|
12712
|
+
it('disconnects if the data channel url has changed', async () => {
|
|
12697
12713
|
meeting.joinedWith = {state: 'JOINED'};
|
|
12698
12714
|
webex.internal.llm.isConnected.returns(true);
|
|
12699
12715
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
12700
|
-
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
12701
12716
|
|
|
12702
|
-
meeting.locusInfo = {
|
|
12717
|
+
meeting.locusInfo = {
|
|
12718
|
+
url: 'a url',
|
|
12719
|
+
info: {datachannelUrl: 'a different datachannel url'},
|
|
12720
|
+
self: {}
|
|
12721
|
+
};
|
|
12703
12722
|
|
|
12704
12723
|
const result = await meeting.updateLLMConnection();
|
|
12705
12724
|
|
|
12706
|
-
assert.
|
|
12707
|
-
|
|
12708
|
-
reason: 'done (permanent)'
|
|
12709
|
-
|
|
12710
|
-
|
|
12725
|
+
assert.calledWithExactly(
|
|
12726
|
+
webex.internal.llm.disconnectLLM,
|
|
12727
|
+
{code: 3050, reason: 'done (permanent)'}
|
|
12728
|
+
);
|
|
12729
|
+
|
|
12730
|
+
assert.calledWithExactly(
|
|
12711
12731
|
webex.internal.llm.registerAndConnect,
|
|
12712
12732
|
'a url',
|
|
12713
|
-
'a different datachannel url'
|
|
12733
|
+
'a different datachannel url',
|
|
12734
|
+
undefined
|
|
12714
12735
|
);
|
|
12736
|
+
|
|
12715
12737
|
assert.equal(result, 'something');
|
|
12738
|
+
|
|
12716
12739
|
assert.calledWithExactly(
|
|
12717
12740
|
meeting.webex.internal.llm.off,
|
|
12718
12741
|
'event:relay.event',
|
|
@@ -12723,6 +12746,7 @@ describe('plugin-meetings', () => {
|
|
|
12723
12746
|
'event:locus.state_message',
|
|
12724
12747
|
meeting.processLocusLLMEvent
|
|
12725
12748
|
);
|
|
12749
|
+
|
|
12726
12750
|
assert.calledWithExactly(
|
|
12727
12751
|
meeting.webex.internal.llm.on,
|
|
12728
12752
|
'event:relay.event',
|
|
@@ -12734,7 +12758,6 @@ describe('plugin-meetings', () => {
|
|
|
12734
12758
|
meeting.processLocusLLMEvent
|
|
12735
12759
|
);
|
|
12736
12760
|
});
|
|
12737
|
-
|
|
12738
12761
|
it('disconnects when the state is not JOINED', async () => {
|
|
12739
12762
|
meeting.joinedWith = {state: 'any other state'};
|
|
12740
12763
|
webex.internal.llm.isConnected.returns(true);
|
|
@@ -12750,32 +12773,134 @@ describe('plugin-meetings', () => {
|
|
|
12750
12773
|
});
|
|
12751
12774
|
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
12752
12775
|
assert.equal(result, undefined);
|
|
12776
|
+
});
|
|
12777
|
+
it('connects practice session data channel when PS started', async () => {
|
|
12778
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
12779
|
+
meeting.locusInfo = {
|
|
12780
|
+
url: 'a url',
|
|
12781
|
+
info: {
|
|
12782
|
+
datachannelUrl: 'a datachannel url',
|
|
12783
|
+
practiceSessionDatachannelUrl: 'ps-url',
|
|
12784
|
+
},
|
|
12785
|
+
};
|
|
12786
|
+
meeting.webinar.isJoinPracticeSessionDataChannel.returns(true);
|
|
12787
|
+
|
|
12788
|
+
await meeting.updateLLMConnection();
|
|
12789
|
+
|
|
12753
12790
|
assert.calledWithExactly(
|
|
12754
|
-
|
|
12755
|
-
'
|
|
12756
|
-
|
|
12791
|
+
webex.internal.llm.registerAndConnect,
|
|
12792
|
+
'a url',
|
|
12793
|
+
'ps-url',
|
|
12794
|
+
undefined
|
|
12757
12795
|
);
|
|
12796
|
+
});
|
|
12797
|
+
it('passes dataChannelToken to registerAndConnect', async () => {
|
|
12798
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
12799
|
+
meeting.locusInfo = {
|
|
12800
|
+
url: 'a url',
|
|
12801
|
+
info: {datachannelUrl: 'a datachannel url'},
|
|
12802
|
+
self: {datachannelToken: 'token-123'},
|
|
12803
|
+
};
|
|
12804
|
+
|
|
12805
|
+
webex.internal.llm.getDatachannelToken.returns(undefined);
|
|
12806
|
+
|
|
12807
|
+
await meeting.updateLLMConnection();
|
|
12808
|
+
|
|
12758
12809
|
assert.calledWithExactly(
|
|
12759
|
-
|
|
12760
|
-
'
|
|
12761
|
-
|
|
12810
|
+
webex.internal.llm.registerAndConnect,
|
|
12811
|
+
'a url',
|
|
12812
|
+
'a datachannel url',
|
|
12813
|
+
'token-123'
|
|
12814
|
+
);
|
|
12815
|
+
assert.calledWithExactly(
|
|
12816
|
+
webex.internal.llm.setDatachannelToken,
|
|
12817
|
+
'token-123',
|
|
12818
|
+
'default'
|
|
12762
12819
|
);
|
|
12763
12820
|
});
|
|
12821
|
+
it('prefers refreshed token over locus self token', async () => {
|
|
12822
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
12823
|
+
meeting.locusInfo = {
|
|
12824
|
+
url: 'a url',
|
|
12825
|
+
info: {datachannelUrl: 'a datachannel url'},
|
|
12826
|
+
self: {datachannelToken: 'locus-token'},
|
|
12827
|
+
};
|
|
12828
|
+
|
|
12829
|
+
webex.internal.llm.getDatachannelToken
|
|
12830
|
+
.withArgs('default')
|
|
12831
|
+
.returns('refreshed-token');
|
|
12832
|
+
|
|
12833
|
+
await meeting.updateLLMConnection();
|
|
12764
12834
|
|
|
12765
|
-
|
|
12835
|
+
assert.calledWithExactly(
|
|
12836
|
+
webex.internal.llm.registerAndConnect,
|
|
12837
|
+
'a url',
|
|
12838
|
+
'a datachannel url',
|
|
12839
|
+
'refreshed-token'
|
|
12840
|
+
);
|
|
12841
|
+
|
|
12842
|
+
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
12843
|
+
});
|
|
12844
|
+
it('uses practice session token when in PS even if refreshed token exists', async () => {
|
|
12766
12845
|
meeting.joinedWith = {state: 'JOINED'};
|
|
12846
|
+
|
|
12767
12847
|
meeting.locusInfo = {
|
|
12768
12848
|
url: 'a url',
|
|
12769
12849
|
info: {
|
|
12770
12850
|
datachannelUrl: 'a datachannel url',
|
|
12771
|
-
practiceSessionDatachannelUrl: '
|
|
12851
|
+
practiceSessionDatachannelUrl: 'ps-url',
|
|
12852
|
+
},
|
|
12853
|
+
self: {
|
|
12854
|
+
datachannelToken: 'locus-token',
|
|
12855
|
+
practiceSessionDatachannelToken: 'ps-token',
|
|
12772
12856
|
},
|
|
12773
12857
|
};
|
|
12774
|
-
|
|
12858
|
+
|
|
12859
|
+
meeting.webinar.isJoinPracticeSessionDataChannel.returns(true);
|
|
12860
|
+
|
|
12861
|
+
webex.internal.llm.getDatachannelToken
|
|
12862
|
+
.withArgs(true).returns('refreshed-ps-token') // refreshed practice token
|
|
12863
|
+
.withArgs(false).returns('refreshed-normal-token'); // refreshed normal token
|
|
12864
|
+
|
|
12775
12865
|
await meeting.updateLLMConnection();
|
|
12776
12866
|
|
|
12777
|
-
assert.
|
|
12778
|
-
|
|
12867
|
+
assert.calledWithExactly(
|
|
12868
|
+
webex.internal.llm.registerAndConnect,
|
|
12869
|
+
'a url',
|
|
12870
|
+
'ps-url',
|
|
12871
|
+
'ps-token'
|
|
12872
|
+
);
|
|
12873
|
+
assert.calledWithExactly(
|
|
12874
|
+
webex.internal.llm.setDatachannelToken,
|
|
12875
|
+
'ps-token',
|
|
12876
|
+
'practiceSession'
|
|
12877
|
+
);
|
|
12878
|
+
});
|
|
12879
|
+
|
|
12880
|
+
it('does not pass token when data channel with jwt token is disabled', async () => {
|
|
12881
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
12882
|
+
meeting.locusInfo = {
|
|
12883
|
+
url: 'a url',
|
|
12884
|
+
info: {datachannelUrl: 'a datachannel url'},
|
|
12885
|
+
self: {datachannelToken: 'token-123'}
|
|
12886
|
+
};
|
|
12887
|
+
|
|
12888
|
+
webex.internal.llm.getDatachannelToken.returns(undefined);
|
|
12889
|
+
webex.internal.llm.isDataChannelTokenEnabled = sinon.stub().resolves(false);
|
|
12890
|
+
|
|
12891
|
+
await meeting.updateLLMConnection();
|
|
12892
|
+
|
|
12893
|
+
assert.calledWithExactly(
|
|
12894
|
+
webex.internal.llm.registerAndConnect,
|
|
12895
|
+
'a url',
|
|
12896
|
+
'a datachannel url',
|
|
12897
|
+
'token-123'
|
|
12898
|
+
);
|
|
12899
|
+
assert.calledWithExactly(
|
|
12900
|
+
webex.internal.llm.setDatachannelToken,
|
|
12901
|
+
'token-123',
|
|
12902
|
+
'default'
|
|
12903
|
+
);
|
|
12779
12904
|
});
|
|
12780
12905
|
});
|
|
12781
12906
|
|
|
@@ -14345,6 +14470,72 @@ describe('plugin-meetings', () => {
|
|
|
14345
14470
|
assert.calledOnce(meeting.meetingRequest.keepAlive);
|
|
14346
14471
|
});
|
|
14347
14472
|
});
|
|
14473
|
+
describe('#refreshDataChannelToken()', () => {
|
|
14474
|
+
let meeting;
|
|
14475
|
+
|
|
14476
|
+
beforeEach(() => {
|
|
14477
|
+
meeting = Object.create(Meeting.prototype);
|
|
14478
|
+
meeting.locusUrl = 'https://locus.example.com';
|
|
14479
|
+
meeting.meetingRequest = {
|
|
14480
|
+
fetchDatachannelToken: sinon.stub().resolves({
|
|
14481
|
+
body: { datachannelToken: 'mock-token' },
|
|
14482
|
+
}),
|
|
14483
|
+
};
|
|
14484
|
+
meeting.members = {
|
|
14485
|
+
selfId: 'self-123',
|
|
14486
|
+
};
|
|
14487
|
+
meeting.webinar = {
|
|
14488
|
+
isJoinPracticeSessionDataChannel: sinon.stub().returns(true),
|
|
14489
|
+
};
|
|
14490
|
+
});
|
|
14491
|
+
|
|
14492
|
+
it('calls fetchDatachannelToken with correct parameters', async () => {
|
|
14493
|
+
await meeting.refreshDataChannelToken();
|
|
14494
|
+
|
|
14495
|
+
sinon.assert.calledOnce(meeting.meetingRequest.fetchDatachannelToken);
|
|
14496
|
+
|
|
14497
|
+
sinon.assert.calledWith(
|
|
14498
|
+
meeting.meetingRequest.fetchDatachannelToken,
|
|
14499
|
+
{
|
|
14500
|
+
locusUrl: 'https://locus.example.com',
|
|
14501
|
+
requestingParticipantId: 'self-123',
|
|
14502
|
+
isPracticeSession: true,
|
|
14503
|
+
}
|
|
14504
|
+
);
|
|
14505
|
+
});
|
|
14506
|
+
|
|
14507
|
+
it('returns the correct structured result', async () => {
|
|
14508
|
+
const result = await meeting.refreshDataChannelToken();
|
|
14509
|
+
|
|
14510
|
+
expect(result).to.deep.equal({
|
|
14511
|
+
body: {
|
|
14512
|
+
datachannelToken: 'mock-token',
|
|
14513
|
+
dataChannelTokenType: 'practiceSession',
|
|
14514
|
+
},
|
|
14515
|
+
});
|
|
14516
|
+
});
|
|
14517
|
+
});
|
|
14518
|
+
describe('#getDataChannelTokenType', () => {
|
|
14519
|
+
it('returns PracticeSession when webinar is in practice session mode', () => {
|
|
14520
|
+
meeting.webinar = {
|
|
14521
|
+
isJoinPracticeSessionDataChannel: sinon.stub().returns(true),
|
|
14522
|
+
};
|
|
14523
|
+
|
|
14524
|
+
const result = meeting.getDataChannelTokenType();
|
|
14525
|
+
|
|
14526
|
+
expect(result).to.equal('practiceSession');
|
|
14527
|
+
});
|
|
14528
|
+
|
|
14529
|
+
it('returns Default when not in practice session mode', () => {
|
|
14530
|
+
meeting.webinar = {
|
|
14531
|
+
isJoinPracticeSessionDataChannel: sinon.stub().returns(false),
|
|
14532
|
+
};
|
|
14533
|
+
|
|
14534
|
+
const result = meeting.getDataChannelTokenType();
|
|
14535
|
+
|
|
14536
|
+
expect(result).to.equal('default');
|
|
14537
|
+
});
|
|
14538
|
+
});
|
|
14348
14539
|
describe('#stopKeepAlive', () => {
|
|
14349
14540
|
let clock;
|
|
14350
14541
|
const defaultKeepAliveUrl = 'keep.alive.url';
|
|
@@ -115,6 +115,7 @@ describe('plugin-meetings', () => {
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
describe('#changeVideoLayout', () => {
|
|
118
|
+
|
|
118
119
|
const locusUrl = 'locusURL';
|
|
119
120
|
const deviceUrl = 'deviceUrl';
|
|
120
121
|
const layoutType = 'Equal';
|
|
@@ -918,4 +919,67 @@ describe('plugin-meetings', () => {
|
|
|
918
919
|
});
|
|
919
920
|
});
|
|
920
921
|
});
|
|
922
|
+
|
|
923
|
+
describe('#fetchDatachannelToken', () => {
|
|
924
|
+
const locusUrl = 'https://locus.example.com/locus/api/v1/loci/123';
|
|
925
|
+
const participantId = 'participant-123';
|
|
926
|
+
|
|
927
|
+
it('sends GET request to regular datachannel token endpoint', async () => {
|
|
928
|
+
await meetingsRequest.fetchDatachannelToken({
|
|
929
|
+
locusUrl,
|
|
930
|
+
requestingParticipantId: participantId,
|
|
931
|
+
isPracticeSession: false,
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
assert.calledOnceWithExactly(locusDeltaRequestSpy, {
|
|
935
|
+
method: 'GET',
|
|
936
|
+
uri: `${locusUrl}/participant/${participantId}/datachannel/token`,
|
|
937
|
+
});
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
it('sends GET request to practice session datachannel token endpoint', async () => {
|
|
941
|
+
await meetingsRequest.fetchDatachannelToken({
|
|
942
|
+
locusUrl,
|
|
943
|
+
requestingParticipantId: participantId,
|
|
944
|
+
isPracticeSession: true,
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
assert.calledOnceWithExactly(locusDeltaRequestSpy, {
|
|
948
|
+
method: 'GET',
|
|
949
|
+
uri: `${locusUrl}/participant/${participantId}/practiceSession/datachannel/token`,
|
|
950
|
+
});
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
it('throws if locusUrl or participantId is missing', async () => {
|
|
954
|
+
await assert.isRejected(
|
|
955
|
+
meetingsRequest.fetchDatachannelToken({
|
|
956
|
+
locusUrl: null,
|
|
957
|
+
requestingParticipantId: participantId,
|
|
958
|
+
}),
|
|
959
|
+
/locusUrl and participantId are required/
|
|
960
|
+
);
|
|
961
|
+
|
|
962
|
+
await assert.isRejected(
|
|
963
|
+
meetingsRequest.fetchDatachannelToken({
|
|
964
|
+
locusUrl,
|
|
965
|
+
requestingParticipantId: null,
|
|
966
|
+
}),
|
|
967
|
+
/locusUrl and participantId are required/
|
|
968
|
+
);
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
it('logs and rethrows error when locusDeltaRequest fails', async () => {
|
|
972
|
+
const error = new Error('network error');
|
|
973
|
+
locusDeltaRequestSpy.restore();
|
|
974
|
+
sinon.stub(meetingsRequest, 'locusDeltaRequest').rejects(error);
|
|
975
|
+
|
|
976
|
+
await assert.isRejected(
|
|
977
|
+
meetingsRequest.fetchDatachannelToken({
|
|
978
|
+
locusUrl,
|
|
979
|
+
requestingParticipantId: participantId,
|
|
980
|
+
}),
|
|
981
|
+
/network error/
|
|
982
|
+
);
|
|
983
|
+
});
|
|
984
|
+
});
|
|
921
985
|
});
|