@webex/plugin-meetings 3.12.0-next.8 → 3.12.0-task-refactor.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/annotation/index.js +5 -14
- 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 +2 -8
- package/dist/config.js.map +1 -1
- package/dist/constants.js +6 -29
- package/dist/constants.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +29 -1563
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/types.js +3 -13
- package/dist/hashTree/types.js.map +1 -1
- package/dist/index.js +2 -11
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +0 -7
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/locusRouteToken.js +5 -27
- package/dist/interceptors/locusRouteToken.js.map +1 -1
- 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 +3 -7
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +247 -642
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +0 -1
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +1 -57
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +2 -4
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +1 -7
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1036 -1481
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +0 -50
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +3 -133
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +59 -142
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +7 -11
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +0 -10
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +0 -10
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +1 -7
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +60 -9
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +0 -11
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +2 -116
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +18 -171
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +11 -21
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachabilityPeerConnection.js +1 -1
- package/dist/reachability/reachabilityPeerConnection.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +1 -0
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/types/common/browser-detection.d.ts +0 -1
- package/dist/types/common/events/events-scope.d.ts +0 -1
- package/dist/types/common/events/events.d.ts +0 -1
- package/dist/types/config.d.ts +0 -5
- package/dist/types/constants.d.ts +1 -24
- package/dist/types/hashTree/hashTreeParser.d.ts +11 -260
- package/dist/types/hashTree/types.d.ts +0 -20
- package/dist/types/index.d.ts +0 -1
- package/dist/types/interceptors/index.d.ts +1 -2
- package/dist/types/interceptors/locusRouteToken.d.ts +0 -2
- package/dist/types/locus-info/index.d.ts +47 -68
- package/dist/types/locus-info/types.d.ts +12 -28
- package/dist/types/media/MediaConnectionAwaiter.d.ts +1 -10
- package/dist/types/media/properties.d.ts +1 -2
- package/dist/types/meeting/in-meeting-actions.d.ts +0 -6
- package/dist/types/meeting/index.d.ts +7 -86
- package/dist/types/meeting/request.d.ts +1 -16
- package/dist/types/meeting/request.type.d.ts +0 -5
- package/dist/types/meeting/util.d.ts +0 -31
- package/dist/types/meeting-info/util.d.ts +0 -1
- package/dist/types/meeting-info/utilv2.d.ts +0 -1
- package/dist/types/meetings/index.d.ts +2 -4
- package/dist/types/member/index.d.ts +0 -1
- package/dist/types/member/types.d.ts +4 -4
- package/dist/types/member/util.d.ts +0 -5
- package/dist/types/metrics/constants.d.ts +0 -6
- package/dist/types/multistream/mediaRequestManager.d.ts +23 -0
- package/dist/types/multistream/sendSlotManager.d.ts +1 -23
- package/dist/types/reachability/clusterReachability.d.ts +3 -30
- package/dist/types/reactions/reactions.type.d.ts +0 -1
- package/dist/types/recording-controller/util.d.ts +5 -5
- package/dist/types/roap/index.d.ts +1 -1
- package/dist/webinar/index.js +163 -438
- package/dist/webinar/index.js.map +1 -1
- package/package.json +24 -26
- package/src/annotation/index.ts +7 -27
- package/src/config.ts +0 -5
- package/src/constants.ts +1 -30
- package/src/hashTree/hashTreeParser.ts +25 -1523
- package/src/hashTree/types.ts +1 -24
- package/src/index.ts +1 -8
- package/src/interceptors/index.ts +1 -2
- package/src/interceptors/locusRouteToken.ts +5 -22
- package/src/interpretation/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +0 -17
- package/src/locus-info/index.ts +213 -707
- package/src/locus-info/selfUtils.ts +0 -1
- package/src/locus-info/types.ts +12 -27
- package/src/media/MediaConnectionAwaiter.ts +1 -41
- package/src/media/properties.ts +1 -3
- package/src/meeting/in-meeting-actions.ts +0 -12
- package/src/meeting/index.ts +84 -461
- package/src/meeting/request.ts +0 -42
- package/src/meeting/request.type.ts +0 -6
- package/src/meeting/util.ts +2 -160
- package/src/meetings/index.ts +60 -180
- package/src/meetings/util.ts +9 -10
- package/src/member/index.ts +0 -10
- package/src/member/util.ts +0 -12
- package/src/metrics/constants.ts +0 -7
- package/src/multistream/mediaRequestManager.ts +54 -4
- package/src/multistream/remoteMediaManager.ts +0 -13
- package/src/multistream/sendSlotManager.ts +3 -97
- package/src/reachability/clusterReachability.ts +27 -153
- package/src/reachability/index.ts +1 -15
- package/src/reachability/reachabilityPeerConnection.ts +1 -3
- package/src/reactions/reactions.type.ts +0 -1
- package/src/reconnection-manager/index.ts +1 -0
- package/src/webinar/index.ts +6 -265
- package/test/unit/spec/annotation/index.ts +7 -69
- package/test/unit/spec/interceptors/locusRouteToken.ts +0 -44
- package/test/unit/spec/locus-info/controlsUtils.js +1 -56
- package/test/unit/spec/locus-info/index.js +90 -1457
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +1 -41
- package/test/unit/spec/media/properties.ts +3 -12
- package/test/unit/spec/meeting/in-meeting-actions.ts +2 -8
- package/test/unit/spec/meeting/index.js +128 -981
- package/test/unit/spec/meeting/request.js +0 -70
- package/test/unit/spec/meeting/utils.js +26 -438
- package/test/unit/spec/meetings/index.js +33 -845
- package/test/unit/spec/meetings/utils.js +1 -51
- package/test/unit/spec/member/index.js +4 -28
- package/test/unit/spec/member/util.js +27 -65
- package/test/unit/spec/multistream/mediaRequestManager.ts +85 -2
- package/test/unit/spec/multistream/remoteMediaManager.ts +0 -30
- package/test/unit/spec/multistream/sendSlotManager.ts +36 -135
- package/test/unit/spec/reachability/clusterReachability.ts +1 -125
- package/test/unit/spec/reachability/index.ts +3 -26
- package/test/unit/spec/reconnection-manager/index.js +8 -4
- package/test/unit/spec/webinar/index.ts +37 -534
- package/dist/aiEnableRequest/index.js +0 -184
- package/dist/aiEnableRequest/index.js.map +0 -1
- package/dist/aiEnableRequest/utils.js +0 -36
- package/dist/aiEnableRequest/utils.js.map +0 -1
- package/dist/hashTree/constants.js +0 -22
- package/dist/hashTree/constants.js.map +0 -1
- package/dist/hashTree/hashTree.js +0 -533
- package/dist/hashTree/hashTree.js.map +0 -1
- package/dist/hashTree/utils.js +0 -69
- package/dist/hashTree/utils.js.map +0 -1
- package/dist/interceptors/constant.js +0 -12
- package/dist/interceptors/constant.js.map +0 -1
- package/dist/interceptors/dataChannelAuthToken.js +0 -290
- package/dist/interceptors/dataChannelAuthToken.js.map +0 -1
- package/dist/interceptors/utils.js +0 -27
- package/dist/interceptors/utils.js.map +0 -1
- package/dist/types/aiEnableRequest/index.d.ts +0 -5
- package/dist/types/aiEnableRequest/utils.d.ts +0 -2
- package/dist/types/hashTree/constants.d.ts +0 -9
- package/dist/types/hashTree/hashTree.d.ts +0 -136
- package/dist/types/hashTree/utils.d.ts +0 -22
- package/dist/types/interceptors/constant.d.ts +0 -5
- package/dist/types/interceptors/dataChannelAuthToken.d.ts +0 -43
- package/dist/types/interceptors/utils.d.ts +0 -1
- package/dist/types/webinar/utils.d.ts +0 -6
- package/dist/webinar/utils.js +0 -25
- package/dist/webinar/utils.js.map +0 -1
- package/src/aiEnableRequest/README.md +0 -84
- package/src/aiEnableRequest/index.ts +0 -170
- package/src/aiEnableRequest/utils.ts +0 -25
- package/src/hashTree/constants.ts +0 -10
- package/src/hashTree/hashTree.ts +0 -480
- package/src/hashTree/utils.ts +0 -62
- package/src/interceptors/constant.ts +0 -6
- package/src/interceptors/dataChannelAuthToken.ts +0 -170
- package/src/interceptors/utils.ts +0 -16
- package/src/webinar/utils.ts +0 -16
- package/test/unit/spec/aiEnableRequest/index.ts +0 -981
- package/test/unit/spec/aiEnableRequest/utils.ts +0 -130
- package/test/unit/spec/hashTree/hashTree.ts +0 -721
- package/test/unit/spec/hashTree/hashTreeParser.ts +0 -3670
- package/test/unit/spec/hashTree/utils.ts +0 -140
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +0 -210
- package/test/unit/spec/interceptors/utils.ts +0 -75
- package/test/unit/spec/webinar/utils.ts +0 -39
|
@@ -38,7 +38,6 @@ import {
|
|
|
38
38
|
import {
|
|
39
39
|
ConnectionState,
|
|
40
40
|
MediaConnectionEventNames,
|
|
41
|
-
MediaCodecMimeType,
|
|
42
41
|
StatsAnalyzerEventNames,
|
|
43
42
|
StatsMonitorEventNames,
|
|
44
43
|
Errors,
|
|
@@ -47,7 +46,6 @@ import {
|
|
|
47
46
|
MediaType,
|
|
48
47
|
} from '@webex/internal-media-core';
|
|
49
48
|
import {LocalStreamEventNames} from '@webex/media-helpers';
|
|
50
|
-
import {CapabilityState, WebCapabilities} from '@webex/web-capabilities';
|
|
51
49
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
52
50
|
import Meetings, {CONSTANTS} from '@webex/plugin-meetings';
|
|
53
51
|
import Meeting from '@webex/plugin-meetings/src/meeting';
|
|
@@ -83,7 +81,6 @@ import Mercury from '@webex/internal-plugin-mercury';
|
|
|
83
81
|
import Breakouts from '@webex/plugin-meetings/src/breakouts';
|
|
84
82
|
import SimultaneousInterpretation from '@webex/plugin-meetings/src/interpretation';
|
|
85
83
|
import Webinar from '@webex/plugin-meetings/src/webinar';
|
|
86
|
-
import AIEnableRequest from '@webex/plugin-meetings/src/aiEnableRequest';
|
|
87
84
|
import {REACTION_RELAY_TYPES} from '../../../../src/reactions/constants';
|
|
88
85
|
import locus from '../fixture/locus';
|
|
89
86
|
import {
|
|
@@ -125,6 +122,7 @@ import {EVENT_TRIGGERS as VOICEAEVENTS} from '@webex/internal-plugin-voicea';
|
|
|
125
122
|
import {createBrbState} from '@webex/plugin-meetings/src/meeting/brbState';
|
|
126
123
|
import JoinForbiddenError from '../../../../src/common/errors/join-forbidden-error';
|
|
127
124
|
import {EventEmitter} from 'stream';
|
|
125
|
+
|
|
128
126
|
describe('plugin-meetings', () => {
|
|
129
127
|
const logger = {
|
|
130
128
|
info: () => {},
|
|
@@ -135,15 +133,11 @@ describe('plugin-meetings', () => {
|
|
|
135
133
|
debug: () => {},
|
|
136
134
|
};
|
|
137
135
|
|
|
138
|
-
let fakeClock;
|
|
139
|
-
|
|
140
136
|
beforeEach(() => {
|
|
141
137
|
sinon.stub(Metrics, 'sendBehavioralMetric');
|
|
142
|
-
fakeClock = sinon.useFakeTimers();
|
|
143
138
|
});
|
|
144
139
|
afterEach(() => {
|
|
145
140
|
sinon.restore();
|
|
146
|
-
fakeClock.restore();
|
|
147
141
|
});
|
|
148
142
|
|
|
149
143
|
before(() => {
|
|
@@ -266,9 +260,7 @@ describe('plugin-meetings', () => {
|
|
|
266
260
|
stopReachability: sinon.stub(),
|
|
267
261
|
isSubnetReachable: sinon.stub().returns(true),
|
|
268
262
|
};
|
|
269
|
-
webex.internal.llm.isDataChannelTokenEnabled = sinon.stub().resolves(false);
|
|
270
263
|
webex.internal.llm.on = sinon.stub();
|
|
271
|
-
webex.internal.voicea.announce = sinon.stub();
|
|
272
264
|
webex.internal.newMetrics.callDiagnosticLatencies = new CallDiagnosticLatencies(
|
|
273
265
|
{},
|
|
274
266
|
{parent: webex}
|
|
@@ -379,7 +371,6 @@ describe('plugin-meetings', () => {
|
|
|
379
371
|
assert.instanceOf(meeting.breakouts, Breakouts);
|
|
380
372
|
assert.instanceOf(meeting.simultaneousInterpretation, SimultaneousInterpretation);
|
|
381
373
|
assert.instanceOf(meeting.webinar, Webinar);
|
|
382
|
-
assert.instanceOf(meeting.aiEnableRequest, AIEnableRequest);
|
|
383
374
|
});
|
|
384
375
|
|
|
385
376
|
it('should call the callback with the meeting that has id already set', () => {
|
|
@@ -739,13 +730,8 @@ describe('plugin-meetings', () => {
|
|
|
739
730
|
let handleTurnDiscoveryHttpResponseStub;
|
|
740
731
|
let abortTurnDiscoveryStub;
|
|
741
732
|
let addMediaInternalStub;
|
|
742
|
-
let supportsRTCPeerConnectionStub;
|
|
743
733
|
|
|
744
734
|
beforeEach(() => {
|
|
745
|
-
supportsRTCPeerConnectionStub = sinon
|
|
746
|
-
.stub(WebCapabilities, 'supportsRTCPeerConnection')
|
|
747
|
-
.returns(CapabilityState.CAPABLE);
|
|
748
|
-
|
|
749
735
|
meeting.join = sinon.stub().callsFake((joinOptions) => {
|
|
750
736
|
meeting.isMultistream = joinOptions.enableMultistream;
|
|
751
737
|
return Promise.resolve(fakeJoinResult);
|
|
@@ -1017,55 +1003,6 @@ describe('plugin-meetings', () => {
|
|
|
1017
1003
|
);
|
|
1018
1004
|
});
|
|
1019
1005
|
|
|
1020
|
-
it('should call leave() if addMediaInternal() fails with a browser media error (TypeError)', async () => {
|
|
1021
|
-
const addMediaError = new Error('fake addMedia error');
|
|
1022
|
-
addMediaError.name = 'TypeError'; // This makes it a browser media error
|
|
1023
|
-
|
|
1024
|
-
const leaveStub = sinon.stub(meeting, 'leave').resolves();
|
|
1025
|
-
meeting.addMediaInternal = sinon.stub().rejects(addMediaError);
|
|
1026
|
-
|
|
1027
|
-
// When a browser media error occurs, it gets transformed into a special structure
|
|
1028
|
-
const rejectedError = await assert.isRejected(
|
|
1029
|
-
meeting.joinWithMedia({
|
|
1030
|
-
joinOptions,
|
|
1031
|
-
mediaOptions,
|
|
1032
|
-
})
|
|
1033
|
-
);
|
|
1034
|
-
|
|
1035
|
-
// Verify the error was transformed with errorCode 2729
|
|
1036
|
-
assert.equal(rejectedError.error.body.errorCode, 2729);
|
|
1037
|
-
assert.equal(rejectedError.error.body.message, 'fake addMedia error');
|
|
1038
|
-
assert.equal(rejectedError.error.body.name, 'TypeError');
|
|
1039
|
-
|
|
1040
|
-
assert.calledOnce(meeting.join);
|
|
1041
|
-
assert.calledOnce(meeting.addMediaInternal);
|
|
1042
|
-
assert.calledOnce(leaveStub);
|
|
1043
|
-
assert.calledOnceWithExactly(leaveStub, {
|
|
1044
|
-
resourceId: undefined,
|
|
1045
|
-
reason: 'joinWithMedia failure',
|
|
1046
|
-
});
|
|
1047
|
-
|
|
1048
|
-
// Browser media errors don't retry, so behavioral metric is sent only once
|
|
1049
|
-
// NOTE: The error gets transformed, so the metric receives undefined for message/stack/name
|
|
1050
|
-
// because they're now nested in error.body instead of at the top level
|
|
1051
|
-
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
1052
|
-
assert.calledWith(
|
|
1053
|
-
Metrics.sendBehavioralMetric,
|
|
1054
|
-
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
1055
|
-
{
|
|
1056
|
-
correlation_id: meeting.correlationId,
|
|
1057
|
-
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1058
|
-
reason: undefined, // transformed error doesn't have .message at top level
|
|
1059
|
-
stack: undefined, // transformed error doesn't have .stack at top level
|
|
1060
|
-
leaveErrorReason: undefined,
|
|
1061
|
-
isRetry: false,
|
|
1062
|
-
},
|
|
1063
|
-
{
|
|
1064
|
-
type: undefined, // transformed error doesn't have .name at top level
|
|
1065
|
-
}
|
|
1066
|
-
);
|
|
1067
|
-
});
|
|
1068
|
-
|
|
1069
1006
|
it('should not call leave() if addMediaInternal() fails the first time and succeeds the second time and should only call join() once', async () => {
|
|
1070
1007
|
const addMediaError = new Error('fake addMedia error');
|
|
1071
1008
|
const leaveStub = sinon.stub(meeting, 'leave');
|
|
@@ -1274,54 +1211,43 @@ describe('plugin-meetings', () => {
|
|
|
1274
1211
|
await assert.isRejected(result);
|
|
1275
1212
|
});
|
|
1276
1213
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
description: 'if we fail to create the offer on first attempt',
|
|
1281
|
-
},
|
|
1282
|
-
{
|
|
1283
|
-
errorName: 'WebrtcApiNotAvailableError',
|
|
1284
|
-
description: 'if RTCPeerConnection is not available',
|
|
1285
|
-
},
|
|
1286
|
-
].forEach(({errorName, description}) => {
|
|
1287
|
-
it(`should not attempt a retry ${description}`, async () => {
|
|
1288
|
-
const addMediaError = new Error('fake addMedia error');
|
|
1289
|
-
addMediaError.name = errorName;
|
|
1214
|
+
it('should not attempt a retry if we fail to create the offer on first atttempt', async () => {
|
|
1215
|
+
const addMediaError = new Error('fake addMedia error');
|
|
1216
|
+
addMediaError.name = 'SdpOfferCreationError';
|
|
1290
1217
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1218
|
+
meeting.addMediaInternal.rejects(addMediaError);
|
|
1219
|
+
sinon.stub(meeting, 'leave').resolves();
|
|
1293
1220
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1221
|
+
await assert.isRejected(
|
|
1222
|
+
meeting.joinWithMedia({
|
|
1223
|
+
joinOptions,
|
|
1224
|
+
mediaOptions,
|
|
1225
|
+
}),
|
|
1226
|
+
addMediaError
|
|
1227
|
+
);
|
|
1301
1228
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
});
|
|
1229
|
+
// check that only 1 attempt was done
|
|
1230
|
+
assert.calledOnce(meeting.join);
|
|
1231
|
+
assert.calledOnce(meeting.addMediaInternal);
|
|
1232
|
+
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
1233
|
+
assert.calledWith(
|
|
1234
|
+
Metrics.sendBehavioralMetric.firstCall,
|
|
1235
|
+
BEHAVIORAL_METRICS.JOIN_WITH_MEDIA_FAILURE,
|
|
1236
|
+
{
|
|
1237
|
+
correlation_id: meeting.correlationId,
|
|
1238
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1239
|
+
reason: addMediaError.message,
|
|
1240
|
+
stack: addMediaError.stack,
|
|
1241
|
+
leaveErrorReason: undefined,
|
|
1242
|
+
isRetry: false,
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
type: addMediaError.name,
|
|
1246
|
+
}
|
|
1247
|
+
);
|
|
1248
|
+
assert.calledOnceWithExactly(meeting.leave, {
|
|
1249
|
+
resourceId: undefined,
|
|
1250
|
+
reason: 'joinWithMedia failure',
|
|
1325
1251
|
});
|
|
1326
1252
|
});
|
|
1327
1253
|
|
|
@@ -1390,21 +1316,6 @@ describe('plugin-meetings', () => {
|
|
|
1390
1316
|
})
|
|
1391
1317
|
);
|
|
1392
1318
|
});
|
|
1393
|
-
|
|
1394
|
-
it('should throw immediately if RTCPeerConnection is not available', async () => {
|
|
1395
|
-
supportsRTCPeerConnectionStub.returns(CapabilityState.NOT_CAPABLE);
|
|
1396
|
-
|
|
1397
|
-
await assert.isRejected(
|
|
1398
|
-
meeting.joinWithMedia({
|
|
1399
|
-
joinOptions,
|
|
1400
|
-
mediaOptions,
|
|
1401
|
-
}),
|
|
1402
|
-
Errors.WebrtcApiNotAvailableError
|
|
1403
|
-
);
|
|
1404
|
-
|
|
1405
|
-
assert.notCalled(meeting.join);
|
|
1406
|
-
assert.notCalled(meeting.addMediaInternal);
|
|
1407
|
-
});
|
|
1408
1319
|
});
|
|
1409
1320
|
describe('#isTranscriptionSupported', () => {
|
|
1410
1321
|
it('should return false if the feature is not supported for the meeting', () => {
|
|
@@ -1419,25 +1330,6 @@ describe('plugin-meetings', () => {
|
|
|
1419
1330
|
});
|
|
1420
1331
|
});
|
|
1421
1332
|
|
|
1422
|
-
describe('#update hesiod llm id', () => {
|
|
1423
|
-
beforeEach(() => {
|
|
1424
|
-
webex.internal.voicea.onCaptionServiceIdUpdate = sinon.stub();
|
|
1425
|
-
});
|
|
1426
|
-
afterEach(() => {
|
|
1427
|
-
// Restore the original methods after each test
|
|
1428
|
-
sinon.restore();
|
|
1429
|
-
});
|
|
1430
|
-
it('should call voicea.onCaptionServiceIdUpdate when joined', async () => {
|
|
1431
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
1432
|
-
await meeting.locusInfo.emitScoped(
|
|
1433
|
-
{function: 'test', file: 'test'},
|
|
1434
|
-
LOCUSINFO.EVENTS.CONTROLS_MEETING_HESIOD_LLM_ID_UPDATED,
|
|
1435
|
-
{hesiodLlmId: '123a-456b-789c'}
|
|
1436
|
-
);
|
|
1437
|
-
assert.calledWith(webex.internal.voicea.onCaptionServiceIdUpdate, '123a-456b-789c');
|
|
1438
|
-
});
|
|
1439
|
-
});
|
|
1440
|
-
|
|
1441
1333
|
describe('#update spoken language', () => {
|
|
1442
1334
|
beforeEach(() => {
|
|
1443
1335
|
webex.internal.voicea.onSpokenLanguageUpdate = sinon.stub();
|
|
@@ -1553,22 +1445,6 @@ describe('plugin-meetings', () => {
|
|
|
1553
1445
|
EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION
|
|
1554
1446
|
);
|
|
1555
1447
|
});
|
|
1556
|
-
|
|
1557
|
-
it('should stop listening to voicea events even when transcription is undefined', () => {
|
|
1558
|
-
meeting.transcription = undefined;
|
|
1559
|
-
meeting.stopTranscription();
|
|
1560
|
-
assert.equal(webex.internal.voicea.off.callCount, 4);
|
|
1561
|
-
assert.equal(meeting.areVoiceaEventsSetup, false);
|
|
1562
|
-
assert.calledWith(
|
|
1563
|
-
TriggerProxy.trigger,
|
|
1564
|
-
sinon.match.instanceOf(Meeting),
|
|
1565
|
-
{
|
|
1566
|
-
file: 'meeting/index',
|
|
1567
|
-
function: 'triggerStopReceivingTranscriptionEvent',
|
|
1568
|
-
},
|
|
1569
|
-
EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION
|
|
1570
|
-
);
|
|
1571
|
-
});
|
|
1572
1448
|
});
|
|
1573
1449
|
|
|
1574
1450
|
describe('#setCaptionLanguage', () => {
|
|
@@ -1930,64 +1806,16 @@ describe('plugin-meetings', () => {
|
|
|
1930
1806
|
fakeProcessedReaction
|
|
1931
1807
|
);
|
|
1932
1808
|
});
|
|
1933
|
-
|
|
1934
|
-
it('should process if participantId does not exist in membersCollection but has displayName in Webinar', () => {
|
|
1935
|
-
LoggerProxy.logger.warn = sinon.stub();
|
|
1936
|
-
meeting.isReactionsSupported = sinon.stub().returns(true);
|
|
1937
|
-
meeting.config.receiveReactions = true;
|
|
1938
|
-
meeting.locusInfo.info = {isWebinar: true};
|
|
1939
|
-
const fakeSendersName = 'Fake reactors name';
|
|
1940
|
-
const fakeReactionPayload = {
|
|
1941
|
-
type: 'fake_type',
|
|
1942
|
-
codepoints: 'fake_codepoints',
|
|
1943
|
-
shortcodes: 'fake_shortcodes',
|
|
1944
|
-
tone: {
|
|
1945
|
-
type: 'fake_tone_type',
|
|
1946
|
-
codepoints: 'fake_tone_codepoints',
|
|
1947
|
-
shortcodes: 'fake_tone_shortcodes',
|
|
1948
|
-
},
|
|
1949
|
-
};
|
|
1950
|
-
const fakeSenderPayload = {
|
|
1951
|
-
displayName: 'Fake reactors name',
|
|
1952
|
-
participantId: 'fake_participant_id',
|
|
1953
|
-
};
|
|
1954
|
-
const fakeProcessedReaction = {
|
|
1955
|
-
reaction: fakeReactionPayload,
|
|
1956
|
-
sender: {
|
|
1957
|
-
id: fakeSenderPayload.participantId,
|
|
1958
|
-
name: fakeSendersName,
|
|
1959
|
-
},
|
|
1960
|
-
};
|
|
1961
|
-
const fakeRelayEvent = {
|
|
1962
|
-
data: {
|
|
1963
|
-
relayType: REACTION_RELAY_TYPES.REACTION,
|
|
1964
|
-
reaction: fakeReactionPayload,
|
|
1965
|
-
sender: fakeSenderPayload,
|
|
1966
|
-
},
|
|
1967
|
-
};
|
|
1968
|
-
meeting.processRelayEvent(fakeRelayEvent);
|
|
1969
|
-
assert.calledWith(
|
|
1970
|
-
TriggerProxy.trigger,
|
|
1971
|
-
sinon.match.instanceOf(Meeting),
|
|
1972
|
-
{
|
|
1973
|
-
file: 'meeting/index',
|
|
1974
|
-
function: 'join',
|
|
1975
|
-
},
|
|
1976
|
-
EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
|
|
1977
|
-
fakeProcessedReaction
|
|
1978
|
-
);
|
|
1979
|
-
});
|
|
1980
1809
|
});
|
|
1981
1810
|
|
|
1982
1811
|
describe('#handleLLMOnline', () => {
|
|
1983
1812
|
beforeEach(() => {
|
|
1984
1813
|
webex.internal.llm.off = sinon.stub();
|
|
1985
|
-
webex.internal.voicea.getIsCaptionBoxOn = sinon.stub().returns(false);
|
|
1986
|
-
webex.internal.voicea.updateSubchannelSubscriptions = sinon.stub();
|
|
1987
1814
|
});
|
|
1988
1815
|
|
|
1989
|
-
it('emits transcription connected events', () => {
|
|
1816
|
+
it('turns off llm online, emits transcription connected events', () => {
|
|
1990
1817
|
meeting.handleLLMOnline();
|
|
1818
|
+
assert.calledOnceWithExactly(webex.internal.llm.off, 'online', meeting.handleLLMOnline);
|
|
1991
1819
|
assert.calledWith(
|
|
1992
1820
|
TriggerProxy.trigger,
|
|
1993
1821
|
sinon.match.instanceOf(Meeting),
|
|
@@ -1998,24 +1826,6 @@ describe('plugin-meetings', () => {
|
|
|
1998
1826
|
EVENT_TRIGGERS.MEETING_TRANSCRIPTION_CONNECTED
|
|
1999
1827
|
);
|
|
2000
1828
|
});
|
|
2001
|
-
|
|
2002
|
-
it('restores transcription subscription when caption intent is enabled', () => {
|
|
2003
|
-
webex.internal.voicea.getIsCaptionBoxOn.returns(true);
|
|
2004
|
-
|
|
2005
|
-
meeting.handleLLMOnline();
|
|
2006
|
-
|
|
2007
|
-
assert.calledOnceWithExactly(webex.internal.voicea.updateSubchannelSubscriptions, {
|
|
2008
|
-
subscribe: ['transcription'],
|
|
2009
|
-
});
|
|
2010
|
-
});
|
|
2011
|
-
|
|
2012
|
-
it('does not restore transcription subscription when caption intent is disabled', () => {
|
|
2013
|
-
webex.internal.voicea.getIsCaptionBoxOn.returns(false);
|
|
2014
|
-
|
|
2015
|
-
meeting.handleLLMOnline();
|
|
2016
|
-
|
|
2017
|
-
assert.notCalled(webex.internal.voicea.updateSubchannelSubscriptions);
|
|
2018
|
-
});
|
|
2019
1829
|
});
|
|
2020
1830
|
|
|
2021
1831
|
describe('#join', () => {
|
|
@@ -2035,7 +1845,6 @@ describe('plugin-meetings', () => {
|
|
|
2035
1845
|
it('should have #join', () => {
|
|
2036
1846
|
assert.exists(meeting.join);
|
|
2037
1847
|
});
|
|
2038
|
-
|
|
2039
1848
|
beforeEach(() => {
|
|
2040
1849
|
setCorrelationIdSpy = sinon.spy(meeting, 'setCorrelationId');
|
|
2041
1850
|
meeting.setLocus = sinon.stub().returns(true);
|
|
@@ -2189,6 +1998,7 @@ describe('plugin-meetings', () => {
|
|
|
2189
1998
|
await meeting.join().catch(() => {
|
|
2190
1999
|
assert.calledOnce(MeetingUtil.joinMeeting);
|
|
2191
2000
|
|
|
2001
|
+
// Assert that client.locus.join.response error event is not sent from this function, it is now emitted from MeetingUtil.joinMeeting
|
|
2192
2002
|
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
|
2193
2003
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
2194
2004
|
name: 'client.call.initiated',
|
|
@@ -2220,7 +2030,6 @@ describe('plugin-meetings', () => {
|
|
|
2220
2030
|
});
|
|
2221
2031
|
});
|
|
2222
2032
|
});
|
|
2223
|
-
|
|
2224
2033
|
describe('lmm, transcription & permissionTokenRefresh decoupling', () => {
|
|
2225
2034
|
beforeEach(() => {
|
|
2226
2035
|
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
|
|
@@ -2291,6 +2100,7 @@ describe('plugin-meetings', () => {
|
|
|
2291
2100
|
const locusInfoParseStub = sinon.stub(meeting.locusInfo, 'parse');
|
|
2292
2101
|
sinon.stub(meeting, 'isJoined').returns(true);
|
|
2293
2102
|
|
|
2103
|
+
// Set up llm.on stub to capture the registered listener when updateLLMConnection is called
|
|
2294
2104
|
let locusLLMEventListener;
|
|
2295
2105
|
meeting.webex.internal.llm.on = sinon.stub().callsFake((eventName, callback) => {
|
|
2296
2106
|
if (eventName === 'event:locus.state_message') {
|
|
@@ -2299,12 +2109,16 @@ describe('plugin-meetings', () => {
|
|
|
2299
2109
|
});
|
|
2300
2110
|
meeting.webex.internal.llm.off = sinon.stub();
|
|
2301
2111
|
|
|
2112
|
+
// we need the real meeting.updateLLMConnection not the mock
|
|
2302
2113
|
meeting.updateLLMConnection.restore();
|
|
2303
2114
|
|
|
2115
|
+
// Call updateLLMConnection to register the listener
|
|
2304
2116
|
await meeting.updateLLMConnection();
|
|
2305
2117
|
|
|
2118
|
+
// Verify the listener was registered and we captured it
|
|
2306
2119
|
assert.isDefined(locusLLMEventListener, 'LLM event listener should be registered');
|
|
2307
2120
|
|
|
2121
|
+
// Now trigger the event
|
|
2308
2122
|
const eventData = {
|
|
2309
2123
|
eventType: 'locus.state_message',
|
|
2310
2124
|
stateElementsMessage: {
|
|
@@ -2317,66 +2131,6 @@ describe('plugin-meetings', () => {
|
|
|
2317
2131
|
|
|
2318
2132
|
assert.calledOnceWithExactly(locusInfoParseStub, meeting, eventData);
|
|
2319
2133
|
});
|
|
2320
|
-
|
|
2321
|
-
it('UpdateLLMConnection sends a metric if not connected after timeout', async () => {
|
|
2322
|
-
sinon.stub(meeting, 'isJoined').returns(true);
|
|
2323
|
-
sinon.stub(meeting.webex.internal.llm, 'isConnected').returns(false);
|
|
2324
|
-
sinon.stub(meeting.webex.internal.llm, 'hasEverConnected').value(true);
|
|
2325
|
-
sinon.stub(meeting.webex.internal.llm, 'registerAndConnect').resolves({});
|
|
2326
|
-
|
|
2327
|
-
meeting.updateLLMConnection.restore();
|
|
2328
|
-
|
|
2329
|
-
await meeting.updateLLMConnection();
|
|
2330
|
-
|
|
2331
|
-
fakeClock.tick(3 * 60 * 1000);
|
|
2332
|
-
|
|
2333
|
-
assert.calledWith(
|
|
2334
|
-
Metrics.sendBehavioralMetric,
|
|
2335
|
-
BEHAVIORAL_METRICS.LLM_HEALTHCHECK_FAILURE,
|
|
2336
|
-
{
|
|
2337
|
-
correlation_id: meeting.correlationId,
|
|
2338
|
-
hasEverConnected: true,
|
|
2339
|
-
}
|
|
2340
|
-
);
|
|
2341
|
-
});
|
|
2342
|
-
|
|
2343
|
-
it('clears the LLM health check timer when disconnecting LLM', async () => {
|
|
2344
|
-
const isJoinedStub = sinon.stub(meeting, 'isJoined');
|
|
2345
|
-
sinon.stub(meeting.webex.internal.llm, 'isConnected');
|
|
2346
|
-
sinon.stub(meeting.webex.internal.llm, 'disconnectLLM').resolves();
|
|
2347
|
-
sinon.stub(meeting.webex.internal.llm, 'registerAndConnect').resolves({});
|
|
2348
|
-
sinon
|
|
2349
|
-
.stub(meeting.webex.internal.llm, 'getLocusUrl')
|
|
2350
|
-
.returns('https://locus1.example.com');
|
|
2351
|
-
sinon
|
|
2352
|
-
.stub(meeting.webex.internal.llm, 'getDatachannelUrl')
|
|
2353
|
-
.returns('https://datachannel1.example.com');
|
|
2354
|
-
|
|
2355
|
-
meeting.updateLLMConnection.restore();
|
|
2356
|
-
|
|
2357
|
-
isJoinedStub.returns(true);
|
|
2358
|
-
meeting.webex.internal.llm.isConnected.returns(false);
|
|
2359
|
-
await meeting.updateLLMConnection();
|
|
2360
|
-
|
|
2361
|
-
assert.exists(meeting.llmHealthCheckTimer);
|
|
2362
|
-
|
|
2363
|
-
isJoinedStub.returns(false);
|
|
2364
|
-
meeting.webex.internal.llm.isConnected.returns(true);
|
|
2365
|
-
|
|
2366
|
-
await meeting.updateLLMConnection();
|
|
2367
|
-
|
|
2368
|
-
assert.calledOnce(meeting.webex.internal.llm.disconnectLLM);
|
|
2369
|
-
|
|
2370
|
-
assert.isUndefined(meeting.llmHealthCheckTimer);
|
|
2371
|
-
|
|
2372
|
-
Metrics.sendBehavioralMetric.resetHistory();
|
|
2373
|
-
fakeClock.tick(3 * 60 * 1000);
|
|
2374
|
-
|
|
2375
|
-
assert.neverCalledWith(
|
|
2376
|
-
Metrics.sendBehavioralMetric,
|
|
2377
|
-
BEHAVIORAL_METRICS.LLM_HEALTHCHECK_FAILURE
|
|
2378
|
-
);
|
|
2379
|
-
});
|
|
2380
2134
|
});
|
|
2381
2135
|
|
|
2382
2136
|
describe('refreshPermissionToken', () => {
|
|
@@ -2403,6 +2157,7 @@ describe('plugin-meetings', () => {
|
|
|
2403
2157
|
.stub()
|
|
2404
2158
|
.rejects(new CaptchaError('bad captcha'));
|
|
2405
2159
|
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
2160
|
+
const joinMeetingOptionsSpy = sinon.spy(MeetingUtil, 'joinMeetingOptions');
|
|
2406
2161
|
|
|
2407
2162
|
try {
|
|
2408
2163
|
await meeting.join();
|
|
@@ -2416,7 +2171,8 @@ describe('plugin-meetings', () => {
|
|
|
2416
2171
|
);
|
|
2417
2172
|
assert.instanceOf(error, CaptchaError);
|
|
2418
2173
|
assert.equal(error.message, 'bad captcha');
|
|
2419
|
-
|
|
2174
|
+
// should not get to the end promise chain, which does do the join
|
|
2175
|
+
assert.notCalled(joinMeetingOptionsSpy);
|
|
2420
2176
|
}
|
|
2421
2177
|
});
|
|
2422
2178
|
|
|
@@ -2425,6 +2181,7 @@ describe('plugin-meetings', () => {
|
|
|
2425
2181
|
.stub()
|
|
2426
2182
|
.rejects(new PasswordError('bad password'));
|
|
2427
2183
|
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
2184
|
+
const joinMeetingOptionsSpy = sinon.spy(MeetingUtil.joinMeetingOptions);
|
|
2428
2185
|
|
|
2429
2186
|
try {
|
|
2430
2187
|
await meeting.join();
|
|
@@ -2438,7 +2195,8 @@ describe('plugin-meetings', () => {
|
|
|
2438
2195
|
);
|
|
2439
2196
|
assert.instanceOf(error, PasswordError);
|
|
2440
2197
|
assert.equal(error.message, 'bad password');
|
|
2441
|
-
|
|
2198
|
+
// should not get to the end promise chain, which does do the join
|
|
2199
|
+
assert.notCalled(joinMeetingOptionsSpy);
|
|
2442
2200
|
}
|
|
2443
2201
|
});
|
|
2444
2202
|
|
|
@@ -2447,6 +2205,7 @@ describe('plugin-meetings', () => {
|
|
|
2447
2205
|
.stub()
|
|
2448
2206
|
.rejects(new PermissionError('bad permission'));
|
|
2449
2207
|
const stateMachineFailSpy = sinon.spy(meeting.meetingFiniteStateMachine, 'fail');
|
|
2208
|
+
const joinMeetingOptionsSpy = sinon.spy(MeetingUtil.joinMeetingOptions);
|
|
2450
2209
|
|
|
2451
2210
|
try {
|
|
2452
2211
|
await meeting.join();
|
|
@@ -2460,14 +2219,14 @@ describe('plugin-meetings', () => {
|
|
|
2460
2219
|
);
|
|
2461
2220
|
assert.instanceOf(error, PermissionError);
|
|
2462
2221
|
assert.equal(error.message, 'bad permission');
|
|
2463
|
-
|
|
2222
|
+
// should not get to the end promise chain, which does do the join
|
|
2223
|
+
assert.notCalled(joinMeetingOptionsSpy);
|
|
2464
2224
|
}
|
|
2465
2225
|
});
|
|
2466
2226
|
});
|
|
2467
2227
|
});
|
|
2468
2228
|
});
|
|
2469
2229
|
|
|
2470
|
-
|
|
2471
2230
|
describe('#addMedia', () => {
|
|
2472
2231
|
const muteStateStub = {
|
|
2473
2232
|
handleClientRequest: sinon.stub().returns(Promise.resolve(true)),
|
|
@@ -3124,111 +2883,6 @@ describe('plugin-meetings', () => {
|
|
|
3124
2883
|
checkWorking({allowMediaInLobby: true});
|
|
3125
2884
|
});
|
|
3126
2885
|
|
|
3127
|
-
const setupLobbyTest = () => {
|
|
3128
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
3129
|
-
.stub()
|
|
3130
|
-
.resolves({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});
|
|
3131
|
-
|
|
3132
|
-
meeting.meetingState = 'ACTIVE';
|
|
3133
|
-
meeting.locusInfo.parsedLocus = {self: {state: 'IDLE'}};
|
|
3134
|
-
meeting.isUserUnadmitted = true;
|
|
3135
|
-
|
|
3136
|
-
// Mock locusMediaRequest
|
|
3137
|
-
meeting.locusMediaRequest = {
|
|
3138
|
-
send: sinon.stub().resolves(),
|
|
3139
|
-
isConfluenceCreated: sinon.stub().returns(false),
|
|
3140
|
-
};
|
|
3141
|
-
|
|
3142
|
-
sinon.stub(RemoteMediaManagerModule, 'RemoteMediaManager').returns({
|
|
3143
|
-
start: sinon.stub().resolves(),
|
|
3144
|
-
on: sinon.stub(),
|
|
3145
|
-
logAllReceiveSlots: sinon.stub(),
|
|
3146
|
-
});
|
|
3147
|
-
|
|
3148
|
-
meeting.isMultistream = true;
|
|
3149
|
-
|
|
3150
|
-
const createFakeStream = (id) => ({
|
|
3151
|
-
on: sinon.stub(),
|
|
3152
|
-
off: sinon.stub(),
|
|
3153
|
-
userMuted: false,
|
|
3154
|
-
systemMuted: false,
|
|
3155
|
-
get muted() {
|
|
3156
|
-
return this.userMuted || this.systemMuted;
|
|
3157
|
-
},
|
|
3158
|
-
setUnmuteAllowed: sinon.stub(),
|
|
3159
|
-
setUserMuted: sinon.stub(),
|
|
3160
|
-
outputStream: {
|
|
3161
|
-
getTracks: () => [{id}],
|
|
3162
|
-
},
|
|
3163
|
-
getSettings: sinon.stub().returns({}),
|
|
3164
|
-
});
|
|
3165
|
-
|
|
3166
|
-
return {
|
|
3167
|
-
fakeMicrophoneStream: createFakeStream('fake mic'),
|
|
3168
|
-
fakeCameraStream: createFakeStream('fake camera'),
|
|
3169
|
-
};
|
|
3170
|
-
};
|
|
3171
|
-
|
|
3172
|
-
it('should not publish any local streams when in the lobby and allowPublishMediaInLobby is false', async () => {
|
|
3173
|
-
const {fakeMicrophoneStream, fakeCameraStream} = setupLobbyTest();
|
|
3174
|
-
|
|
3175
|
-
const publishStreamStub = sinon.stub();
|
|
3176
|
-
fakeMediaConnection.createSendSlot = sinon.stub().returns({
|
|
3177
|
-
publishStream: publishStreamStub,
|
|
3178
|
-
unpublishStream: sinon.stub(),
|
|
3179
|
-
setNamedMediaGroups: sinon.stub(),
|
|
3180
|
-
});
|
|
3181
|
-
|
|
3182
|
-
await meeting.addMedia({
|
|
3183
|
-
allowMediaInLobby: true,
|
|
3184
|
-
allowPublishMediaInLobby: false,
|
|
3185
|
-
audioEnabled: true,
|
|
3186
|
-
videoEnabled: true,
|
|
3187
|
-
localStreams: {
|
|
3188
|
-
microphone: fakeMicrophoneStream,
|
|
3189
|
-
camera: fakeCameraStream,
|
|
3190
|
-
},
|
|
3191
|
-
});
|
|
3192
|
-
|
|
3193
|
-
assert.notCalled(publishStreamStub);
|
|
3194
|
-
});
|
|
3195
|
-
|
|
3196
|
-
it('should publish local streams when in the lobby and allowPublishMediaInLobby is true', async () => {
|
|
3197
|
-
const {fakeMicrophoneStream, fakeCameraStream} = setupLobbyTest();
|
|
3198
|
-
|
|
3199
|
-
const audioSlot = {
|
|
3200
|
-
publishStream: sinon.stub(),
|
|
3201
|
-
unpublishStream: sinon.stub(),
|
|
3202
|
-
setNamedMediaGroups: sinon.stub(),
|
|
3203
|
-
};
|
|
3204
|
-
const videoSlot = {
|
|
3205
|
-
publishStream: sinon.stub(),
|
|
3206
|
-
unpublishStream: sinon.stub(),
|
|
3207
|
-
setNamedMediaGroups: sinon.stub(),
|
|
3208
|
-
};
|
|
3209
|
-
|
|
3210
|
-
fakeMediaConnection.createSendSlot = sinon.stub().callsFake((mediaType) => {
|
|
3211
|
-
if (mediaType === 'AUDIO-MAIN') {
|
|
3212
|
-
return audioSlot;
|
|
3213
|
-
}
|
|
3214
|
-
return videoSlot;
|
|
3215
|
-
});
|
|
3216
|
-
|
|
3217
|
-
await meeting.addMedia({
|
|
3218
|
-
allowMediaInLobby: true,
|
|
3219
|
-
allowPublishMediaInLobby: true,
|
|
3220
|
-
audioEnabled: true,
|
|
3221
|
-
videoEnabled: true,
|
|
3222
|
-
localStreams: {
|
|
3223
|
-
microphone: fakeMicrophoneStream,
|
|
3224
|
-
camera: fakeCameraStream,
|
|
3225
|
-
},
|
|
3226
|
-
});
|
|
3227
|
-
|
|
3228
|
-
assert.calledOnceWithExactly(audioSlot.publishStream, fakeMicrophoneStream);
|
|
3229
|
-
assert.calledOnceWithExactly(videoSlot.publishStream, fakeCameraStream);
|
|
3230
|
-
});
|
|
3231
|
-
|
|
3232
2886
|
it('should create rtcMetrics and pass them to Media.createMediaConnection()', async () => {
|
|
3233
2887
|
const setIntervalOriginal = window.setInterval;
|
|
3234
2888
|
window.setInterval = sinon.stub().returns(1);
|
|
@@ -6419,10 +6073,7 @@ describe('plugin-meetings', () => {
|
|
|
6419
6073
|
meeting.statsAnalyzer = {stopAnalyzer: sinon.stub().resolves()};
|
|
6420
6074
|
meeting.unsetPeerConnections = sinon.stub().returns(true);
|
|
6421
6075
|
meeting.logger.error = sinon.stub().returns(true);
|
|
6422
|
-
meeting.
|
|
6423
|
-
meeting.audio = null;
|
|
6424
|
-
meeting.video = null;
|
|
6425
|
-
});
|
|
6076
|
+
meeting.updateLLMConnection = sinon.stub().returns(Promise.resolve());
|
|
6426
6077
|
webex.internal.voicea.off = sinon.stub().returns(true);
|
|
6427
6078
|
meeting.stopTranscription = sinon.stub();
|
|
6428
6079
|
meeting.transcription = {};
|
|
@@ -6449,7 +6100,9 @@ describe('plugin-meetings', () => {
|
|
|
6449
6100
|
assert.calledOnce(meeting.closePeerConnections);
|
|
6450
6101
|
assert.calledOnce(meeting.unsetRemoteStreams);
|
|
6451
6102
|
assert.calledOnce(meeting.unsetPeerConnections);
|
|
6452
|
-
assert.calledOnce(meeting.
|
|
6103
|
+
assert.calledOnce(meeting.stopTranscription);
|
|
6104
|
+
assert.calledOnce(meeting.annotation.deregisterEvents);
|
|
6105
|
+
assert.calledWith(webex.internal.llm.off, 'event:relay.event', meeting.processRelayEvent);
|
|
6453
6106
|
});
|
|
6454
6107
|
|
|
6455
6108
|
it('should reset call diagnostic latencies correctly', async () => {
|
|
@@ -8450,10 +8103,7 @@ describe('plugin-meetings', () => {
|
|
|
8450
8103
|
meeting.statsAnalyzer = {stopAnalyzer: sinon.stub().resolves()};
|
|
8451
8104
|
meeting.unsetPeerConnections = sinon.stub().returns(true);
|
|
8452
8105
|
meeting.logger.error = sinon.stub().returns(true);
|
|
8453
|
-
meeting.
|
|
8454
|
-
meeting.audio = null;
|
|
8455
|
-
meeting.video = null;
|
|
8456
|
-
});
|
|
8106
|
+
meeting.updateLLMConnection = sinon.stub().returns(Promise.resolve());
|
|
8457
8107
|
meeting.transcription = {};
|
|
8458
8108
|
meeting.stopTranscription = sinon.stub();
|
|
8459
8109
|
|
|
@@ -8479,7 +8129,10 @@ describe('plugin-meetings', () => {
|
|
|
8479
8129
|
assert.calledOnce(meeting?.closePeerConnections);
|
|
8480
8130
|
assert.calledOnce(meeting?.unsetRemoteStreams);
|
|
8481
8131
|
assert.calledOnce(meeting?.unsetPeerConnections);
|
|
8482
|
-
assert.calledOnce(meeting?.
|
|
8132
|
+
assert.calledOnce(meeting?.stopTranscription);
|
|
8133
|
+
|
|
8134
|
+
assert.called(meeting.annotation.deregisterEvents);
|
|
8135
|
+
assert.calledWith(webex.internal.llm.off, 'event:relay.event', meeting.processRelayEvent);
|
|
8483
8136
|
});
|
|
8484
8137
|
});
|
|
8485
8138
|
|
|
@@ -9216,8 +8869,8 @@ describe('plugin-meetings', () => {
|
|
|
9216
8869
|
const fakeMultistreamRoapMediaConnection = {
|
|
9217
8870
|
createSendSlot: () => {
|
|
9218
8871
|
return {
|
|
9219
|
-
|
|
9220
|
-
|
|
8872
|
+
setCodecParameters: sinon.stub().resolves(),
|
|
8873
|
+
deleteCodecParameters: sinon.stub().resolves(),
|
|
9221
8874
|
};
|
|
9222
8875
|
},
|
|
9223
8876
|
};
|
|
@@ -9240,29 +8893,27 @@ describe('plugin-meetings', () => {
|
|
|
9240
8893
|
}
|
|
9241
8894
|
);
|
|
9242
8895
|
|
|
9243
|
-
it('should set
|
|
8896
|
+
it('should set the codec parameters when shouldEnableMusicMode is true', async () => {
|
|
9244
8897
|
await meeting.enableMusicMode(true);
|
|
9245
8898
|
assert.calledOnceWithExactly(
|
|
9246
|
-
meeting.sendSlotManager.getSlot(MediaType.AudioMain).
|
|
9247
|
-
MediaCodecMimeType.OPUS,
|
|
8899
|
+
meeting.sendSlotManager.getSlot(MediaType.AudioMain).setCodecParameters,
|
|
9248
8900
|
{
|
|
9249
8901
|
maxaveragebitrate: '64000',
|
|
9250
8902
|
maxplaybackrate: '48000',
|
|
9251
8903
|
}
|
|
9252
8904
|
);
|
|
9253
8905
|
assert.notCalled(
|
|
9254
|
-
meeting.sendSlotManager.getSlot(MediaType.AudioMain).
|
|
8906
|
+
meeting.sendSlotManager.getSlot(MediaType.AudioMain).deleteCodecParameters
|
|
9255
8907
|
);
|
|
9256
8908
|
});
|
|
9257
8909
|
|
|
9258
|
-
it('should
|
|
8910
|
+
it('should set the codec parameters when shouldEnableMusicMode is false', async () => {
|
|
9259
8911
|
await meeting.enableMusicMode(false);
|
|
9260
8912
|
assert.calledOnceWithExactly(
|
|
9261
|
-
meeting.sendSlotManager.getSlot(MediaType.AudioMain).
|
|
9262
|
-
MediaCodecMimeType.OPUS,
|
|
8913
|
+
meeting.sendSlotManager.getSlot(MediaType.AudioMain).deleteCodecParameters,
|
|
9263
8914
|
['maxaveragebitrate', 'maxplaybackrate']
|
|
9264
8915
|
);
|
|
9265
|
-
assert.notCalled(meeting.sendSlotManager.getSlot(MediaType.AudioMain).
|
|
8916
|
+
assert.notCalled(meeting.sendSlotManager.getSlot(MediaType.AudioMain).setCodecParameters);
|
|
9266
8917
|
});
|
|
9267
8918
|
});
|
|
9268
8919
|
|
|
@@ -9353,10 +9004,7 @@ describe('plugin-meetings', () => {
|
|
|
9353
9004
|
|
|
9354
9005
|
// check that the right things were called by the callback
|
|
9355
9006
|
assert.calledOnceWithExactly(meeting.waitForRemoteSDPAnswer);
|
|
9356
|
-
assert.calledOnceWithExactly(
|
|
9357
|
-
meeting.mediaProperties.waitForMediaConnectionConnected,
|
|
9358
|
-
meeting.correlationId
|
|
9359
|
-
);
|
|
9007
|
+
assert.calledOnceWithExactly(meeting.mediaProperties.waitForMediaConnectionConnected);
|
|
9360
9008
|
});
|
|
9361
9009
|
});
|
|
9362
9010
|
|
|
@@ -10417,24 +10065,14 @@ describe('plugin-meetings', () => {
|
|
|
10417
10065
|
);
|
|
10418
10066
|
done();
|
|
10419
10067
|
});
|
|
10420
|
-
it('listens to the self admitted guest event
|
|
10068
|
+
it('listens to the self admitted guest event', (done) => {
|
|
10421
10069
|
meeting.stopKeepAlive = sinon.stub();
|
|
10422
10070
|
meeting.updateLLMConnection = sinon.stub();
|
|
10423
|
-
let resolvePrefetch;
|
|
10424
|
-
|
|
10425
|
-
meeting.ensureDefaultDatachannelTokenAfterAdmit = sinon
|
|
10426
|
-
.stub()
|
|
10427
|
-
.returns(new Promise((resolve) => {
|
|
10428
|
-
resolvePrefetch = resolve;
|
|
10429
|
-
}));
|
|
10430
10071
|
meeting.rtcMetrics = {
|
|
10431
10072
|
sendNextMetrics: sinon.stub(),
|
|
10432
10073
|
};
|
|
10433
|
-
|
|
10434
10074
|
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_ADMITTED_GUEST', test1);
|
|
10435
|
-
|
|
10436
10075
|
assert.calledOnceWithExactly(meeting.stopKeepAlive);
|
|
10437
|
-
assert.calledOnceWithExactly(meeting.ensureDefaultDatachannelTokenAfterAdmit);
|
|
10438
10076
|
assert.calledThrice(TriggerProxy.trigger);
|
|
10439
10077
|
assert.calledWith(
|
|
10440
10078
|
TriggerProxy.trigger,
|
|
@@ -10453,11 +10091,7 @@ describe('plugin-meetings', () => {
|
|
|
10453
10091
|
correlation_id: meeting.correlationId,
|
|
10454
10092
|
}
|
|
10455
10093
|
);
|
|
10456
|
-
|
|
10457
|
-
resolvePrefetch(false);
|
|
10458
|
-
await Promise.resolve();
|
|
10459
|
-
|
|
10460
|
-
assert.calledOnce(meeting.updateLLMConnection);
|
|
10094
|
+
done();
|
|
10461
10095
|
});
|
|
10462
10096
|
|
|
10463
10097
|
it('listens to the breakouts changed event', () => {
|
|
@@ -10544,21 +10178,6 @@ describe('plugin-meetings', () => {
|
|
|
10544
10178
|
EVENT_TRIGGERS.MEETING_INTERPRETATION_UPDATE
|
|
10545
10179
|
);
|
|
10546
10180
|
});
|
|
10547
|
-
|
|
10548
|
-
it('listens to the self id changed event and updates aiEnableRequest', () => {
|
|
10549
|
-
meeting.aiEnableRequest = {
|
|
10550
|
-
selfParticipantIdUpdate: sinon.stub(),
|
|
10551
|
-
};
|
|
10552
|
-
|
|
10553
|
-
const payload = {selfId: 'participant-test-123'};
|
|
10554
|
-
|
|
10555
|
-
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_ID_CHANGED', payload);
|
|
10556
|
-
|
|
10557
|
-
assert.calledOnceWithExactly(
|
|
10558
|
-
meeting.aiEnableRequest.selfParticipantIdUpdate,
|
|
10559
|
-
payload.selfId
|
|
10560
|
-
);
|
|
10561
|
-
});
|
|
10562
10181
|
});
|
|
10563
10182
|
|
|
10564
10183
|
describe('#setUpBreakoutsListener', () => {
|
|
@@ -10806,24 +10425,6 @@ describe('plugin-meetings', () => {
|
|
|
10806
10425
|
);
|
|
10807
10426
|
});
|
|
10808
10427
|
|
|
10809
|
-
it('listens to MEETING_CONTROLS_AI_SUMMARY_NOTIFICATION_UPDATED', async () => {
|
|
10810
|
-
const aiSummaryNotification = {example: 'value'};
|
|
10811
|
-
|
|
10812
|
-
await meeting.locusInfo.emitScoped(
|
|
10813
|
-
{function: 'test', file: 'test'},
|
|
10814
|
-
LOCUSINFO.EVENTS.CONTROLS_AI_SUMMARY_NOTIFICATION_UPDATED,
|
|
10815
|
-
{aiSummaryNotification}
|
|
10816
|
-
);
|
|
10817
|
-
|
|
10818
|
-
assert.calledWith(
|
|
10819
|
-
TriggerProxy.trigger,
|
|
10820
|
-
meeting,
|
|
10821
|
-
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
10822
|
-
EVENT_TRIGGERS.MEETING_CONTROLS_AI_SUMMARY_NOTIFICATION_UPDATED,
|
|
10823
|
-
{aiSummaryNotification}
|
|
10824
|
-
);
|
|
10825
|
-
});
|
|
10826
|
-
|
|
10827
10428
|
it('listens to MEETING_CONTROLS_MEETING_FULL_UPDATED', async () => {
|
|
10828
10429
|
const state = {example: 'value'};
|
|
10829
10430
|
|
|
@@ -11096,9 +10697,6 @@ describe('plugin-meetings', () => {
|
|
|
11096
10697
|
meeting.simultaneousInterpretation = {
|
|
11097
10698
|
approvalUrlUpdate: sinon.stub().returns(undefined),
|
|
11098
10699
|
};
|
|
11099
|
-
meeting.aiEnableRequest = {
|
|
11100
|
-
approvalUrlUpdate: sinon.stub().returns(undefined),
|
|
11101
|
-
};
|
|
11102
10700
|
|
|
11103
10701
|
meeting.locusInfo.emit(
|
|
11104
10702
|
{function: 'test', file: 'test'},
|
|
@@ -11118,10 +10716,6 @@ describe('plugin-meetings', () => {
|
|
|
11118
10716
|
meeting.simultaneousInterpretation.approvalUrlUpdate,
|
|
11119
10717
|
newLocusServices.services.approval.url
|
|
11120
10718
|
);
|
|
11121
|
-
assert.calledWith(
|
|
11122
|
-
meeting.aiEnableRequest.approvalUrlUpdate,
|
|
11123
|
-
newLocusServices.services.approval.url
|
|
11124
|
-
);
|
|
11125
10719
|
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
11126
10720
|
done();
|
|
11127
10721
|
});
|
|
@@ -11522,43 +11116,8 @@ describe('plugin-meetings', () => {
|
|
|
11522
11116
|
meeting.unsetPeerConnections();
|
|
11523
11117
|
assert.calledOnce(meeting.mediaProperties.unsetPeerConnection);
|
|
11524
11118
|
assert.calledTwice(meeting.webex.internal.mercury.off);
|
|
11525
|
-
assert.calledWith(meeting.webex.internal.mercury.off.firstCall, ONLINE);
|
|
11526
|
-
assert.calledWith(meeting.webex.internal.mercury.off.secondCall, OFFLINE);
|
|
11527
|
-
});
|
|
11528
|
-
});
|
|
11529
|
-
|
|
11530
|
-
describe('localConstraintsChangeHandler', () => {
|
|
11531
|
-
it('calls updatePreferredBitrateKbps when not multistream', () => {
|
|
11532
|
-
meeting.isMultistream = false;
|
|
11533
|
-
meeting.mediaProperties.webrtcMediaConnection = {
|
|
11534
|
-
updatePreferredBitrateKbps: sinon.stub(),
|
|
11535
|
-
};
|
|
11536
|
-
|
|
11537
|
-
meeting.localConstraintsChangeHandler();
|
|
11538
|
-
|
|
11539
|
-
assert.calledOnce(
|
|
11540
|
-
meeting.mediaProperties.webrtcMediaConnection.updatePreferredBitrateKbps
|
|
11541
|
-
);
|
|
11542
|
-
});
|
|
11543
|
-
|
|
11544
|
-
it('does not call updatePreferredBitrateKbps when multistream', () => {
|
|
11545
|
-
meeting.isMultistream = true;
|
|
11546
|
-
meeting.mediaProperties.webrtcMediaConnection = {
|
|
11547
|
-
updatePreferredBitrateKbps: sinon.stub(),
|
|
11548
|
-
};
|
|
11549
|
-
|
|
11550
|
-
meeting.localConstraintsChangeHandler();
|
|
11551
|
-
|
|
11552
|
-
assert.notCalled(
|
|
11553
|
-
meeting.mediaProperties.webrtcMediaConnection.updatePreferredBitrateKbps
|
|
11554
|
-
);
|
|
11555
|
-
});
|
|
11556
|
-
|
|
11557
|
-
it('does not throw when webrtcMediaConnection is undefined', () => {
|
|
11558
|
-
meeting.isMultistream = false;
|
|
11559
|
-
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
|
11560
|
-
|
|
11561
|
-
assert.doesNotThrow(() => meeting.localConstraintsChangeHandler());
|
|
11119
|
+
assert.calledWith(meeting.webex.internal.mercury.off.firstCall, ONLINE);
|
|
11120
|
+
assert.calledWith(meeting.webex.internal.mercury.off.secondCall, OFFLINE);
|
|
11562
11121
|
});
|
|
11563
11122
|
});
|
|
11564
11123
|
|
|
@@ -11941,7 +11500,6 @@ describe('plugin-meetings', () => {
|
|
|
11941
11500
|
let canUnsetDisallowUnmuteSpy;
|
|
11942
11501
|
let canUserRaiseHandSpy;
|
|
11943
11502
|
let bothLeaveAndEndMeetingAvailableSpy;
|
|
11944
|
-
let requireHostEndMeetingBeforeLeaveSpy;
|
|
11945
11503
|
let canUserLowerAllHandsSpy;
|
|
11946
11504
|
let canUserLowerSomeoneElsesHandSpy;
|
|
11947
11505
|
let waitingForOthersToJoinSpy;
|
|
@@ -11953,8 +11511,6 @@ describe('plugin-meetings', () => {
|
|
|
11953
11511
|
let canMoveToLobbySpy;
|
|
11954
11512
|
let isSpokenLanguageAutoDetectionEnabledSpy;
|
|
11955
11513
|
let showAutoEndMeetingWarningSpy;
|
|
11956
|
-
let canAttendeeRequestAiAssistantEnabledSpy;
|
|
11957
|
-
let attendeeRequestAiAssistantDeclinedAllSpy;
|
|
11958
11514
|
// Due to import tree issues, hasHints must be stubed within the scope of the `it`.
|
|
11959
11515
|
|
|
11960
11516
|
beforeEach(() => {
|
|
@@ -11975,10 +11531,6 @@ describe('plugin-meetings', () => {
|
|
|
11975
11531
|
MeetingUtil,
|
|
11976
11532
|
'bothLeaveAndEndMeetingAvailable'
|
|
11977
11533
|
);
|
|
11978
|
-
requireHostEndMeetingBeforeLeaveSpy = sinon.spy(
|
|
11979
|
-
MeetingUtil,
|
|
11980
|
-
'requireHostEndMeetingBeforeLeave'
|
|
11981
|
-
);
|
|
11982
11534
|
canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
|
|
11983
11535
|
waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
|
|
11984
11536
|
canSendReactionsSpy = sinon.spy(MeetingUtil, 'canSendReactions');
|
|
@@ -11995,22 +11547,12 @@ describe('plugin-meetings', () => {
|
|
|
11995
11547
|
MeetingUtil,
|
|
11996
11548
|
'isSpokenLanguageAutoDetectionEnabled'
|
|
11997
11549
|
);
|
|
11998
|
-
canAttendeeRequestAiAssistantEnabledSpy = sinon.spy(
|
|
11999
|
-
MeetingUtil,
|
|
12000
|
-
'canAttendeeRequestAiAssistantEnabled'
|
|
12001
|
-
);
|
|
12002
|
-
attendeeRequestAiAssistantDeclinedAllSpy = sinon.spy(
|
|
12003
|
-
MeetingUtil,
|
|
12004
|
-
'attendeeRequestAiAssistantDeclinedAll'
|
|
12005
|
-
);
|
|
12006
11550
|
});
|
|
12007
11551
|
|
|
12008
11552
|
afterEach(() => {
|
|
12009
11553
|
inMeetingActionsSetSpy.restore();
|
|
12010
11554
|
waitingForOthersToJoinSpy.restore();
|
|
12011
11555
|
showAutoEndMeetingWarningSpy.restore();
|
|
12012
|
-
canAttendeeRequestAiAssistantEnabledSpy.restore();
|
|
12013
|
-
attendeeRequestAiAssistantDeclinedAllSpy.restore();
|
|
12014
11556
|
});
|
|
12015
11557
|
|
|
12016
11558
|
forEach(
|
|
@@ -12534,7 +12076,6 @@ describe('plugin-meetings', () => {
|
|
|
12534
12076
|
const userDisplayHints = ['LOCK_CONTROL_UNLOCK'];
|
|
12535
12077
|
meeting.userDisplayHints = ['LOCK_CONTROL_UNLOCK'];
|
|
12536
12078
|
meeting.meetingInfo.supportVoIP = true;
|
|
12537
|
-
meeting.roles = [];
|
|
12538
12079
|
|
|
12539
12080
|
meeting.updateMeetingActions();
|
|
12540
12081
|
|
|
@@ -12550,7 +12091,6 @@ describe('plugin-meetings', () => {
|
|
|
12550
12091
|
assert.calledWith(canUnsetDisallowUnmuteSpy, userDisplayHints);
|
|
12551
12092
|
assert.calledWith(canUserRaiseHandSpy, userDisplayHints);
|
|
12552
12093
|
assert.calledWith(bothLeaveAndEndMeetingAvailableSpy, userDisplayHints);
|
|
12553
|
-
assert.calledWith(requireHostEndMeetingBeforeLeaveSpy, userDisplayHints);
|
|
12554
12094
|
assert.calledWith(canUserLowerAllHandsSpy, userDisplayHints);
|
|
12555
12095
|
assert.calledWith(canUserLowerSomeoneElsesHandSpy, userDisplayHints);
|
|
12556
12096
|
assert.calledWith(waitingForOthersToJoinSpy, userDisplayHints);
|
|
@@ -12562,12 +12102,6 @@ describe('plugin-meetings', () => {
|
|
|
12562
12102
|
assert.calledWith(canMoveToLobbySpy, userDisplayHints);
|
|
12563
12103
|
assert.calledWith(showAutoEndMeetingWarningSpy, userDisplayHints);
|
|
12564
12104
|
assert.calledWith(isSpokenLanguageAutoDetectionEnabledSpy, userDisplayHints);
|
|
12565
|
-
assert.calledWith(
|
|
12566
|
-
canAttendeeRequestAiAssistantEnabledSpy,
|
|
12567
|
-
userDisplayHints,
|
|
12568
|
-
meeting.roles
|
|
12569
|
-
);
|
|
12570
|
-
assert.calledWith(attendeeRequestAiAssistantDeclinedAllSpy, userDisplayHints);
|
|
12571
12105
|
|
|
12572
12106
|
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
12573
12107
|
requiredHints: [DISPLAY_HINTS.MUTE_ALL],
|
|
@@ -12710,159 +12244,33 @@ describe('plugin-meetings', () => {
|
|
|
12710
12244
|
|
|
12711
12245
|
describe('#handleDataChannelUrlChange', () => {
|
|
12712
12246
|
let updateLLMConnectionSpy;
|
|
12713
|
-
let updatePSDataChannelSpy;
|
|
12714
12247
|
|
|
12715
12248
|
beforeEach(() => {
|
|
12716
12249
|
updateLLMConnectionSpy = sinon.spy(meeting, 'updateLLMConnection');
|
|
12717
|
-
updatePSDataChannelSpy = sinon.stub(meeting.webinar, 'updatePSDataChannel').resolves();
|
|
12718
|
-
meeting.webinar.isJoinPracticeSessionDataChannel = sinon.stub().returns(false);
|
|
12719
12250
|
});
|
|
12720
12251
|
|
|
12721
|
-
const check = (
|
|
12722
|
-
url
|
|
12723
|
-
practiceSessionDatachannelUrl,
|
|
12724
|
-
{expectedMainCalled, expectedPracticeCalled}
|
|
12725
|
-
) => {
|
|
12726
|
-
meeting.handleDataChannelUrlChange(url, practiceSessionDatachannelUrl);
|
|
12252
|
+
const check = (url, expectedCalled) => {
|
|
12253
|
+
meeting.handleDataChannelUrlChange(url);
|
|
12727
12254
|
|
|
12728
|
-
if (
|
|
12255
|
+
if (expectedCalled) {
|
|
12729
12256
|
assert.calledWith(updateLLMConnectionSpy);
|
|
12730
12257
|
} else {
|
|
12731
12258
|
assert.notCalled(updateLLMConnectionSpy);
|
|
12732
12259
|
}
|
|
12733
|
-
|
|
12734
|
-
if (expectedPracticeCalled) {
|
|
12735
|
-
assert.calledWith(updatePSDataChannelSpy);
|
|
12736
|
-
} else {
|
|
12737
|
-
assert.notCalled(updatePSDataChannelSpy);
|
|
12738
|
-
}
|
|
12739
12260
|
};
|
|
12740
12261
|
|
|
12741
12262
|
it('calls deferred updateLLMConnection if datachannelURL is set and the enableAutomaticLLM is true', () => {
|
|
12742
12263
|
meeting.config.enableAutomaticLLM = true;
|
|
12743
|
-
check('some url',
|
|
12264
|
+
check('some url', true);
|
|
12744
12265
|
});
|
|
12745
12266
|
|
|
12746
12267
|
it('does not call updateLLMConnection if datachannelURL is undefined', () => {
|
|
12747
12268
|
meeting.config.enableAutomaticLLM = true;
|
|
12748
|
-
check(undefined,
|
|
12749
|
-
expectedMainCalled: false,
|
|
12750
|
-
expectedPracticeCalled: false,
|
|
12751
|
-
});
|
|
12269
|
+
check(undefined, false);
|
|
12752
12270
|
});
|
|
12753
12271
|
|
|
12754
12272
|
it('does not call updateLLMConnection if enableAutomaticLLM is false', () => {
|
|
12755
|
-
check('some url',
|
|
12756
|
-
expectedMainCalled: false,
|
|
12757
|
-
expectedPracticeCalled: false,
|
|
12758
|
-
});
|
|
12759
|
-
});
|
|
12760
|
-
|
|
12761
|
-
it('calls updatePSDataChannel when practice-session routing is active', () => {
|
|
12762
|
-
meeting.config.enableAutomaticLLM = true;
|
|
12763
|
-
meeting.webinar.isJoinPracticeSessionDataChannel.returns(true);
|
|
12764
|
-
|
|
12765
|
-
check('some url', 'some practice url', {
|
|
12766
|
-
expectedMainCalled: true,
|
|
12767
|
-
expectedPracticeCalled: true,
|
|
12768
|
-
});
|
|
12769
|
-
});
|
|
12770
|
-
|
|
12771
|
-
it('does not call updatePSDataChannel when the main datachannelURL is undefined', () => {
|
|
12772
|
-
meeting.config.enableAutomaticLLM = true;
|
|
12773
|
-
meeting.webinar.isJoinPracticeSessionDataChannel.returns(true);
|
|
12774
|
-
|
|
12775
|
-
check(undefined, 'some practice url', {
|
|
12776
|
-
expectedMainCalled: false,
|
|
12777
|
-
expectedPracticeCalled: false,
|
|
12778
|
-
});
|
|
12779
|
-
});
|
|
12780
|
-
});
|
|
12781
|
-
|
|
12782
|
-
describe('#saveDataChannelToken', () => {
|
|
12783
|
-
beforeEach(() => {
|
|
12784
|
-
webex.internal.llm.setDatachannelToken = sinon.stub();
|
|
12785
|
-
});
|
|
12786
|
-
|
|
12787
|
-
it('saves datachannelToken into LLM as Default', () => {
|
|
12788
|
-
meeting.saveDataChannelToken({
|
|
12789
|
-
locus: {
|
|
12790
|
-
self: {datachannelToken: 'default-token'},
|
|
12791
|
-
},
|
|
12792
|
-
});
|
|
12793
|
-
|
|
12794
|
-
assert.calledWithExactly(
|
|
12795
|
-
webex.internal.llm.setDatachannelToken,
|
|
12796
|
-
'default-token',
|
|
12797
|
-
'llm-default-session'
|
|
12798
|
-
);
|
|
12799
|
-
});
|
|
12800
|
-
|
|
12801
|
-
it('saves practiceSessionDatachannelToken into LLM as PracticeSession', () => {
|
|
12802
|
-
meeting.saveDataChannelToken({
|
|
12803
|
-
locus: {
|
|
12804
|
-
self: {practiceSessionDatachannelToken: 'ps-token'},
|
|
12805
|
-
},
|
|
12806
|
-
});
|
|
12807
|
-
|
|
12808
|
-
assert.calledWithExactly(
|
|
12809
|
-
webex.internal.llm.setDatachannelToken,
|
|
12810
|
-
'ps-token',
|
|
12811
|
-
'llm-practice-session'
|
|
12812
|
-
);
|
|
12813
|
-
});
|
|
12814
|
-
|
|
12815
|
-
it('saves both tokens when both are present', () => {
|
|
12816
|
-
meeting.saveDataChannelToken({
|
|
12817
|
-
locus: {
|
|
12818
|
-
self: {
|
|
12819
|
-
datachannelToken: 'default-token',
|
|
12820
|
-
practiceSessionDatachannelToken: 'ps-token',
|
|
12821
|
-
},
|
|
12822
|
-
},
|
|
12823
|
-
});
|
|
12824
|
-
|
|
12825
|
-
assert.calledTwice(webex.internal.llm.setDatachannelToken);
|
|
12826
|
-
assert.calledWithExactly(
|
|
12827
|
-
webex.internal.llm.setDatachannelToken,
|
|
12828
|
-
'default-token',
|
|
12829
|
-
'llm-default-session'
|
|
12830
|
-
);
|
|
12831
|
-
assert.calledWithExactly(
|
|
12832
|
-
webex.internal.llm.setDatachannelToken,
|
|
12833
|
-
'ps-token',
|
|
12834
|
-
'llm-practice-session'
|
|
12835
|
-
);
|
|
12836
|
-
});
|
|
12837
|
-
|
|
12838
|
-
it('does not call setDatachannelToken when no tokens are present', () => {
|
|
12839
|
-
meeting.saveDataChannelToken({locus: {self: {}}});
|
|
12840
|
-
|
|
12841
|
-
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
12842
|
-
});
|
|
12843
|
-
|
|
12844
|
-
it('handles undefined join gracefully', () => {
|
|
12845
|
-
meeting.saveDataChannelToken(undefined);
|
|
12846
|
-
|
|
12847
|
-
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
12848
|
-
});
|
|
12849
|
-
|
|
12850
|
-
it('handles missing locus.self gracefully', () => {
|
|
12851
|
-
meeting.saveDataChannelToken({locus: {}});
|
|
12852
|
-
|
|
12853
|
-
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
12854
|
-
});
|
|
12855
|
-
});
|
|
12856
|
-
|
|
12857
|
-
describe('#clearDataChannelToken', () => {
|
|
12858
|
-
beforeEach(() => {
|
|
12859
|
-
webex.internal.llm.resetDatachannelTokens = sinon.stub();
|
|
12860
|
-
});
|
|
12861
|
-
|
|
12862
|
-
it('calls resetDatachannelTokens on LLM', () => {
|
|
12863
|
-
meeting.clearDataChannelToken();
|
|
12864
|
-
|
|
12865
|
-
assert.calledOnce(webex.internal.llm.resetDatachannelTokens);
|
|
12273
|
+
check('some url', false);
|
|
12866
12274
|
});
|
|
12867
12275
|
});
|
|
12868
12276
|
|
|
@@ -12871,20 +12279,16 @@ describe('plugin-meetings', () => {
|
|
|
12871
12279
|
webex.internal.llm.isConnected = sinon.stub().returns(false);
|
|
12872
12280
|
webex.internal.llm.getLocusUrl = sinon.stub();
|
|
12873
12281
|
webex.internal.llm.getDatachannelUrl = sinon.stub();
|
|
12874
|
-
webex.internal.llm.registerAndConnect = sinon
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
webex.internal.llm.
|
|
12878
|
-
webex.internal.llm.
|
|
12879
|
-
webex.internal.llm.
|
|
12880
|
-
|
|
12282
|
+
webex.internal.llm.registerAndConnect = sinon
|
|
12283
|
+
.stub()
|
|
12284
|
+
.returns(Promise.resolve('something'));
|
|
12285
|
+
webex.internal.llm.disconnectLLM = sinon.stub().returns(Promise.resolve());
|
|
12286
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
12287
|
+
meeting.webex.internal.llm.off = sinon.stub();
|
|
12881
12288
|
meeting.processRelayEvent = sinon.stub();
|
|
12882
|
-
meeting.processLocusLLMEvent = sinon.stub();
|
|
12883
|
-
meeting.clearLLMHealthCheckTimer = sinon.stub();
|
|
12884
|
-
meeting.startLLMHealthCheckTimer = sinon.stub();
|
|
12885
|
-
|
|
12886
12289
|
meeting.webinar.isJoinPracticeSessionDataChannel = sinon.stub().returns(false);
|
|
12887
12290
|
});
|
|
12291
|
+
|
|
12888
12292
|
it('does not connect if the call is not joined yet', async () => {
|
|
12889
12293
|
meeting.joinedWith = {state: 'any other state'};
|
|
12890
12294
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
@@ -12898,21 +12302,31 @@ describe('plugin-meetings', () => {
|
|
|
12898
12302
|
assert.equal(result, undefined);
|
|
12899
12303
|
assert.notCalled(meeting.webex.internal.llm.on);
|
|
12900
12304
|
});
|
|
12305
|
+
|
|
12901
12306
|
it('returns undefined if llm is already connected and the locus url is unchanged', async () => {
|
|
12902
12307
|
meeting.joinedWith = {state: 'JOINED'};
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
|
|
12906
|
-
|
|
12308
|
+
webex.internal.llm.isConnected.returns(true);
|
|
12309
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
12310
|
+
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
12311
|
+
|
|
12312
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12907
12313
|
|
|
12908
12314
|
const result = await meeting.updateLLMConnection();
|
|
12315
|
+
|
|
12316
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
12909
12317
|
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
12910
|
-
assert.
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12318
|
+
assert.equal(result, undefined);
|
|
12319
|
+
assert.notCalled(meeting.webex.internal.llm.on);
|
|
12320
|
+
});
|
|
12321
|
+
|
|
12322
|
+
it('connects if not already connected', async () => {
|
|
12323
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
12324
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12325
|
+
|
|
12326
|
+
const result = await meeting.updateLLMConnection();
|
|
12327
|
+
|
|
12328
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
12329
|
+
assert.calledWith(webex.internal.llm.registerAndConnect, 'a url', 'a datachannel url');
|
|
12916
12330
|
assert.equal(result, 'something');
|
|
12917
12331
|
assert.calledWithExactly(
|
|
12918
12332
|
meeting.webex.internal.llm.off,
|
|
@@ -12935,49 +12349,27 @@ describe('plugin-meetings', () => {
|
|
|
12935
12349
|
meeting.processLocusLLMEvent
|
|
12936
12350
|
);
|
|
12937
12351
|
});
|
|
12938
|
-
it('connects if not already connected', async () => {
|
|
12939
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
12940
|
-
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12941
|
-
|
|
12942
|
-
const result = await meeting.updateLLMConnection();
|
|
12943
12352
|
|
|
12944
|
-
|
|
12945
|
-
assert.calledWithExactly(
|
|
12946
|
-
webex.internal.llm.registerAndConnect,
|
|
12947
|
-
'a url',
|
|
12948
|
-
'a datachannel url',
|
|
12949
|
-
undefined
|
|
12950
|
-
);
|
|
12951
|
-
assert.equal(result, 'something');
|
|
12952
|
-
});
|
|
12953
|
-
it('disconnects if the locus url has changed', async () => {
|
|
12353
|
+
it('disconnects if first if the locus url has changed', async () => {
|
|
12954
12354
|
meeting.joinedWith = {state: 'JOINED'};
|
|
12955
|
-
|
|
12956
12355
|
webex.internal.llm.isConnected.returns(true);
|
|
12957
12356
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
12357
|
+
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
12958
12358
|
|
|
12959
|
-
meeting.locusInfo = {
|
|
12960
|
-
url: 'a different url',
|
|
12961
|
-
info: {datachannelUrl: 'a datachannel url'},
|
|
12962
|
-
self: {},
|
|
12963
|
-
};
|
|
12359
|
+
meeting.locusInfo = {url: 'a different url', info: {datachannelUrl: 'a datachannel url'}};
|
|
12964
12360
|
|
|
12965
12361
|
const result = await meeting.updateLLMConnection();
|
|
12966
12362
|
|
|
12967
|
-
assert.
|
|
12363
|
+
assert.calledWith(webex.internal.llm.disconnectLLM, {
|
|
12968
12364
|
code: 3050,
|
|
12969
12365
|
reason: 'done (permanent)',
|
|
12970
12366
|
});
|
|
12971
|
-
|
|
12972
|
-
assert.calledWithExactly(
|
|
12367
|
+
assert.calledWith(
|
|
12973
12368
|
webex.internal.llm.registerAndConnect,
|
|
12974
12369
|
'a different url',
|
|
12975
|
-
'a datachannel url'
|
|
12976
|
-
undefined
|
|
12370
|
+
'a datachannel url'
|
|
12977
12371
|
);
|
|
12978
|
-
|
|
12979
12372
|
assert.equal(result, 'something');
|
|
12980
|
-
|
|
12981
12373
|
assert.calledWithExactly(
|
|
12982
12374
|
meeting.webex.internal.llm.off,
|
|
12983
12375
|
'event:relay.event',
|
|
@@ -12989,7 +12381,6 @@ describe('plugin-meetings', () => {
|
|
|
12989
12381
|
meeting.processLocusLLMEvent
|
|
12990
12382
|
);
|
|
12991
12383
|
assert.callCount(meeting.webex.internal.llm.off, 4);
|
|
12992
|
-
|
|
12993
12384
|
assert.calledWithExactly(
|
|
12994
12385
|
meeting.webex.internal.llm.on,
|
|
12995
12386
|
'event:relay.event',
|
|
@@ -13000,37 +12391,28 @@ describe('plugin-meetings', () => {
|
|
|
13000
12391
|
'event:locus.state_message',
|
|
13001
12392
|
meeting.processLocusLLMEvent
|
|
13002
12393
|
);
|
|
13003
|
-
assert.isFalse(
|
|
13004
|
-
meeting.webex.internal.llm.off.calledWithExactly('online', meeting.handleLLMOnline)
|
|
13005
|
-
);
|
|
13006
12394
|
});
|
|
13007
|
-
|
|
12395
|
+
|
|
12396
|
+
it('disconnects it first if the data channel url has changed', async () => {
|
|
13008
12397
|
meeting.joinedWith = {state: 'JOINED'};
|
|
13009
12398
|
webex.internal.llm.isConnected.returns(true);
|
|
13010
12399
|
webex.internal.llm.getLocusUrl.returns('a url');
|
|
12400
|
+
webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
|
|
13011
12401
|
|
|
13012
|
-
meeting.locusInfo = {
|
|
13013
|
-
url: 'a url',
|
|
13014
|
-
info: {datachannelUrl: 'a different datachannel url'},
|
|
13015
|
-
self: {},
|
|
13016
|
-
};
|
|
12402
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a different datachannel url'}};
|
|
13017
12403
|
|
|
13018
12404
|
const result = await meeting.updateLLMConnection();
|
|
13019
12405
|
|
|
13020
|
-
assert.
|
|
12406
|
+
assert.calledWith(webex.internal.llm.disconnectLLM, {
|
|
13021
12407
|
code: 3050,
|
|
13022
12408
|
reason: 'done (permanent)',
|
|
13023
12409
|
});
|
|
13024
|
-
|
|
13025
|
-
assert.calledWithExactly(
|
|
12410
|
+
assert.calledWith(
|
|
13026
12411
|
webex.internal.llm.registerAndConnect,
|
|
13027
12412
|
'a url',
|
|
13028
|
-
'a different datachannel url'
|
|
13029
|
-
undefined
|
|
12413
|
+
'a different datachannel url'
|
|
13030
12414
|
);
|
|
13031
|
-
|
|
13032
12415
|
assert.equal(result, 'something');
|
|
13033
|
-
|
|
13034
12416
|
assert.calledWithExactly(
|
|
13035
12417
|
meeting.webex.internal.llm.off,
|
|
13036
12418
|
'event:relay.event',
|
|
@@ -13041,7 +12423,6 @@ describe('plugin-meetings', () => {
|
|
|
13041
12423
|
'event:locus.state_message',
|
|
13042
12424
|
meeting.processLocusLLMEvent
|
|
13043
12425
|
);
|
|
13044
|
-
|
|
13045
12426
|
assert.calledWithExactly(
|
|
13046
12427
|
meeting.webex.internal.llm.on,
|
|
13047
12428
|
'event:relay.event',
|
|
@@ -13052,10 +12433,8 @@ describe('plugin-meetings', () => {
|
|
|
13052
12433
|
'event:locus.state_message',
|
|
13053
12434
|
meeting.processLocusLLMEvent
|
|
13054
12435
|
);
|
|
13055
|
-
assert.isFalse(
|
|
13056
|
-
meeting.webex.internal.llm.off.calledWithExactly('online', meeting.handleLLMOnline)
|
|
13057
|
-
);
|
|
13058
12436
|
});
|
|
12437
|
+
|
|
13059
12438
|
it('disconnects when the state is not JOINED', async () => {
|
|
13060
12439
|
meeting.joinedWith = {state: 'any other state'};
|
|
13061
12440
|
webex.internal.llm.isConnected.returns(true);
|
|
@@ -13065,38 +12444,9 @@ describe('plugin-meetings', () => {
|
|
|
13065
12444
|
|
|
13066
12445
|
const result = await meeting.updateLLMConnection();
|
|
13067
12446
|
|
|
13068
|
-
assert.calledWith(webex.internal.llm.disconnectLLM,
|
|
13069
|
-
code: 3050,
|
|
13070
|
-
reason: 'done (permanent)',
|
|
13071
|
-
});
|
|
12447
|
+
assert.calledWith(webex.internal.llm.disconnectLLM, undefined);
|
|
13072
12448
|
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
13073
12449
|
assert.equal(result, undefined);
|
|
13074
|
-
assert.isFalse(
|
|
13075
|
-
meeting.webex.internal.llm.off.calledWithExactly('online', meeting.handleLLMOnline)
|
|
13076
|
-
);
|
|
13077
|
-
});
|
|
13078
|
-
it('rethrows disconnect errors during reconnect cleanup after removing relay listeners and timer', async () => {
|
|
13079
|
-
const disconnectError = new Error('disconnect failed');
|
|
13080
|
-
|
|
13081
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
13082
|
-
webex.internal.llm.isConnected.returns(true);
|
|
13083
|
-
webex.internal.llm.getLocusUrl.returns('a url');
|
|
13084
|
-
webex.internal.llm.disconnectLLM.rejects(disconnectError);
|
|
13085
|
-
|
|
13086
|
-
meeting.locusInfo = {
|
|
13087
|
-
url: 'a different url',
|
|
13088
|
-
info: {datachannelUrl: 'a datachannel url'},
|
|
13089
|
-
self: {},
|
|
13090
|
-
};
|
|
13091
|
-
|
|
13092
|
-
try {
|
|
13093
|
-
await meeting.updateLLMConnection();
|
|
13094
|
-
assert.fail('Expected updateLLMConnection to reject when disconnectLLM fails');
|
|
13095
|
-
} catch (error) {
|
|
13096
|
-
assert.equal(error, disconnectError);
|
|
13097
|
-
}
|
|
13098
|
-
|
|
13099
|
-
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
13100
12450
|
assert.calledWithExactly(
|
|
13101
12451
|
meeting.webex.internal.llm.off,
|
|
13102
12452
|
'event:relay.event',
|
|
@@ -13107,159 +12457,22 @@ describe('plugin-meetings', () => {
|
|
|
13107
12457
|
'event:locus.state_message',
|
|
13108
12458
|
meeting.processLocusLLMEvent
|
|
13109
12459
|
);
|
|
13110
|
-
assert.isFalse(
|
|
13111
|
-
meeting.webex.internal.llm.off.calledWithExactly('online', meeting.handleLLMOnline)
|
|
13112
|
-
);
|
|
13113
|
-
assert.calledOnce(meeting.clearLLMHealthCheckTimer);
|
|
13114
12460
|
});
|
|
13115
|
-
|
|
12461
|
+
|
|
12462
|
+
it('connect ps data channel if ps started in webinar', async () => {
|
|
13116
12463
|
meeting.joinedWith = {state: 'JOINED'};
|
|
13117
12464
|
meeting.locusInfo = {
|
|
13118
12465
|
url: 'a url',
|
|
13119
12466
|
info: {
|
|
13120
12467
|
datachannelUrl: 'a datachannel url',
|
|
13121
|
-
practiceSessionDatachannelUrl: 'ps
|
|
12468
|
+
practiceSessionDatachannelUrl: 'a ps datachannel url',
|
|
13122
12469
|
},
|
|
13123
12470
|
};
|
|
13124
|
-
meeting.webinar.isJoinPracticeSessionDataChannel.returns(true);
|
|
13125
|
-
|
|
13126
|
-
await meeting.updateLLMConnection();
|
|
13127
|
-
|
|
13128
|
-
assert.calledWithExactly(
|
|
13129
|
-
webex.internal.llm.registerAndConnect,
|
|
13130
|
-
'a url',
|
|
13131
|
-
'a datachannel url',
|
|
13132
|
-
undefined
|
|
13133
|
-
);
|
|
13134
|
-
});
|
|
13135
|
-
it('passes dataChannelToken from LLM to registerAndConnect', async () => {
|
|
13136
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
13137
|
-
meeting.locusInfo = {
|
|
13138
|
-
url: 'a url',
|
|
13139
|
-
info: {datachannelUrl: 'a datachannel url'},
|
|
13140
|
-
};
|
|
13141
|
-
|
|
13142
|
-
webex.internal.llm.getDatachannelToken.withArgs('llm-default-session').returns('token-123');
|
|
13143
|
-
|
|
13144
|
-
await meeting.updateLLMConnection();
|
|
13145
|
-
|
|
13146
|
-
assert.calledWithExactly(
|
|
13147
|
-
webex.internal.llm.registerAndConnect,
|
|
13148
|
-
'a url',
|
|
13149
|
-
'a datachannel url',
|
|
13150
|
-
'token-123'
|
|
13151
|
-
);
|
|
13152
|
-
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
13153
|
-
});
|
|
13154
|
-
it('passes undefined token when LLM has no token stored', async () => {
|
|
13155
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
13156
|
-
meeting.locusInfo = {
|
|
13157
|
-
url: 'a url',
|
|
13158
|
-
info: {datachannelUrl: 'a datachannel url'},
|
|
13159
|
-
};
|
|
13160
|
-
|
|
13161
|
-
webex.internal.llm.getDatachannelToken.returns(undefined);
|
|
13162
|
-
|
|
13163
|
-
await meeting.updateLLMConnection();
|
|
13164
|
-
|
|
13165
|
-
assert.calledWithExactly(
|
|
13166
|
-
webex.internal.llm.registerAndConnect,
|
|
13167
|
-
'a url',
|
|
13168
|
-
'a datachannel url',
|
|
13169
|
-
undefined
|
|
13170
|
-
);
|
|
13171
|
-
|
|
13172
|
-
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
13173
|
-
});
|
|
13174
|
-
|
|
13175
|
-
it('does not pass token when data channel with jwt token is disabled', async () => {
|
|
13176
|
-
meeting.joinedWith = {state: 'JOINED'};
|
|
13177
|
-
meeting.locusInfo = {
|
|
13178
|
-
url: 'a url',
|
|
13179
|
-
info: {datachannelUrl: 'a datachannel url'},
|
|
13180
|
-
};
|
|
13181
|
-
|
|
13182
|
-
webex.internal.llm.getDatachannelToken.returns(undefined);
|
|
13183
|
-
webex.internal.llm.isDataChannelTokenEnabled = sinon.stub().resolves(false);
|
|
13184
|
-
|
|
12471
|
+
meeting.webinar.isJoinPracticeSessionDataChannel = sinon.stub().returns(true);
|
|
13185
12472
|
await meeting.updateLLMConnection();
|
|
13186
12473
|
|
|
13187
|
-
assert.
|
|
13188
|
-
|
|
13189
|
-
'a url',
|
|
13190
|
-
'a datachannel url',
|
|
13191
|
-
undefined
|
|
13192
|
-
);
|
|
13193
|
-
assert.notCalled(webex.internal.llm.setDatachannelToken);
|
|
13194
|
-
});
|
|
13195
|
-
|
|
13196
|
-
describe('#clearMeetingData', () => {
|
|
13197
|
-
beforeEach(() => {
|
|
13198
|
-
webex.internal.llm.isConnected = sinon.stub().returns(true);
|
|
13199
|
-
webex.internal.llm.disconnectLLM = sinon.stub().resolves();
|
|
13200
|
-
webex.internal.llm.off = sinon.stub();
|
|
13201
|
-
meeting.annotation.deregisterEvents = sinon.stub();
|
|
13202
|
-
meeting.clearLLMHealthCheckTimer = sinon.stub();
|
|
13203
|
-
meeting.stopTranscription = sinon.stub();
|
|
13204
|
-
meeting.clearDataChannelToken = sinon.stub();
|
|
13205
|
-
meeting.shareStatus = 'no-share';
|
|
13206
|
-
});
|
|
13207
|
-
|
|
13208
|
-
it('disconnects llm and removes online and relay listeners during meeting data cleanup', async () => {
|
|
13209
|
-
await meeting.clearMeetingData();
|
|
13210
|
-
|
|
13211
|
-
assert.calledOnceWithExactly(webex.internal.llm.disconnectLLM, {
|
|
13212
|
-
code: 3050,
|
|
13213
|
-
reason: 'done (permanent)',
|
|
13214
|
-
});
|
|
13215
|
-
assert.calledWithExactly(webex.internal.llm.off, 'online', meeting.handleLLMOnline);
|
|
13216
|
-
assert.calledWithExactly(
|
|
13217
|
-
webex.internal.llm.off,
|
|
13218
|
-
'event:relay.event',
|
|
13219
|
-
meeting.processRelayEvent
|
|
13220
|
-
);
|
|
13221
|
-
assert.calledWithExactly(
|
|
13222
|
-
webex.internal.llm.off,
|
|
13223
|
-
'event:locus.state_message',
|
|
13224
|
-
meeting.processLocusLLMEvent
|
|
13225
|
-
);
|
|
13226
|
-
assert.calledOnce(meeting.clearLLMHealthCheckTimer);
|
|
13227
|
-
assert.calledOnce(meeting.stopTranscription);
|
|
13228
|
-
assert.isUndefined(meeting.transcription);
|
|
13229
|
-
assert.calledOnce(meeting.clearDataChannelToken);
|
|
13230
|
-
assert.calledOnce(meeting.annotation.deregisterEvents);
|
|
13231
|
-
});
|
|
13232
|
-
it('continues cleanup when disconnectLLM fails during meeting data cleanup', async () => {
|
|
13233
|
-
webex.internal.llm.disconnectLLM.rejects(new Error('disconnect failed'));
|
|
13234
|
-
|
|
13235
|
-
await meeting.clearMeetingData();
|
|
13236
|
-
|
|
13237
|
-
assert.calledWithExactly(webex.internal.llm.off, 'online', meeting.handleLLMOnline);
|
|
13238
|
-
assert.calledWithExactly(
|
|
13239
|
-
webex.internal.llm.off,
|
|
13240
|
-
'event:relay.event',
|
|
13241
|
-
meeting.processRelayEvent
|
|
13242
|
-
);
|
|
13243
|
-
assert.calledWithExactly(
|
|
13244
|
-
webex.internal.llm.off,
|
|
13245
|
-
'event:locus.state_message',
|
|
13246
|
-
meeting.processLocusLLMEvent
|
|
13247
|
-
);
|
|
13248
|
-
assert.calledOnce(meeting.clearLLMHealthCheckTimer);
|
|
13249
|
-
assert.calledOnce(meeting.stopTranscription);
|
|
13250
|
-
assert.isUndefined(meeting.transcription);
|
|
13251
|
-
assert.calledOnce(meeting.clearDataChannelToken);
|
|
13252
|
-
assert.calledOnce(meeting.annotation.deregisterEvents);
|
|
13253
|
-
});
|
|
13254
|
-
it('always calls stopTranscription even when transcription is undefined', async () => {
|
|
13255
|
-
meeting.transcription = undefined;
|
|
13256
|
-
|
|
13257
|
-
await meeting.clearMeetingData();
|
|
13258
|
-
|
|
13259
|
-
assert.calledOnce(meeting.stopTranscription);
|
|
13260
|
-
assert.isUndefined(meeting.transcription);
|
|
13261
|
-
assert.calledOnce(meeting.clearDataChannelToken);
|
|
13262
|
-
});
|
|
12474
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
12475
|
+
assert.calledWith(webex.internal.llm.registerAndConnect, 'a url', 'a ps datachannel url');
|
|
13263
12476
|
});
|
|
13264
12477
|
});
|
|
13265
12478
|
|
|
@@ -13270,7 +12483,6 @@ describe('plugin-meetings', () => {
|
|
|
13270
12483
|
|
|
13271
12484
|
it('should read the locus object, set on the meeting and return null', () => {
|
|
13272
12485
|
const dataSets = {someFakeStuff: 'dataSet'};
|
|
13273
|
-
const metadata = {some: 'metadata'};
|
|
13274
12486
|
|
|
13275
12487
|
meeting.setLocus({
|
|
13276
12488
|
mediaConnections: [test1],
|
|
@@ -13280,14 +12492,12 @@ describe('plugin-meetings', () => {
|
|
|
13280
12492
|
mediaId: uuid3,
|
|
13281
12493
|
locus: {host: {id: uuid4}},
|
|
13282
12494
|
dataSets,
|
|
13283
|
-
metadata,
|
|
13284
12495
|
});
|
|
13285
12496
|
assert.calledOnce(meeting.locusInfo.initialSetup);
|
|
13286
12497
|
assert.calledWith(meeting.locusInfo.initialSetup, {
|
|
13287
12498
|
trigger: 'join-response',
|
|
13288
12499
|
locus: {host: {id: uuid4}},
|
|
13289
12500
|
dataSets,
|
|
13290
|
-
metadata,
|
|
13291
12501
|
});
|
|
13292
12502
|
assert.equal(meeting.mediaConnections, test1);
|
|
13293
12503
|
assert.equal(meeting.locusUrl, url1);
|
|
@@ -14829,69 +14039,6 @@ describe('plugin-meetings', () => {
|
|
|
14829
14039
|
assert.calledOnce(meeting.meetingRequest.keepAlive);
|
|
14830
14040
|
});
|
|
14831
14041
|
});
|
|
14832
|
-
describe('#refreshDataChannelToken()', () => {
|
|
14833
|
-
let meeting;
|
|
14834
|
-
|
|
14835
|
-
beforeEach(() => {
|
|
14836
|
-
meeting = Object.create(Meeting.prototype);
|
|
14837
|
-
meeting.locusUrl = 'https://locus.example.com';
|
|
14838
|
-
meeting.meetingRequest = {
|
|
14839
|
-
fetchDatachannelToken: sinon.stub().resolves({
|
|
14840
|
-
body: {datachannelToken: 'mock-token'},
|
|
14841
|
-
}),
|
|
14842
|
-
};
|
|
14843
|
-
meeting.members = {
|
|
14844
|
-
selfId: 'self-123',
|
|
14845
|
-
};
|
|
14846
|
-
meeting.webinar = {
|
|
14847
|
-
isJoinPracticeSessionDataChannel: sinon.stub().returns(true),
|
|
14848
|
-
};
|
|
14849
|
-
});
|
|
14850
|
-
|
|
14851
|
-
it('calls fetchDatachannelToken with correct parameters', async () => {
|
|
14852
|
-
await meeting.refreshDataChannelToken();
|
|
14853
|
-
|
|
14854
|
-
sinon.assert.calledOnce(meeting.meetingRequest.fetchDatachannelToken);
|
|
14855
|
-
|
|
14856
|
-
sinon.assert.calledWith(meeting.meetingRequest.fetchDatachannelToken, {
|
|
14857
|
-
locusUrl: 'https://locus.example.com',
|
|
14858
|
-
requestingParticipantId: 'self-123',
|
|
14859
|
-
isPracticeSession: true,
|
|
14860
|
-
});
|
|
14861
|
-
});
|
|
14862
|
-
|
|
14863
|
-
it('returns the correct structured result', async () => {
|
|
14864
|
-
const result = await meeting.refreshDataChannelToken();
|
|
14865
|
-
|
|
14866
|
-
expect(result).to.deep.equal({
|
|
14867
|
-
body: {
|
|
14868
|
-
datachannelToken: 'mock-token',
|
|
14869
|
-
dataChannelTokenType: 'llm-practice-session',
|
|
14870
|
-
},
|
|
14871
|
-
});
|
|
14872
|
-
});
|
|
14873
|
-
});
|
|
14874
|
-
describe('#getDataChannelTokenType', () => {
|
|
14875
|
-
it('returns PracticeSession when webinar is in practice session mode', () => {
|
|
14876
|
-
meeting.webinar = {
|
|
14877
|
-
isJoinPracticeSessionDataChannel: sinon.stub().returns(true),
|
|
14878
|
-
};
|
|
14879
|
-
|
|
14880
|
-
const result = meeting.getDataChannelTokenType();
|
|
14881
|
-
|
|
14882
|
-
expect(result).to.equal('llm-practice-session');
|
|
14883
|
-
});
|
|
14884
|
-
|
|
14885
|
-
it('returns Default when not in practice session mode', () => {
|
|
14886
|
-
meeting.webinar = {
|
|
14887
|
-
isJoinPracticeSessionDataChannel: sinon.stub().returns(false),
|
|
14888
|
-
};
|
|
14889
|
-
|
|
14890
|
-
const result = meeting.getDataChannelTokenType();
|
|
14891
|
-
|
|
14892
|
-
expect(result).to.equal('llm-default-session');
|
|
14893
|
-
});
|
|
14894
|
-
});
|
|
14895
14042
|
describe('#stopKeepAlive', () => {
|
|
14896
14043
|
let clock;
|
|
14897
14044
|
const defaultKeepAliveUrl = 'keep.alive.url';
|