@webex/plugin-meetings 3.8.1-web-workers-keepalive.1 → 3.9.0-next.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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +24 -2
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +39 -85
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/brbState.js +14 -12
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +6 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +274 -140
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +19 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/type.js +7 -0
- package/dist/meeting/type.js.map +1 -0
- package/dist/meeting/util.js +68 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +35 -33
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js.map +1 -1
- package/dist/members/index.js +11 -9
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -3
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +18 -6
- package/dist/members/util.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +34 -5
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +42 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +32 -2
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/types/constants.d.ts +22 -0
- package/dist/types/locus-info/index.d.ts +0 -9
- package/dist/types/meeting/brbState.d.ts +0 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +40 -19
- package/dist/types/meeting/request.d.ts +9 -1
- package/dist/types/meeting/request.type.d.ts +74 -0
- package/dist/types/meeting/type.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +3 -0
- package/dist/types/members/index.d.ts +10 -7
- package/dist/types/members/request.d.ts +1 -1
- package/dist/types/members/util.d.ts +7 -3
- package/dist/types/multistream/remoteMedia.d.ts +20 -1
- package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
- package/dist/types/multistream/sendSlotManager.d.ts +16 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -23
- package/src/constants.ts +23 -2
- package/src/locus-info/index.ts +48 -86
- package/src/meeting/brbState.ts +9 -7
- package/src/meeting/in-meeting-actions.ts +13 -0
- package/src/meeting/index.ts +165 -38
- package/src/meeting/request.ts +16 -0
- package/src/meeting/request.type.ts +64 -0
- package/src/meeting/type.ts +9 -0
- package/src/meeting/util.ts +73 -2
- package/src/meetings/index.ts +3 -2
- package/src/member/index.ts +1 -0
- package/src/members/index.ts +13 -10
- package/src/members/request.ts +2 -2
- package/src/members/util.ts +16 -4
- package/src/multistream/mediaRequestManager.ts +7 -7
- package/src/multistream/remoteMedia.ts +34 -4
- package/src/multistream/remoteMediaGroup.ts +37 -2
- package/src/multistream/sendSlotManager.ts +34 -2
- package/test/unit/spec/locus-info/index.js +199 -83
- package/test/unit/spec/meeting/brbState.ts +9 -9
- package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
- package/test/unit/spec/meeting/index.js +729 -80
- package/test/unit/spec/meeting/request.js +71 -0
- package/test/unit/spec/meeting/utils.js +122 -1
- package/test/unit/spec/meetings/index.js +2 -0
- package/test/unit/spec/members/index.js +68 -9
- package/test/unit/spec/members/request.js +2 -2
- package/test/unit/spec/members/utils.js +27 -7
- package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
- package/test/unit/spec/multistream/remoteMedia.ts +66 -2
- package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
- package/test/unit/spec/reachability/index.ts +3 -1
@@ -56,6 +56,7 @@ import * as MeetingRequestImport from '@webex/plugin-meetings/src/meeting/reques
|
|
56
56
|
import LocusInfo from '@webex/plugin-meetings/src/locus-info';
|
57
57
|
import MediaProperties from '@webex/plugin-meetings/src/media/properties';
|
58
58
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
59
|
+
import MembersUtil from '@webex/plugin-meetings/src/members/util';
|
59
60
|
import MeetingsUtil from '@webex/plugin-meetings/src/meetings/util';
|
60
61
|
import Media from '@webex/plugin-meetings/src/media/index';
|
61
62
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
@@ -244,6 +245,7 @@ describe('plugin-meetings', () => {
|
|
244
245
|
});
|
245
246
|
|
246
247
|
webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache = sinon.stub();
|
248
|
+
webex.internal.newMetrics.callDiagnosticMetrics.clearEventLimitsForCorrelationId = sinon.stub();
|
247
249
|
webex.internal.support.submitLogs = sinon.stub().returns(Promise.resolve());
|
248
250
|
webex.internal.services = {get: sinon.stub().returns('locus-url')};
|
249
251
|
webex.credentials.getOrgId = sinon.stub().returns('fake-org-id');
|
@@ -368,6 +370,35 @@ describe('plugin-meetings', () => {
|
|
368
370
|
assert.instanceOf(meeting.simultaneousInterpretation, SimultaneousInterpretation);
|
369
371
|
assert.instanceOf(meeting.webinar, Webinar);
|
370
372
|
});
|
373
|
+
|
374
|
+
it('should call the callback with the meeting that has id already set', () => {
|
375
|
+
let meetingIdFromCallback;
|
376
|
+
// check that the meeting id is already set correctly at the time when the callback is called
|
377
|
+
const meetingCreationCallback = sinon.stub().callsFake((meeting) => {
|
378
|
+
meetingIdFromCallback = meeting.id;
|
379
|
+
});
|
380
|
+
|
381
|
+
meeting = new Meeting(
|
382
|
+
{
|
383
|
+
userId: uuid1,
|
384
|
+
resource: uuid2,
|
385
|
+
deviceUrl: uuid3,
|
386
|
+
locus: {url: url1},
|
387
|
+
destination: testDestination,
|
388
|
+
destinationType: DESTINATION_TYPE.MEETING_ID,
|
389
|
+
correlationId,
|
390
|
+
selfId: uuid1,
|
391
|
+
},
|
392
|
+
{
|
393
|
+
parent: webex,
|
394
|
+
},
|
395
|
+
meetingCreationCallback
|
396
|
+
);
|
397
|
+
assert.exists(meeting.id);
|
398
|
+
assert.calledOnceWithExactly(meetingCreationCallback, meeting);
|
399
|
+
assert.equal(meeting.id, meetingIdFromCallback);
|
400
|
+
});
|
401
|
+
|
371
402
|
it('creates MediaRequestManager instances', () => {
|
372
403
|
assert.instanceOf(meeting.mediaRequestManagers.audio, MediaRequestManager);
|
373
404
|
assert.instanceOf(meeting.mediaRequestManagers.video, MediaRequestManager);
|
@@ -454,6 +485,18 @@ describe('plugin-meetings', () => {
|
|
454
485
|
});
|
455
486
|
});
|
456
487
|
|
488
|
+
it('pstnCorrelationId getter/setter should work correctly', () => {
|
489
|
+
const testPstnCorrelationId = uuid.v4();
|
490
|
+
|
491
|
+
meeting.pstnCorrelationId = testPstnCorrelationId;
|
492
|
+
assert.equal(meeting.pstnCorrelationId, testPstnCorrelationId);
|
493
|
+
assert.equal(meeting.callStateForMetrics.pstnCorrelationId, testPstnCorrelationId);
|
494
|
+
|
495
|
+
meeting.pstnCorrelationId = undefined;
|
496
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
497
|
+
assert.equal(meeting.callStateForMetrics.pstnCorrelationId, undefined);
|
498
|
+
});
|
499
|
+
|
457
500
|
describe('creates ReceiveSlot manager instance', () => {
|
458
501
|
let mockReceiveSlotManagerCtor;
|
459
502
|
let providedCreateSlotCallback;
|
@@ -581,7 +624,6 @@ describe('plugin-meetings', () => {
|
|
581
624
|
assert.isFalse(meeting.isLocusCall());
|
582
625
|
});
|
583
626
|
});
|
584
|
-
|
585
627
|
describe('#invite', () => {
|
586
628
|
it('should have #invite', () => {
|
587
629
|
assert.exists(meeting.invite);
|
@@ -592,8 +634,6 @@ describe('plugin-meetings', () => {
|
|
592
634
|
it('should proxy members #addMember and return a promise', async () => {
|
593
635
|
const invite = meeting.invite(uuid1, false);
|
594
636
|
|
595
|
-
assert.exists(invite.then);
|
596
|
-
await invite;
|
597
637
|
assert.calledOnce(meeting.members.addMember);
|
598
638
|
assert.calledWith(meeting.members.addMember, uuid1, false);
|
599
639
|
});
|
@@ -614,20 +654,20 @@ describe('plugin-meetings', () => {
|
|
614
654
|
assert.calledWith(meeting.members.cancelPhoneInvite, uuid1);
|
615
655
|
});
|
616
656
|
});
|
617
|
-
describe('#
|
618
|
-
it('should have #
|
619
|
-
assert.exists(meeting.
|
657
|
+
describe('#cancelInviteByMemberId', () => {
|
658
|
+
it('should have #cancelInviteByMemberId', () => {
|
659
|
+
assert.exists(meeting.cancelInviteByMemberId);
|
620
660
|
});
|
621
661
|
beforeEach(() => {
|
622
|
-
meeting.members.
|
662
|
+
meeting.members.cancelInviteByMemberId = sinon.stub().returns(Promise.resolve(test1));
|
623
663
|
});
|
624
|
-
it('should proxy members #
|
625
|
-
const cancel = meeting.
|
664
|
+
it('should proxy members #cancelInviteByMemberId and return a promise', async () => {
|
665
|
+
const cancel = meeting.cancelInviteByMemberId({memberId: uuid1});
|
626
666
|
|
627
667
|
assert.exists(cancel.then);
|
628
668
|
await cancel;
|
629
|
-
assert.calledOnce(meeting.members.
|
630
|
-
assert.calledWith(meeting.members.
|
669
|
+
assert.calledOnce(meeting.members.cancelInviteByMemberId);
|
670
|
+
assert.calledWith(meeting.members.cancelInviteByMemberId, {memberId: uuid1});
|
631
671
|
});
|
632
672
|
});
|
633
673
|
describe('#admit', () => {
|
@@ -1219,14 +1259,13 @@ describe('plugin-meetings', () => {
|
|
1219
1259
|
allowMediaInLobby: true,
|
1220
1260
|
},
|
1221
1261
|
});
|
1222
|
-
|
1262
|
+
|
1223
1263
|
assert.calledWithMatch(
|
1224
1264
|
meeting.addMediaInternal,
|
1225
1265
|
sinon.match.any,
|
1226
1266
|
sinon.match.any,
|
1227
1267
|
sinon.match.any,
|
1228
|
-
sinon.match.has('videoEnabled', false)
|
1229
|
-
.and(sinon.match.has('allowMediaInLobby', true))
|
1268
|
+
sinon.match.has('videoEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
|
1230
1269
|
);
|
1231
1270
|
});
|
1232
1271
|
|
@@ -1235,23 +1274,21 @@ describe('plugin-meetings', () => {
|
|
1235
1274
|
joinOptions,
|
1236
1275
|
mediaOptions: {
|
1237
1276
|
audioEnabled: false,
|
1238
|
-
sendAudio: true,
|
1239
|
-
receiveAudio: false,
|
1277
|
+
sendAudio: true,
|
1278
|
+
receiveAudio: false,
|
1240
1279
|
allowMediaInLobby: true,
|
1241
1280
|
},
|
1242
1281
|
});
|
1243
|
-
|
1282
|
+
|
1244
1283
|
assert.calledWithMatch(
|
1245
1284
|
meeting.addMediaInternal,
|
1246
1285
|
sinon.match.any,
|
1247
1286
|
sinon.match.any,
|
1248
1287
|
sinon.match.any,
|
1249
|
-
sinon.match.has('audioEnabled', false)
|
1250
|
-
.and(sinon.match.has('allowMediaInLobby', true))
|
1288
|
+
sinon.match.has('audioEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
|
1251
1289
|
);
|
1252
|
-
});
|
1290
|
+
});
|
1253
1291
|
|
1254
|
-
|
1255
1292
|
it('should use provided send/receive values when videoEnabled/audioEnabled are true or not set', async () => {
|
1256
1293
|
await meeting.joinWithMedia({
|
1257
1294
|
joinOptions,
|
@@ -1263,7 +1300,7 @@ describe('plugin-meetings', () => {
|
|
1263
1300
|
allowMediaInLobby: true,
|
1264
1301
|
},
|
1265
1302
|
});
|
1266
|
-
|
1303
|
+
|
1267
1304
|
assert.calledWith(
|
1268
1305
|
meeting.addMediaInternal,
|
1269
1306
|
sinon.match.any,
|
@@ -1301,12 +1338,11 @@ describe('plugin-meetings', () => {
|
|
1301
1338
|
sinon.restore();
|
1302
1339
|
});
|
1303
1340
|
it('should call voicea.onSpokenLanguageUpdate when joined', async () => {
|
1304
|
-
|
1305
1341
|
meeting.joinedWith = {state: 'JOINED'};
|
1306
1342
|
await meeting.locusInfo.emitScoped(
|
1307
1343
|
{function: 'test', file: 'test'},
|
1308
1344
|
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
1309
|
-
{spokenLanguage: 'fr'}
|
1345
|
+
{spokenLanguage: 'fr'}
|
1310
1346
|
);
|
1311
1347
|
assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr', meeting.id);
|
1312
1348
|
assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'fr');
|
@@ -1319,12 +1355,11 @@ describe('plugin-meetings', () => {
|
|
1319
1355
|
});
|
1320
1356
|
|
1321
1357
|
it('should also call voicea.onSpokenLanguageUpdate when not joined', async () => {
|
1322
|
-
|
1323
1358
|
meeting.joinedWith = {state: 'NOT_JOINED'};
|
1324
1359
|
await meeting.locusInfo.emitScoped(
|
1325
1360
|
{function: 'test', file: 'test'},
|
1326
1361
|
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
1327
|
-
{spokenLanguage: 'de'}
|
1362
|
+
{spokenLanguage: 'de'}
|
1328
1363
|
);
|
1329
1364
|
assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'de');
|
1330
1365
|
assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'de');
|
@@ -1954,21 +1989,25 @@ describe('plugin-meetings', () => {
|
|
1954
1989
|
});
|
1955
1990
|
});
|
1956
1991
|
|
1957
|
-
it('should
|
1992
|
+
it('should handle join failure', async () => {
|
1958
1993
|
MeetingUtil.isPinOrGuest = sinon.stub().returns(false);
|
1994
|
+
webex.internal.newMetrics.submitClientEvent = sinon.stub();
|
1995
|
+
|
1959
1996
|
await meeting.join().catch(() => {
|
1960
|
-
assert.
|
1961
|
-
|
1962
|
-
|
1963
|
-
);
|
1964
|
-
assert.
|
1965
|
-
webex.internal.newMetrics.submitClientEvent
|
1997
|
+
assert.calledOnce(MeetingUtil.joinMeeting);
|
1998
|
+
|
1999
|
+
// Assert that client.locus.join.response error event is not sent from this function, it is now emitted from MeetingUtil.joinMeeting
|
2000
|
+
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
2001
|
+
assert.calledWithMatch(
|
2002
|
+
webex.internal.newMetrics.submitClientEvent,
|
1966
2003
|
{
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
2004
|
+
name: 'client.call.initiated',
|
2005
|
+
payload: {
|
2006
|
+
trigger: 'user-interaction',
|
2007
|
+
isRoapCallEnabled: true,
|
2008
|
+
pstnAudioType: undefined
|
2009
|
+
},
|
2010
|
+
options: {meetingId: meeting.id},
|
1972
2011
|
}
|
1973
2012
|
);
|
1974
2013
|
});
|
@@ -2169,14 +2208,12 @@ describe('plugin-meetings', () => {
|
|
2169
2208
|
};
|
2170
2209
|
meeting.mediaProperties.setMediaDirection = sinon.stub().returns(true);
|
2171
2210
|
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
2172
|
-
meeting.mediaProperties.getCurrentConnectionInfo = sinon
|
2173
|
-
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
|
2178
|
-
ipVersion: 'IPv6',
|
2179
|
-
});
|
2211
|
+
meeting.mediaProperties.getCurrentConnectionInfo = sinon.stub().resolves({
|
2212
|
+
connectionType: 'udp',
|
2213
|
+
selectedCandidatePairChanges: 2,
|
2214
|
+
numTransports: 1,
|
2215
|
+
ipVersion: 'IPv6',
|
2216
|
+
});
|
2180
2217
|
meeting.audio = muteStateStub;
|
2181
2218
|
meeting.video = muteStateStub;
|
2182
2219
|
sinon.stub(Media, 'createMediaConnection').returns(fakeMediaConnection);
|
@@ -3401,8 +3438,8 @@ describe('plugin-meetings', () => {
|
|
3401
3438
|
meeting.mediaConnections = [
|
3402
3439
|
{
|
3403
3440
|
mediaAgentCluster: 'some.cluster',
|
3404
|
-
}
|
3405
|
-
]
|
3441
|
+
},
|
3442
|
+
];
|
3406
3443
|
meeting.iceCandidatesCount = 3;
|
3407
3444
|
meeting.iceCandidateErrors.set('701_error', 3);
|
3408
3445
|
meeting.iceCandidateErrors.set('701_turn_host_lookup_received_error', 1);
|
@@ -3583,12 +3620,12 @@ describe('plugin-meetings', () => {
|
|
3583
3620
|
stopReachability: sinon.stub(),
|
3584
3621
|
isSubnetReachable: sinon.stub().returns(false),
|
3585
3622
|
};
|
3586
|
-
meeting.mediaServerIp =
|
3623
|
+
meeting.mediaServerIp = '1.2.3.4';
|
3587
3624
|
meeting.mediaConnections = [
|
3588
3625
|
{
|
3589
3626
|
mediaAgentCluster: 'some.cluster',
|
3590
|
-
}
|
3591
|
-
]
|
3627
|
+
},
|
3628
|
+
];
|
3592
3629
|
|
3593
3630
|
const forceRtcMetricsSend = sinon.stub().resolves();
|
3594
3631
|
const closeMediaConnectionStub = sinon.stub();
|
@@ -3638,12 +3675,12 @@ describe('plugin-meetings', () => {
|
|
3638
3675
|
stopReachability: sinon.stub(),
|
3639
3676
|
isSubnetReachable: sinon.stub().returns(true),
|
3640
3677
|
};
|
3641
|
-
meeting.mediaServerIp =
|
3678
|
+
meeting.mediaServerIp = '1.2.3.4';
|
3642
3679
|
meeting.mediaConnections = [
|
3643
3680
|
{
|
3644
3681
|
mediaAgentCluster: 'some.cluster',
|
3645
|
-
}
|
3646
|
-
]
|
3682
|
+
},
|
3683
|
+
];
|
3647
3684
|
|
3648
3685
|
const forceRtcMetricsSend = sinon.stub().resolves();
|
3649
3686
|
const closeMediaConnectionStub = sinon.stub();
|
@@ -4355,9 +4392,7 @@ describe('plugin-meetings', () => {
|
|
4355
4392
|
const error = new Error();
|
4356
4393
|
meeting.meetingRequest.setBrb = sinon.stub().rejects(error);
|
4357
4394
|
|
4358
|
-
await expect(
|
4359
|
-
meeting.beRightBack(true)
|
4360
|
-
).to.be.rejectedWith(error);
|
4395
|
+
await expect(meeting.beRightBack(true)).to.be.rejectedWith(error);
|
4361
4396
|
|
4362
4397
|
assert.isFalse(meeting.brbState.state.syncToServerInProgress);
|
4363
4398
|
});
|
@@ -6507,12 +6542,17 @@ describe('plugin-meetings', () => {
|
|
6507
6542
|
const DIAL_IN_URL = meeting.dialInUrl;
|
6508
6543
|
|
6509
6544
|
assert.calledWith(meeting.meetingRequest.dialIn, {
|
6510
|
-
correlationId: meeting.
|
6545
|
+
correlationId: meeting.pstnCorrelationId,
|
6511
6546
|
dialInUrl: DIAL_IN_URL,
|
6512
6547
|
locusUrl: meeting.locusUrl,
|
6513
6548
|
clientUrl: meeting.deviceUrl,
|
6514
6549
|
});
|
6515
6550
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
6551
|
+
|
6552
|
+
// Verify pstnCorrelationId was set
|
6553
|
+
assert.exists(meeting.pstnCorrelationId);
|
6554
|
+
assert.notEqual(meeting.pstnCorrelationId, meeting.correlationId);
|
6555
|
+
const firstPstnCorrelationId = meeting.pstnCorrelationId
|
6516
6556
|
|
6517
6557
|
meeting.meetingRequest.dialIn.resetHistory();
|
6518
6558
|
|
@@ -6520,12 +6560,18 @@ describe('plugin-meetings', () => {
|
|
6520
6560
|
await meeting.usePhoneAudio();
|
6521
6561
|
|
6522
6562
|
assert.calledWith(meeting.meetingRequest.dialIn, {
|
6523
|
-
correlationId: meeting.
|
6563
|
+
correlationId: meeting.pstnCorrelationId,
|
6524
6564
|
dialInUrl: DIAL_IN_URL,
|
6525
6565
|
locusUrl: meeting.locusUrl,
|
6526
6566
|
clientUrl: meeting.deviceUrl,
|
6527
6567
|
});
|
6528
6568
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
6569
|
+
// A new PSTN correlationId should be generated for the second attempt
|
6570
|
+
assert.notEqual(
|
6571
|
+
meeting.pstnCorrelationId,
|
6572
|
+
firstPstnCorrelationId,
|
6573
|
+
'pstnCorrelationId should be regenerated on each dial-in attempt'
|
6574
|
+
);
|
6529
6575
|
});
|
6530
6576
|
|
6531
6577
|
it('given a phone number, triggers dial-out, delegating request to meetingRequest correctly', async () => {
|
@@ -6535,7 +6581,7 @@ describe('plugin-meetings', () => {
|
|
6535
6581
|
const DIAL_OUT_URL = meeting.dialOutUrl;
|
6536
6582
|
|
6537
6583
|
assert.calledWith(meeting.meetingRequest.dialOut, {
|
6538
|
-
correlationId: meeting.
|
6584
|
+
correlationId: meeting.pstnCorrelationId,
|
6539
6585
|
dialOutUrl: DIAL_OUT_URL,
|
6540
6586
|
locusUrl: meeting.locusUrl,
|
6541
6587
|
clientUrl: meeting.deviceUrl,
|
@@ -6543,49 +6589,126 @@ describe('plugin-meetings', () => {
|
|
6543
6589
|
});
|
6544
6590
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
6545
6591
|
|
6592
|
+
// Verify pstnCorrelationId was set
|
6593
|
+
assert.exists(meeting.pstnCorrelationId);
|
6594
|
+
assert.notEqual(meeting.pstnCorrelationId, meeting.correlationId);
|
6595
|
+
const firstPstnCorrelationId = meeting.pstnCorrelationId;
|
6596
|
+
|
6546
6597
|
meeting.meetingRequest.dialOut.resetHistory();
|
6547
6598
|
|
6548
6599
|
// try again. the dial out urls should match
|
6549
6600
|
await meeting.usePhoneAudio(phoneNumber);
|
6550
6601
|
|
6551
6602
|
assert.calledWith(meeting.meetingRequest.dialOut, {
|
6552
|
-
correlationId: meeting.
|
6603
|
+
correlationId: meeting.pstnCorrelationId,
|
6553
6604
|
dialOutUrl: DIAL_OUT_URL,
|
6554
6605
|
locusUrl: meeting.locusUrl,
|
6555
6606
|
clientUrl: meeting.deviceUrl,
|
6556
6607
|
phoneNumber,
|
6557
6608
|
});
|
6558
6609
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
6610
|
+
// A new PSTN correlationId should be generated for the second attempt
|
6611
|
+
assert.notEqual(
|
6612
|
+
meeting.pstnCorrelationId,
|
6613
|
+
firstPstnCorrelationId,
|
6614
|
+
'pstnCorrelationId should be regenerated on each dial-out attempt'
|
6615
|
+
);
|
6559
6616
|
});
|
6560
6617
|
|
6561
|
-
it('rejects if the request failed (dial in)', () => {
|
6562
|
-
const error = '
|
6618
|
+
it('rejects if the request failed (dial in)', async () => {
|
6619
|
+
const error = {error: {message: 'dial in failed'}, stack: 'error stack'};
|
6563
6620
|
|
6564
6621
|
meeting.meetingRequest.dialIn = sinon.stub().returns(Promise.reject(error));
|
6565
6622
|
|
6566
|
-
|
6567
|
-
.usePhoneAudio()
|
6568
|
-
|
6569
|
-
|
6570
|
-
|
6571
|
-
|
6572
|
-
|
6623
|
+
try {
|
6624
|
+
await meeting.usePhoneAudio();
|
6625
|
+
throw new Error('Promise resolved when it should have rejected');
|
6626
|
+
} catch (e) {
|
6627
|
+
assert.equal(e, error);
|
6628
|
+
|
6629
|
+
// Verify behavioral metric was sent with dial_in_correlation_id
|
6630
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
|
6631
|
+
correlation_id: meeting.correlationId,
|
6632
|
+
dial_in_url: meeting.dialInUrl,
|
6633
|
+
dial_in_correlation_id: sinon.match.string,
|
6634
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
6635
|
+
client_url: meeting.deviceUrl,
|
6636
|
+
reason: error.error.message,
|
6637
|
+
stack: error.stack,
|
6573
6638
|
});
|
6639
|
+
|
6640
|
+
// Verify pstnCorrelationId was cleared after error
|
6641
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6642
|
+
}
|
6574
6643
|
});
|
6575
6644
|
|
6576
6645
|
it('rejects if the request failed (dial out)', async () => {
|
6577
|
-
const error = '
|
6646
|
+
const error = {error: {message: 'dial out failed'}, stack: 'error stack'};
|
6578
6647
|
|
6579
6648
|
meeting.meetingRequest.dialOut = sinon.stub().returns(Promise.reject(error));
|
6580
6649
|
|
6581
|
-
|
6582
|
-
.usePhoneAudio('+441234567890')
|
6583
|
-
|
6584
|
-
|
6585
|
-
|
6586
|
-
|
6587
|
-
|
6650
|
+
try {
|
6651
|
+
await meeting.usePhoneAudio('+441234567890');
|
6652
|
+
throw new Error('Promise resolved when it should have rejected');
|
6653
|
+
} catch (e) {
|
6654
|
+
assert.equal(e, error);
|
6655
|
+
|
6656
|
+
// Verify behavioral metric was sent with dial_out_correlation_id
|
6657
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
|
6658
|
+
correlation_id: meeting.correlationId,
|
6659
|
+
dial_out_url: meeting.dialOutUrl,
|
6660
|
+
dial_out_correlation_id: sinon.match.string,
|
6661
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
6662
|
+
client_url: meeting.deviceUrl,
|
6663
|
+
reason: error.error.message,
|
6664
|
+
stack: error.stack,
|
6588
6665
|
});
|
6666
|
+
|
6667
|
+
// Verify pstnCorrelationId was cleared after error
|
6668
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6669
|
+
}
|
6670
|
+
});
|
6671
|
+
});
|
6672
|
+
|
6673
|
+
describe('#disconnectPhoneAudio', () => {
|
6674
|
+
beforeEach(() => {
|
6675
|
+
// Mock the MeetingUtil.disconnectPhoneAudio method
|
6676
|
+
sinon.stub(MeetingUtil, 'disconnectPhoneAudio').resolves();
|
6677
|
+
meeting.dialInUrl = 'dialin:///test-dial-in-url';
|
6678
|
+
meeting.dialOutUrl = 'dialout:///test-dial-out-url';
|
6679
|
+
meeting.dialInDeviceStatus = 'JOINED';
|
6680
|
+
meeting.dialOutDeviceStatus = 'JOINED';
|
6681
|
+
});
|
6682
|
+
|
6683
|
+
afterEach(() => {
|
6684
|
+
MeetingUtil.disconnectPhoneAudio.restore();
|
6685
|
+
});
|
6686
|
+
|
6687
|
+
it('should disconnect phone audio and clear pstnCorrelationId', async () => {
|
6688
|
+
meeting.pstnCorrelationId = 'test-pstn-correlation-id';
|
6689
|
+
|
6690
|
+
await meeting.disconnectPhoneAudio();
|
6691
|
+
|
6692
|
+
// Verify that pstnCorrelationId is cleared
|
6693
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6694
|
+
|
6695
|
+
// Verify that MeetingUtil.disconnectPhoneAudio was called for both dial-in and dial-out
|
6696
|
+
assert.calledTwice(MeetingUtil.disconnectPhoneAudio);
|
6697
|
+
assert.calledWith(MeetingUtil.disconnectPhoneAudio, meeting, meeting.dialInUrl);
|
6698
|
+
assert.calledWith(MeetingUtil.disconnectPhoneAudio, meeting, meeting.dialOutUrl);
|
6699
|
+
});
|
6700
|
+
|
6701
|
+
it('should handle case when no PSTN connection is active', async () => {
|
6702
|
+
meeting.dialInDeviceStatus = 'IDLE';
|
6703
|
+
meeting.dialOutDeviceStatus = 'IDLE';
|
6704
|
+
meeting.pstnCorrelationId = 'test-pstn-correlation-id';
|
6705
|
+
|
6706
|
+
await meeting.disconnectPhoneAudio();
|
6707
|
+
|
6708
|
+
// Verify that pstnCorrelationId is still cleared even when no phone connection is active
|
6709
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6710
|
+
// And verify no disconnect was attempted
|
6711
|
+
assert.notCalled(MeetingUtil.disconnectPhoneAudio);
|
6589
6712
|
});
|
6590
6713
|
});
|
6591
6714
|
|
@@ -8016,11 +8139,13 @@ describe('plugin-meetings', () => {
|
|
8016
8139
|
meeting.isoLocalClientMeetingJoinTime = undefined;
|
8017
8140
|
assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
|
8018
8141
|
});
|
8142
|
+
|
8019
8143
|
it('should fallback to system clock ISO string when given an invalid value', () => {
|
8020
8144
|
const currentSystemTime = new Date().toISOString();
|
8021
8145
|
meeting.isoLocalClientMeetingJoinTime = 'invalid-date';
|
8022
8146
|
assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
|
8023
8147
|
});
|
8148
|
+
|
8024
8149
|
it('should set the isoLocalClientMeetingJoinTime correctly for a valid date string', () => {
|
8025
8150
|
const validDateString = 'Tue, 01 Apr 2025 13:00:36 GMT';
|
8026
8151
|
const expectedISOString = new Date(validDateString).toISOString();
|
@@ -8100,6 +8225,7 @@ describe('plugin-meetings', () => {
|
|
8100
8225
|
|
8101
8226
|
meeting.requestScreenShareFloor = sinon.stub().resolves({});
|
8102
8227
|
meeting.releaseScreenShareFloor = sinon.stub().resolves({});
|
8228
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
8103
8229
|
meeting.mediaProperties.mediaDirection = {
|
8104
8230
|
sendAudio: 'fake value', // using non-boolean here so that we can check that these values are untouched in tests
|
8105
8231
|
sendVideo: 'fake value',
|
@@ -8181,6 +8307,12 @@ describe('plugin-meetings', () => {
|
|
8181
8307
|
payload: {mediaType: 'share', shareInstanceId: meeting.localShareInstanceId},
|
8182
8308
|
options: {meetingId: meeting.id},
|
8183
8309
|
});
|
8310
|
+
|
8311
|
+
// ensure the share start timestamp is saved
|
8312
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
8313
|
+
key: 'internal.client.share.initiated',
|
8314
|
+
});
|
8315
|
+
|
8184
8316
|
assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
|
8185
8317
|
|
8186
8318
|
assert.equal(meeting.shareCAEventSentStatus.transmitStart, false);
|
@@ -8199,6 +8331,11 @@ describe('plugin-meetings', () => {
|
|
8199
8331
|
options: {meetingId: meeting.id},
|
8200
8332
|
});
|
8201
8333
|
|
8334
|
+
// ensure the share start timestamp is saved
|
8335
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
8336
|
+
key: 'internal.client.share.initiated',
|
8337
|
+
});
|
8338
|
+
|
8202
8339
|
assert.calledWith(
|
8203
8340
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
|
8204
8341
|
stream
|
@@ -9194,6 +9331,7 @@ describe('plugin-meetings', () => {
|
|
9194
9331
|
meeting.deferSDPAnswer = {
|
9195
9332
|
reject: sinon.stub(),
|
9196
9333
|
};
|
9334
|
+
|
9197
9335
|
const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
|
9198
9336
|
|
9199
9337
|
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
@@ -10471,6 +10609,8 @@ describe('plugin-meetings', () => {
|
|
10471
10609
|
meeting.mediaProperties = {mediaDirection: {sendShare: true}};
|
10472
10610
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
10473
10611
|
(meeting.deviceUrl = 'deviceUrl.com'), (meeting.localShareInstanceId = '1234-5678');
|
10612
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
10613
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration = sinon.stub().returns(1000);
|
10474
10614
|
});
|
10475
10615
|
it('should call changeMeetingFloor()', async () => {
|
10476
10616
|
meeting.screenShareFloorState = 'GRANTED';
|
@@ -10488,6 +10628,22 @@ describe('plugin-meetings', () => {
|
|
10488
10628
|
assert.exists(share.then);
|
10489
10629
|
await share;
|
10490
10630
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
10631
|
+
|
10632
|
+
// ensure the share stop timestamp is saved
|
10633
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
10634
|
+
key: 'internal.client.share.stopped',
|
10635
|
+
});
|
10636
|
+
|
10637
|
+
// ensure the CA share stopped metric is submitted with duration
|
10638
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
10639
|
+
name: 'client.share.stopped',
|
10640
|
+
payload: {
|
10641
|
+
mediaType: 'share',
|
10642
|
+
shareInstanceId: meeting.localShareInstanceId,
|
10643
|
+
shareDuration: 1000,
|
10644
|
+
},
|
10645
|
+
options: {meetingId: meeting.id},
|
10646
|
+
});
|
10491
10647
|
});
|
10492
10648
|
it('should not call changeMeetingFloor() if someone else already has the floor', async () => {
|
10493
10649
|
// change selfId so that it doesn't match the beneficiary id from meeting.locusInfo.mediaShares
|
@@ -12060,6 +12216,7 @@ describe('plugin-meetings', () => {
|
|
12060
12216
|
meeting.locusInfo.self = {url: url1};
|
12061
12217
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
12062
12218
|
meeting.deviceUrl = 'deviceUrl.com';
|
12219
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
12063
12220
|
});
|
12064
12221
|
it('should have #startWhiteboardShare', () => {
|
12065
12222
|
assert.exists(meeting.startWhiteboardShare);
|
@@ -12087,6 +12244,11 @@ describe('plugin-meetings', () => {
|
|
12087
12244
|
payload: {mediaType: 'whiteboard'},
|
12088
12245
|
options: {meetingId: meeting.id},
|
12089
12246
|
});
|
12247
|
+
|
12248
|
+
// ensure the share start timestamp is saved
|
12249
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
12250
|
+
key: 'internal.client.share.initiated',
|
12251
|
+
});
|
12090
12252
|
});
|
12091
12253
|
});
|
12092
12254
|
describe('#stopWhiteboardShare', () => {
|
@@ -12098,6 +12260,8 @@ describe('plugin-meetings', () => {
|
|
12098
12260
|
meeting.locusInfo.self = {url: url1};
|
12099
12261
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
12100
12262
|
meeting.deviceUrl = 'deviceUrl.com';
|
12263
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
12264
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration = sinon.stub().returns(1000);
|
12101
12265
|
});
|
12102
12266
|
it('should stop the whiteboard share', async () => {
|
12103
12267
|
const whiteboardShare = meeting.stopWhiteboardShare();
|
@@ -12112,6 +12276,21 @@ describe('plugin-meetings', () => {
|
|
12112
12276
|
uri: url1,
|
12113
12277
|
});
|
12114
12278
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
12279
|
+
|
12280
|
+
// ensure the share stop timestamp is saved
|
12281
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
12282
|
+
key: 'internal.client.share.stopped',
|
12283
|
+
});
|
12284
|
+
|
12285
|
+
// ensure the CA share stopped metric is submitted with duration
|
12286
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
12287
|
+
name: 'client.share.stopped',
|
12288
|
+
payload: {
|
12289
|
+
mediaType: 'whiteboard',
|
12290
|
+
shareDuration: 1000,
|
12291
|
+
},
|
12292
|
+
options: {meetingId: meeting.id},
|
12293
|
+
});
|
12115
12294
|
});
|
12116
12295
|
});
|
12117
12296
|
});
|
@@ -12410,7 +12589,7 @@ describe('plugin-meetings', () => {
|
|
12410
12589
|
activeSharingId.whiteboard = beneficiaryId;
|
12411
12590
|
|
12412
12591
|
eventTrigger.share.push(
|
12413
|
-
meeting.webinar.selfIsAttendee
|
12592
|
+
meeting.webinar.selfIsAttendee || meeting.guest
|
12414
12593
|
? {
|
12415
12594
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
12416
12595
|
functionName: 'remoteShare',
|
@@ -12429,7 +12608,8 @@ describe('plugin-meetings', () => {
|
|
12429
12608
|
}
|
12430
12609
|
);
|
12431
12610
|
|
12432
|
-
shareStatus =
|
12611
|
+
shareStatus =
|
12612
|
+
meeting.webinar.selfIsAttendee || meeting.guest
|
12433
12613
|
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
12434
12614
|
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
12435
12615
|
}
|
@@ -12647,6 +12827,36 @@ describe('plugin-meetings', () => {
|
|
12647
12827
|
});
|
12648
12828
|
});
|
12649
12829
|
|
12830
|
+
describe('Whiteboard Share - User is guest', () => {
|
12831
|
+
it('User receives a remote share instead of whiteboard share', () => {
|
12832
|
+
// Set the guest flag
|
12833
|
+
meeting.guest = true;
|
12834
|
+
|
12835
|
+
// Step 1: Start sharing whiteboard A
|
12836
|
+
const data1 = generateData(
|
12837
|
+
blankPayload, // Initial payload
|
12838
|
+
true, // isGranting: Granting share
|
12839
|
+
false, // isContent: Whiteboard (not content)
|
12840
|
+
USER_IDS.REMOTE_A, // Beneficiary ID: Remote user A
|
12841
|
+
RESOURCE_URLS.WHITEBOARD_A // Resource URL: Whiteboard A
|
12842
|
+
);
|
12843
|
+
|
12844
|
+
// Step 2: Stop sharing whiteboard A
|
12845
|
+
const data2 = generateData(
|
12846
|
+
data1.payload, // Updated payload from Step 1
|
12847
|
+
false, // isGranting: Stopping share
|
12848
|
+
false, // isContent: Whiteboard
|
12849
|
+
USER_IDS.REMOTE_A // Beneficiary ID: Remote user A
|
12850
|
+
);
|
12851
|
+
|
12852
|
+
// Validate the payload changes and status updates
|
12853
|
+
payloadTestHelper([data1]);
|
12854
|
+
|
12855
|
+
// Specific assertions for guest
|
12856
|
+
assert.equal(meeting.shareStatus, SHARE_STATUS.REMOTE_SHARE_ACTIVE);
|
12857
|
+
});
|
12858
|
+
});
|
12859
|
+
|
12650
12860
|
describe('Whiteboard A --> Whiteboard B', () => {
|
12651
12861
|
it('Scenario #1: you share both whiteboards', () => {
|
12652
12862
|
const data1 = generateData(
|
@@ -14091,4 +14301,443 @@ describe('plugin-meetings', () => {
|
|
14091
14301
|
assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
|
14092
14302
|
});
|
14093
14303
|
});
|
14304
|
+
|
14305
|
+
describe('#setStage', () => {
|
14306
|
+
const check = async (options, expectedVideoLayout) => {
|
14307
|
+
const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
|
14308
|
+
meeting.locusUrl = locusUrl;
|
14309
|
+
|
14310
|
+
const setStagePromise = meeting.setStage(options);
|
14311
|
+
|
14312
|
+
assert.exists(setStagePromise.then);
|
14313
|
+
await setStagePromise;
|
14314
|
+
|
14315
|
+
assert.calledOnceWithExactly(
|
14316
|
+
meeting.meetingRequest.synchronizeStage,
|
14317
|
+
locusUrl,
|
14318
|
+
expectedVideoLayout
|
14319
|
+
);
|
14320
|
+
};
|
14321
|
+
|
14322
|
+
beforeEach(() => {
|
14323
|
+
meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
|
14324
|
+
});
|
14325
|
+
|
14326
|
+
it('sends the expected request when no options are provided', async () => {
|
14327
|
+
await check(undefined, {
|
14328
|
+
overrideDefault: true,
|
14329
|
+
lockAttendeeViewOnStageOnly: false,
|
14330
|
+
stageParameters: {
|
14331
|
+
activeSpeakerProportion: 0.5,
|
14332
|
+
showActiveSpeaker: {show: false, order: 0},
|
14333
|
+
stageManagerType: 0,
|
14334
|
+
},
|
14335
|
+
});
|
14336
|
+
});
|
14337
|
+
|
14338
|
+
it('sends the expected request when empty options are provided', async () => {
|
14339
|
+
await check(
|
14340
|
+
{},
|
14341
|
+
{
|
14342
|
+
overrideDefault: true,
|
14343
|
+
lockAttendeeViewOnStageOnly: false,
|
14344
|
+
stageParameters: {
|
14345
|
+
activeSpeakerProportion: 0.5,
|
14346
|
+
showActiveSpeaker: {show: false, order: 0},
|
14347
|
+
stageManagerType: 0,
|
14348
|
+
},
|
14349
|
+
}
|
14350
|
+
);
|
14351
|
+
});
|
14352
|
+
|
14353
|
+
[0.25, 0.5, 0.75].forEach((activeSpeakerProportion) => {
|
14354
|
+
it(`sends the expected request when only the active speaker proportion option is provided as ${activeSpeakerProportion}`, async () => {
|
14355
|
+
await check(
|
14356
|
+
{activeSpeakerProportion},
|
14357
|
+
{
|
14358
|
+
overrideDefault: true,
|
14359
|
+
lockAttendeeViewOnStageOnly: false,
|
14360
|
+
stageParameters: {
|
14361
|
+
activeSpeakerProportion,
|
14362
|
+
showActiveSpeaker: {show: false, order: 0},
|
14363
|
+
stageManagerType: 0,
|
14364
|
+
},
|
14365
|
+
}
|
14366
|
+
);
|
14367
|
+
});
|
14368
|
+
});
|
14369
|
+
|
14370
|
+
it('sends the expected request when only the custom background option is provided', async () => {
|
14371
|
+
const customBackground = {
|
14372
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14373
|
+
};
|
14374
|
+
|
14375
|
+
await check(
|
14376
|
+
{customBackground},
|
14377
|
+
{
|
14378
|
+
overrideDefault: true,
|
14379
|
+
lockAttendeeViewOnStageOnly: false,
|
14380
|
+
stageParameters: {
|
14381
|
+
activeSpeakerProportion: 0.5,
|
14382
|
+
showActiveSpeaker: {show: false, order: 0},
|
14383
|
+
stageManagerType: 2,
|
14384
|
+
},
|
14385
|
+
customLayouts: {background: customBackground},
|
14386
|
+
}
|
14387
|
+
);
|
14388
|
+
});
|
14389
|
+
|
14390
|
+
it('sends the expected request when only the custom logo option is provided', async () => {
|
14391
|
+
const customLogo = {
|
14392
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14393
|
+
position: 'LowerRight',
|
14394
|
+
};
|
14395
|
+
|
14396
|
+
await check(
|
14397
|
+
{customLogo},
|
14398
|
+
{
|
14399
|
+
overrideDefault: true,
|
14400
|
+
lockAttendeeViewOnStageOnly: false,
|
14401
|
+
stageParameters: {
|
14402
|
+
activeSpeakerProportion: 0.5,
|
14403
|
+
showActiveSpeaker: {show: false, order: 0},
|
14404
|
+
stageManagerType: 1,
|
14405
|
+
},
|
14406
|
+
customLayouts: {logo: customLogo},
|
14407
|
+
}
|
14408
|
+
);
|
14409
|
+
});
|
14410
|
+
|
14411
|
+
it('sends the expected request when only the custom name label option is provided', async () => {
|
14412
|
+
const customNameLabel = {
|
14413
|
+
accentColor: '#0A7806',
|
14414
|
+
background: {color: 'rgba(255, 255, 255, 1)'},
|
14415
|
+
border: {color: 'rgba(255, 255, 255, 1)'},
|
14416
|
+
content: {
|
14417
|
+
displayName: {color: 'rgba(0, 0, 0, 0.95)'},
|
14418
|
+
subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
|
14419
|
+
},
|
14420
|
+
decoration: {color: 'rgba(10, 120, 6, 1)'},
|
14421
|
+
fadeOut: {delay: 15},
|
14422
|
+
type: 'Primary',
|
14423
|
+
};
|
14424
|
+
|
14425
|
+
await check(
|
14426
|
+
{customNameLabel},
|
14427
|
+
{
|
14428
|
+
overrideDefault: true,
|
14429
|
+
lockAttendeeViewOnStageOnly: false,
|
14430
|
+
stageParameters: {
|
14431
|
+
activeSpeakerProportion: 0.5,
|
14432
|
+
showActiveSpeaker: {show: false, order: 0},
|
14433
|
+
stageManagerType: 4,
|
14434
|
+
},
|
14435
|
+
nameLabelStyle: customNameLabel,
|
14436
|
+
}
|
14437
|
+
);
|
14438
|
+
});
|
14439
|
+
|
14440
|
+
it('sends the expected request when only the custom background and logo options are provided', async () => {
|
14441
|
+
const customBackground = {
|
14442
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14443
|
+
};
|
14444
|
+
const customLogo = {
|
14445
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14446
|
+
position: 'UpperRight',
|
14447
|
+
};
|
14448
|
+
|
14449
|
+
await check(
|
14450
|
+
{customBackground, customLogo},
|
14451
|
+
{
|
14452
|
+
overrideDefault: true,
|
14453
|
+
lockAttendeeViewOnStageOnly: false,
|
14454
|
+
stageParameters: {
|
14455
|
+
activeSpeakerProportion: 0.5,
|
14456
|
+
showActiveSpeaker: {show: false, order: 0},
|
14457
|
+
stageManagerType: 3,
|
14458
|
+
},
|
14459
|
+
customLayouts: {background: customBackground, logo: customLogo},
|
14460
|
+
}
|
14461
|
+
);
|
14462
|
+
});
|
14463
|
+
|
14464
|
+
it('sends the expected request when only the custom background and name label options are provided', async () => {
|
14465
|
+
const customBackground = {
|
14466
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14467
|
+
};
|
14468
|
+
const customNameLabel = {
|
14469
|
+
accentColor: '#00A3FF',
|
14470
|
+
background: {color: 'rgba(0, 163, 255, 1)'},
|
14471
|
+
border: {color: 'rgba(0, 163, 255, 1)'},
|
14472
|
+
content: {
|
14473
|
+
displayName: {color: 'rgba(255, 255, 255, 0.95)'},
|
14474
|
+
subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
|
14475
|
+
},
|
14476
|
+
decoration: {color: 'rgba(255, 255, 255, 0.95)'},
|
14477
|
+
fadeOut: {delay: 15},
|
14478
|
+
type: 'PrimaryInverted',
|
14479
|
+
};
|
14480
|
+
|
14481
|
+
await check(
|
14482
|
+
{customBackground, customNameLabel},
|
14483
|
+
{
|
14484
|
+
overrideDefault: true,
|
14485
|
+
lockAttendeeViewOnStageOnly: false,
|
14486
|
+
stageParameters: {
|
14487
|
+
activeSpeakerProportion: 0.5,
|
14488
|
+
showActiveSpeaker: {show: false, order: 0},
|
14489
|
+
stageManagerType: 6,
|
14490
|
+
},
|
14491
|
+
customLayouts: {background: customBackground},
|
14492
|
+
nameLabelStyle: customNameLabel,
|
14493
|
+
}
|
14494
|
+
);
|
14495
|
+
});
|
14496
|
+
|
14497
|
+
it('sends the expected request when only the custom logo and name label options are provided', async () => {
|
14498
|
+
const customLogo = {
|
14499
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14500
|
+
position: 'UpperLeft',
|
14501
|
+
};
|
14502
|
+
const customNameLabel = {
|
14503
|
+
accentColor: '#942B2B',
|
14504
|
+
background: {color: 'rgba(255, 255, 255, 1)'},
|
14505
|
+
border: {color: 'rgba(148, 43, 43, 1)'},
|
14506
|
+
content: {
|
14507
|
+
displayName: {color: 'rgba(0, 0, 0, 0.95)'},
|
14508
|
+
subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
|
14509
|
+
},
|
14510
|
+
decoration: {color: 'rgba(0, 0, 0, 0)'},
|
14511
|
+
fadeOut: {delay: 15},
|
14512
|
+
type: 'Secondary',
|
14513
|
+
};
|
14514
|
+
|
14515
|
+
await check(
|
14516
|
+
{customLogo, customNameLabel},
|
14517
|
+
{
|
14518
|
+
overrideDefault: true,
|
14519
|
+
lockAttendeeViewOnStageOnly: false,
|
14520
|
+
stageParameters: {
|
14521
|
+
activeSpeakerProportion: 0.5,
|
14522
|
+
showActiveSpeaker: {show: false, order: 0},
|
14523
|
+
stageManagerType: 5,
|
14524
|
+
},
|
14525
|
+
customLayouts: {logo: customLogo},
|
14526
|
+
nameLabelStyle: customNameLabel,
|
14527
|
+
}
|
14528
|
+
);
|
14529
|
+
});
|
14530
|
+
|
14531
|
+
it('sends the expected request when only the custom background, logo, name label options are provided', async () => {
|
14532
|
+
const customBackground = {
|
14533
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14534
|
+
};
|
14535
|
+
const customLogo = {
|
14536
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14537
|
+
position: 'LowerLeft',
|
14538
|
+
};
|
14539
|
+
const customNameLabel = {
|
14540
|
+
accentColor: '#EBD960',
|
14541
|
+
background: {color: 'rgba(235, 217, 96, 0.55)'},
|
14542
|
+
border: {color: 'rgba(235, 217, 96, 0.55)'},
|
14543
|
+
content: {
|
14544
|
+
displayName: {color: 'rgba(255, 255, 255, 0.95)'},
|
14545
|
+
subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
|
14546
|
+
},
|
14547
|
+
decoration: {color: 'rgba(0, 0, 0, 0)'},
|
14548
|
+
fadeOut: {delay: 15},
|
14549
|
+
type: 'SecondaryInverted',
|
14550
|
+
};
|
14551
|
+
|
14552
|
+
await check(
|
14553
|
+
{customBackground, customLogo, customNameLabel},
|
14554
|
+
{
|
14555
|
+
overrideDefault: true,
|
14556
|
+
lockAttendeeViewOnStageOnly: false,
|
14557
|
+
stageParameters: {
|
14558
|
+
activeSpeakerProportion: 0.5,
|
14559
|
+
showActiveSpeaker: {show: false, order: 0},
|
14560
|
+
stageManagerType: 7,
|
14561
|
+
},
|
14562
|
+
customLayouts: {background: customBackground, logo: customLogo},
|
14563
|
+
nameLabelStyle: customNameLabel,
|
14564
|
+
}
|
14565
|
+
);
|
14566
|
+
});
|
14567
|
+
|
14568
|
+
it('sends the expected request when only the important participants option is provided as empty', async () => {
|
14569
|
+
await check(
|
14570
|
+
{importantParticipants: []},
|
14571
|
+
{
|
14572
|
+
overrideDefault: true,
|
14573
|
+
lockAttendeeViewOnStageOnly: false,
|
14574
|
+
stageParameters: {
|
14575
|
+
activeSpeakerProportion: 0.5,
|
14576
|
+
showActiveSpeaker: {show: false, order: 0},
|
14577
|
+
stageManagerType: 0,
|
14578
|
+
},
|
14579
|
+
}
|
14580
|
+
);
|
14581
|
+
});
|
14582
|
+
|
14583
|
+
it('sends the expected request when only the important participants option is provided as populated', async () => {
|
14584
|
+
const importantParticipants = [
|
14585
|
+
{mainCsi: 11111111, participantId: uuidv4()},
|
14586
|
+
{mainCsi: 22222222, participantId: uuidv4()},
|
14587
|
+
{mainCsi: 33333333, participantId: uuidv4()},
|
14588
|
+
{mainCsi: 44444444, participantId: uuidv4()},
|
14589
|
+
{mainCsi: 55555555, participantId: uuidv4()},
|
14590
|
+
{mainCsi: 66666666, participantId: uuidv4()},
|
14591
|
+
{mainCsi: 77777777, participantId: uuidv4()},
|
14592
|
+
{mainCsi: 88888888, participantId: uuidv4()},
|
14593
|
+
];
|
14594
|
+
|
14595
|
+
await check(
|
14596
|
+
{importantParticipants},
|
14597
|
+
{
|
14598
|
+
overrideDefault: true,
|
14599
|
+
lockAttendeeViewOnStageOnly: false,
|
14600
|
+
stageParameters: {
|
14601
|
+
activeSpeakerProportion: 0.5,
|
14602
|
+
importantParticipants: [
|
14603
|
+
{...importantParticipants[0], order: 1},
|
14604
|
+
{...importantParticipants[1], order: 2},
|
14605
|
+
{...importantParticipants[2], order: 3},
|
14606
|
+
{...importantParticipants[3], order: 4},
|
14607
|
+
{...importantParticipants[4], order: 5},
|
14608
|
+
{...importantParticipants[5], order: 6},
|
14609
|
+
{...importantParticipants[6], order: 7},
|
14610
|
+
{...importantParticipants[7], order: 8},
|
14611
|
+
],
|
14612
|
+
showActiveSpeaker: {show: false, order: 0},
|
14613
|
+
stageManagerType: 0,
|
14614
|
+
},
|
14615
|
+
}
|
14616
|
+
);
|
14617
|
+
});
|
14618
|
+
|
14619
|
+
[false, true].forEach((lockAttendeeViewOnStage) => {
|
14620
|
+
it(`sends the expected request when only the lock attendee view on stage option is provided as ${lockAttendeeViewOnStage}`, async () => {
|
14621
|
+
await check(
|
14622
|
+
{lockAttendeeViewOnStage},
|
14623
|
+
{
|
14624
|
+
overrideDefault: true,
|
14625
|
+
lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
|
14626
|
+
stageParameters: {
|
14627
|
+
activeSpeakerProportion: 0.5,
|
14628
|
+
showActiveSpeaker: {show: false, order: 0},
|
14629
|
+
stageManagerType: 0,
|
14630
|
+
},
|
14631
|
+
}
|
14632
|
+
);
|
14633
|
+
});
|
14634
|
+
});
|
14635
|
+
|
14636
|
+
[false, true].forEach((showActiveSpeaker) => {
|
14637
|
+
it(`sends the expected request when only the show active speaker option is provided as ${showActiveSpeaker}`, async () => {
|
14638
|
+
await check(
|
14639
|
+
{showActiveSpeaker},
|
14640
|
+
{
|
14641
|
+
overrideDefault: true,
|
14642
|
+
lockAttendeeViewOnStageOnly: false,
|
14643
|
+
stageParameters: {
|
14644
|
+
activeSpeakerProportion: 0.5,
|
14645
|
+
showActiveSpeaker: {show: showActiveSpeaker, order: 0},
|
14646
|
+
stageManagerType: 0,
|
14647
|
+
},
|
14648
|
+
}
|
14649
|
+
);
|
14650
|
+
});
|
14651
|
+
});
|
14652
|
+
|
14653
|
+
it('sends the expected request when all options are provided', async () => {
|
14654
|
+
const activeSpeakerProportion = 0.6;
|
14655
|
+
const customBackground = {
|
14656
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14657
|
+
};
|
14658
|
+
const customLogo = {
|
14659
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14660
|
+
position: 'UpperMiddle',
|
14661
|
+
};
|
14662
|
+
const customNameLabel = {
|
14663
|
+
accentColor: '#0A7806',
|
14664
|
+
background: {color: 'rgba(255, 255, 255, 1)'},
|
14665
|
+
border: {color: 'rgba(255, 255, 255, 1)'},
|
14666
|
+
content: {
|
14667
|
+
displayName: {color: 'rgba(0, 0, 0, 0.95)'},
|
14668
|
+
subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
|
14669
|
+
},
|
14670
|
+
decoration: {color: 'rgba(10, 120, 6, 1)'},
|
14671
|
+
fadeOut: {delay: 15},
|
14672
|
+
type: 'Primary',
|
14673
|
+
};
|
14674
|
+
const importantParticipants = [
|
14675
|
+
{mainCsi: 11111111, participantId: uuidv4()},
|
14676
|
+
{mainCsi: 22222222, participantId: uuidv4()},
|
14677
|
+
{mainCsi: 33333333, participantId: uuidv4()},
|
14678
|
+
{mainCsi: 44444444, participantId: uuidv4()},
|
14679
|
+
{mainCsi: 55555555, participantId: uuidv4()},
|
14680
|
+
{mainCsi: 66666666, participantId: uuidv4()},
|
14681
|
+
{mainCsi: 77777777, participantId: uuidv4()},
|
14682
|
+
{mainCsi: 88888888, participantId: uuidv4()},
|
14683
|
+
];
|
14684
|
+
const lockAttendeeViewOnStage = true;
|
14685
|
+
const showActiveSpeaker = true;
|
14686
|
+
|
14687
|
+
await check(
|
14688
|
+
{
|
14689
|
+
activeSpeakerProportion,
|
14690
|
+
customBackground,
|
14691
|
+
customLogo,
|
14692
|
+
customNameLabel,
|
14693
|
+
importantParticipants,
|
14694
|
+
lockAttendeeViewOnStage,
|
14695
|
+
showActiveSpeaker,
|
14696
|
+
},
|
14697
|
+
{
|
14698
|
+
overrideDefault: true,
|
14699
|
+
lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
|
14700
|
+
stageParameters: {
|
14701
|
+
activeSpeakerProportion,
|
14702
|
+
importantParticipants: [
|
14703
|
+
{...importantParticipants[0], order: 1},
|
14704
|
+
{...importantParticipants[1], order: 2},
|
14705
|
+
{...importantParticipants[2], order: 3},
|
14706
|
+
{...importantParticipants[3], order: 4},
|
14707
|
+
{...importantParticipants[4], order: 5},
|
14708
|
+
{...importantParticipants[5], order: 6},
|
14709
|
+
{...importantParticipants[6], order: 7},
|
14710
|
+
{...importantParticipants[7], order: 8},
|
14711
|
+
],
|
14712
|
+
showActiveSpeaker: {show: showActiveSpeaker, order: 0},
|
14713
|
+
stageManagerType: 7,
|
14714
|
+
},
|
14715
|
+
customLayouts: {background: customBackground, logo: customLogo},
|
14716
|
+
nameLabelStyle: customNameLabel,
|
14717
|
+
}
|
14718
|
+
);
|
14719
|
+
});
|
14720
|
+
});
|
14721
|
+
|
14722
|
+
describe('#unsetStage', () => {
|
14723
|
+
beforeEach(() => {
|
14724
|
+
meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
|
14725
|
+
});
|
14726
|
+
|
14727
|
+
it('sends the expected request', async () => {
|
14728
|
+
const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
|
14729
|
+
meeting.locusUrl = locusUrl;
|
14730
|
+
|
14731
|
+
const unsetStagePromise = meeting.unsetStage();
|
14732
|
+
|
14733
|
+
assert.exists(unsetStagePromise.then);
|
14734
|
+
await unsetStagePromise;
|
14735
|
+
|
14736
|
+
assert.calledOnceWithExactly(
|
14737
|
+
meeting.meetingRequest.synchronizeStage,
|
14738
|
+
locusUrl,
|
14739
|
+
{overrideDefault: false}
|
14740
|
+
);
|
14741
|
+
});
|
14742
|
+
});
|
14094
14743
|
});
|