@webex/plugin-meetings 3.8.1-next.3 → 3.8.1-next.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +26 -13
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/constants.js +21 -2
  5. package/dist/constants.js.map +1 -1
  6. package/dist/interpretation/index.js +1 -1
  7. package/dist/interpretation/siLanguage.js +1 -1
  8. package/dist/locus-info/index.js +36 -17
  9. package/dist/locus-info/index.js.map +1 -1
  10. package/dist/media/index.js +2 -2
  11. package/dist/media/index.js.map +1 -1
  12. package/dist/meeting/brbState.js +14 -12
  13. package/dist/meeting/brbState.js.map +1 -1
  14. package/dist/meeting/index.js +169 -66
  15. package/dist/meeting/index.js.map +1 -1
  16. package/dist/meeting/request.js +19 -0
  17. package/dist/meeting/request.js.map +1 -1
  18. package/dist/meeting/request.type.js.map +1 -1
  19. package/dist/meetings/index.js +35 -33
  20. package/dist/meetings/index.js.map +1 -1
  21. package/dist/members/index.js +8 -6
  22. package/dist/members/index.js.map +1 -1
  23. package/dist/members/request.js +3 -3
  24. package/dist/members/request.js.map +1 -1
  25. package/dist/members/util.js +18 -6
  26. package/dist/members/util.js.map +1 -1
  27. package/dist/multistream/mediaRequestManager.js +1 -1
  28. package/dist/multistream/mediaRequestManager.js.map +1 -1
  29. package/dist/multistream/remoteMedia.js +34 -5
  30. package/dist/multistream/remoteMedia.js.map +1 -1
  31. package/dist/multistream/remoteMediaGroup.js +42 -2
  32. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  33. package/dist/multistream/sendSlotManager.js +32 -2
  34. package/dist/multistream/sendSlotManager.js.map +1 -1
  35. package/dist/reachability/index.js +5 -10
  36. package/dist/reachability/index.js.map +1 -1
  37. package/dist/types/constants.d.ts +19 -0
  38. package/dist/types/meeting/brbState.d.ts +0 -1
  39. package/dist/types/meeting/index.d.ts +28 -4
  40. package/dist/types/meeting/request.d.ts +9 -1
  41. package/dist/types/meeting/request.type.d.ts +74 -0
  42. package/dist/types/members/index.d.ts +8 -3
  43. package/dist/types/members/request.d.ts +1 -1
  44. package/dist/types/members/util.d.ts +5 -2
  45. package/dist/types/multistream/remoteMedia.d.ts +20 -1
  46. package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
  47. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  48. package/dist/types/reachability/index.d.ts +2 -2
  49. package/dist/webinar/index.js +1 -1
  50. package/package.json +24 -24
  51. package/src/constants.ts +20 -0
  52. package/src/locus-info/index.ts +47 -20
  53. package/src/media/index.ts +2 -2
  54. package/src/meeting/brbState.ts +9 -7
  55. package/src/meeting/index.ts +126 -23
  56. package/src/meeting/request.ts +16 -0
  57. package/src/meeting/request.type.ts +64 -0
  58. package/src/meetings/index.ts +3 -2
  59. package/src/members/index.ts +7 -5
  60. package/src/members/request.ts +2 -2
  61. package/src/members/util.ts +14 -3
  62. package/src/multistream/mediaRequestManager.ts +7 -7
  63. package/src/multistream/remoteMedia.ts +34 -4
  64. package/src/multistream/remoteMediaGroup.ts +37 -2
  65. package/src/multistream/sendSlotManager.ts +34 -2
  66. package/src/reachability/index.ts +5 -13
  67. package/test/unit/spec/locus-info/index.js +177 -47
  68. package/test/unit/spec/media/index.ts +107 -0
  69. package/test/unit/spec/meeting/brbState.ts +9 -9
  70. package/test/unit/spec/meeting/index.js +606 -55
  71. package/test/unit/spec/meeting/request.js +71 -0
  72. package/test/unit/spec/meetings/index.js +1 -0
  73. package/test/unit/spec/members/index.js +32 -9
  74. package/test/unit/spec/members/request.js +2 -2
  75. package/test/unit/spec/members/utils.js +27 -7
  76. package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
  77. package/test/unit/spec/multistream/remoteMedia.ts +66 -2
  78. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  79. package/test/unit/spec/reachability/index.ts +2 -6
@@ -368,6 +368,35 @@ describe('plugin-meetings', () => {
368
368
  assert.instanceOf(meeting.simultaneousInterpretation, SimultaneousInterpretation);
369
369
  assert.instanceOf(meeting.webinar, Webinar);
370
370
  });
371
+
372
+ it('should call the callback with the meeting that has id already set', () => {
373
+ let meetingIdFromCallback;
374
+ // check that the meeting id is already set correctly at the time when the callback is called
375
+ const meetingCreationCallback = sinon.stub().callsFake((meeting) => {
376
+ meetingIdFromCallback = meeting.id;
377
+ });
378
+
379
+ meeting = new Meeting(
380
+ {
381
+ userId: uuid1,
382
+ resource: uuid2,
383
+ deviceUrl: uuid3,
384
+ locus: {url: url1},
385
+ destination: testDestination,
386
+ destinationType: DESTINATION_TYPE.MEETING_ID,
387
+ correlationId,
388
+ selfId: uuid1,
389
+ },
390
+ {
391
+ parent: webex,
392
+ },
393
+ meetingCreationCallback
394
+ );
395
+ assert.exists(meeting.id);
396
+ assert.calledOnceWithExactly(meetingCreationCallback, meeting);
397
+ assert.equal(meeting.id, meetingIdFromCallback);
398
+ });
399
+
371
400
  it('creates MediaRequestManager instances', () => {
372
401
  assert.instanceOf(meeting.mediaRequestManagers.audio, MediaRequestManager);
373
402
  assert.instanceOf(meeting.mediaRequestManagers.video, MediaRequestManager);
@@ -614,20 +643,20 @@ describe('plugin-meetings', () => {
614
643
  assert.calledWith(meeting.members.cancelPhoneInvite, uuid1);
615
644
  });
616
645
  });
617
- describe('#cancelSIPInvite', () => {
618
- it('should have #cancelSIPInvite', () => {
619
- assert.exists(meeting.cancelSIPInvite);
646
+ describe('#cancelInviteByMemberId', () => {
647
+ it('should have #cancelInviteByMemberId', () => {
648
+ assert.exists(meeting.cancelInviteByMemberId);
620
649
  });
621
650
  beforeEach(() => {
622
- meeting.members.cancelSIPInvite = sinon.stub().returns(Promise.resolve(test1));
651
+ meeting.members.cancelInviteByMemberId = sinon.stub().returns(Promise.resolve(test1));
623
652
  });
624
- it('should proxy members #cancelSIPInvite and return a promise', async () => {
625
- const cancel = meeting.cancelSIPInvite({memberId: uuid1});
653
+ it('should proxy members #cancelInviteByMemberId and return a promise', async () => {
654
+ const cancel = meeting.cancelInviteByMemberId({memberId: uuid1});
626
655
 
627
656
  assert.exists(cancel.then);
628
657
  await cancel;
629
- assert.calledOnce(meeting.members.cancelSIPInvite);
630
- assert.calledWith(meeting.members.cancelSIPInvite, {memberId: uuid1});
658
+ assert.calledOnce(meeting.members.cancelInviteByMemberId);
659
+ assert.calledWith(meeting.members.cancelInviteByMemberId, {memberId: uuid1});
631
660
  });
632
661
  });
633
662
  describe('#admit', () => {
@@ -1208,8 +1237,73 @@ describe('plugin-meetings', () => {
1208
1237
  reason: 'joinWithMedia failure',
1209
1238
  });
1210
1239
  });
1211
- });
1212
1240
 
1241
+ it('should ignore sendVideo/receiveVideo when videoEnabled is false', async () => {
1242
+ await meeting.joinWithMedia({
1243
+ joinOptions,
1244
+ mediaOptions: {
1245
+ videoEnabled: false,
1246
+ sendVideo: true,
1247
+ receiveVideo: true,
1248
+ allowMediaInLobby: true,
1249
+ },
1250
+ });
1251
+
1252
+ assert.calledWithMatch(
1253
+ meeting.addMediaInternal,
1254
+ sinon.match.any,
1255
+ sinon.match.any,
1256
+ sinon.match.any,
1257
+ sinon.match.has('videoEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
1258
+ );
1259
+ });
1260
+
1261
+ it('should ignore sendAudio/receiveAudio when audioEnabled is false', async () => {
1262
+ await meeting.joinWithMedia({
1263
+ joinOptions,
1264
+ mediaOptions: {
1265
+ audioEnabled: false,
1266
+ sendAudio: true,
1267
+ receiveAudio: false,
1268
+ allowMediaInLobby: true,
1269
+ },
1270
+ });
1271
+
1272
+ assert.calledWithMatch(
1273
+ meeting.addMediaInternal,
1274
+ sinon.match.any,
1275
+ sinon.match.any,
1276
+ sinon.match.any,
1277
+ sinon.match.has('audioEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
1278
+ );
1279
+ });
1280
+
1281
+ it('should use provided send/receive values when videoEnabled/audioEnabled are true or not set', async () => {
1282
+ await meeting.joinWithMedia({
1283
+ joinOptions,
1284
+ mediaOptions: {
1285
+ sendVideo: true,
1286
+ receiveVideo: false,
1287
+ sendAudio: false,
1288
+ receiveAudio: true,
1289
+ allowMediaInLobby: true,
1290
+ },
1291
+ });
1292
+
1293
+ assert.calledWith(
1294
+ meeting.addMediaInternal,
1295
+ sinon.match.any,
1296
+ sinon.match.any,
1297
+ sinon.match.any,
1298
+ sinon.match({
1299
+ sendVideo: true,
1300
+ receiveVideo: false,
1301
+ sendAudio: false,
1302
+ receiveAudio: true,
1303
+ })
1304
+ );
1305
+ });
1306
+ });
1213
1307
  describe('#isTranscriptionSupported', () => {
1214
1308
  it('should return false if the feature is not supported for the meeting', () => {
1215
1309
  meeting.locusInfo.controls = {transcribe: {caption: false}};
@@ -1233,14 +1327,13 @@ describe('plugin-meetings', () => {
1233
1327
  sinon.restore();
1234
1328
  });
1235
1329
  it('should call voicea.onSpokenLanguageUpdate when joined', async () => {
1236
-
1237
1330
  meeting.joinedWith = {state: 'JOINED'};
1238
1331
  await meeting.locusInfo.emitScoped(
1239
1332
  {function: 'test', file: 'test'},
1240
1333
  LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
1241
- {spokenLanguage: 'fr'},
1334
+ {spokenLanguage: 'fr'}
1242
1335
  );
1243
- assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr');
1336
+ assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr', meeting.id);
1244
1337
  assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'fr');
1245
1338
  assert.calledWith(
1246
1339
  TriggerProxy.trigger,
@@ -1251,12 +1344,11 @@ describe('plugin-meetings', () => {
1251
1344
  });
1252
1345
 
1253
1346
  it('should also call voicea.onSpokenLanguageUpdate when not joined', async () => {
1254
-
1255
1347
  meeting.joinedWith = {state: 'NOT_JOINED'};
1256
1348
  await meeting.locusInfo.emitScoped(
1257
1349
  {function: 'test', file: 'test'},
1258
1350
  LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
1259
- {spokenLanguage: 'de'},
1351
+ {spokenLanguage: 'de'}
1260
1352
  );
1261
1353
  assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'de');
1262
1354
  assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'de');
@@ -2101,14 +2193,12 @@ describe('plugin-meetings', () => {
2101
2193
  };
2102
2194
  meeting.mediaProperties.setMediaDirection = sinon.stub().returns(true);
2103
2195
  meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
2104
- meeting.mediaProperties.getCurrentConnectionInfo = sinon
2105
- .stub()
2106
- .resolves({
2107
- connectionType: 'udp',
2108
- selectedCandidatePairChanges: 2,
2109
- numTransports: 1,
2110
- ipVersion: 'IPv6',
2111
- });
2196
+ meeting.mediaProperties.getCurrentConnectionInfo = sinon.stub().resolves({
2197
+ connectionType: 'udp',
2198
+ selectedCandidatePairChanges: 2,
2199
+ numTransports: 1,
2200
+ ipVersion: 'IPv6',
2201
+ });
2112
2202
  meeting.audio = muteStateStub;
2113
2203
  meeting.video = muteStateStub;
2114
2204
  sinon.stub(Media, 'createMediaConnection').returns(fakeMediaConnection);
@@ -2227,8 +2317,9 @@ describe('plugin-meetings', () => {
2227
2317
  someReachabilityMetric1: 'some value1',
2228
2318
  someReachabilityMetric2: 'some value2',
2229
2319
  selectedCandidatePairChanges: 2,
2230
- isSubnetReachable: null,
2231
- selectedCluster: null,
2320
+ subnet_reachable: null,
2321
+ selected_cluster: null,
2322
+ selected_subnet: null,
2232
2323
  numTransports: 1,
2233
2324
  iceCandidatesCount: 0,
2234
2325
  }
@@ -2275,8 +2366,9 @@ describe('plugin-meetings', () => {
2275
2366
  signalingState: 'unknown',
2276
2367
  connectionState: 'unknown',
2277
2368
  iceConnectionState: 'unknown',
2278
- isSubnetReachable: null,
2279
- selectedCluster: null,
2369
+ subnet_reachable: null,
2370
+ selected_cluster: null,
2371
+ selected_subnet: null,
2280
2372
  })
2281
2373
  );
2282
2374
 
@@ -2342,8 +2434,9 @@ describe('plugin-meetings', () => {
2342
2434
  selectedCandidatePairChanges: 2,
2343
2435
  numTransports: 1,
2344
2436
  iceCandidatesCount: 0,
2345
- isSubnetReachable: null,
2346
- selectedCluster: null,
2437
+ subnet_reachable: null,
2438
+ selected_cluster: null,
2439
+ selected_subnet: null,
2347
2440
  }
2348
2441
  );
2349
2442
  });
@@ -2401,8 +2494,9 @@ describe('plugin-meetings', () => {
2401
2494
  signalingState: 'have-local-offer',
2402
2495
  connectionState: 'connecting',
2403
2496
  iceConnectionState: 'checking',
2404
- isSubnetReachable: null,
2405
- selectedCluster: null,
2497
+ subnet_reachable: null,
2498
+ selected_cluster: null,
2499
+ selected_subnet: null,
2406
2500
  })
2407
2501
  );
2408
2502
 
@@ -2460,8 +2554,9 @@ describe('plugin-meetings', () => {
2460
2554
  signalingState: 'have-local-offer',
2461
2555
  connectionState: 'connecting',
2462
2556
  iceConnectionState: 'checking',
2463
- isSubnetReachable: null,
2464
- selectedCluster: null,
2557
+ subnet_reachable: null,
2558
+ selected_cluster: null,
2559
+ selected_subnet: null,
2465
2560
  })
2466
2561
  );
2467
2562
 
@@ -2983,8 +3078,9 @@ describe('plugin-meetings', () => {
2983
3078
  selectedCandidatePairChanges: 2,
2984
3079
  numTransports: 1,
2985
3080
  iceCandidatesCount: 0,
2986
- isSubnetReachable: null,
2987
- selectedCluster: null,
3081
+ subnet_reachable: null,
3082
+ selected_cluster: null,
3083
+ selected_subnet: null,
2988
3084
  },
2989
3085
  ]);
2990
3086
 
@@ -3191,8 +3287,9 @@ describe('plugin-meetings', () => {
3191
3287
  retriedWithTurnServer: true,
3192
3288
  isJoinWithMediaRetry: false,
3193
3289
  iceCandidatesCount: 0,
3194
- isSubnetReachable: null,
3195
- selectedCluster: null,
3290
+ subnet_reachable: null,
3291
+ selected_cluster: null,
3292
+ selected_subnet: null,
3196
3293
  },
3197
3294
  ]);
3198
3295
  meeting.roap.doTurnDiscovery;
@@ -3326,8 +3423,8 @@ describe('plugin-meetings', () => {
3326
3423
  meeting.mediaConnections = [
3327
3424
  {
3328
3425
  mediaAgentCluster: 'some.cluster',
3329
- }
3330
- ]
3426
+ },
3427
+ ];
3331
3428
  meeting.iceCandidatesCount = 3;
3332
3429
  meeting.iceCandidateErrors.set('701_error', 3);
3333
3430
  meeting.iceCandidateErrors.set('701_turn_host_lookup_received_error', 1);
@@ -3355,8 +3452,9 @@ describe('plugin-meetings', () => {
3355
3452
  iceCandidatesCount: 3,
3356
3453
  '701_error': 3,
3357
3454
  '701_turn_host_lookup_received_error': 1,
3358
- isSubnetReachable: null,
3359
- selectedCluster: 'some.cluster',
3455
+ subnet_reachable: null,
3456
+ selected_cluster: 'some.cluster',
3457
+ selected_subnet: null,
3360
3458
  }
3361
3459
  );
3362
3460
 
@@ -3419,8 +3517,9 @@ describe('plugin-meetings', () => {
3419
3517
  iceConnectionState: 'unknown',
3420
3518
  selectedCandidatePairChanges: 2,
3421
3519
  numTransports: 1,
3422
- isSubnetReachable: null,
3423
- selectedCluster: null,
3520
+ subnet_reachable: null,
3521
+ selected_cluster: null,
3522
+ selected_subnet: null,
3424
3523
  iceCandidatesCount: 0,
3425
3524
  }
3426
3525
  );
@@ -3482,8 +3581,9 @@ describe('plugin-meetings', () => {
3482
3581
  numTransports: 1,
3483
3582
  '701_error': 2,
3484
3583
  '701_turn_host_lookup_received_error': 1,
3485
- isSubnetReachable: null,
3486
- selectedCluster: null,
3584
+ subnet_reachable: null,
3585
+ selected_cluster: null,
3586
+ selected_subnet: null,
3487
3587
  iceCandidatesCount: 0,
3488
3588
  }
3489
3589
  );
@@ -3491,7 +3591,7 @@ describe('plugin-meetings', () => {
3491
3591
  assert.isOk(errorThrown);
3492
3592
  });
3493
3593
 
3494
- it('should send valid isSubnetReachability if media connection success', async () => {
3594
+ it('should send subnet reachablity metrics if media connection success', async () => {
3495
3595
  meeting.roap.doTurnDiscovery = sinon.stub().returns({
3496
3596
  turnServerInfo: undefined,
3497
3597
  turnDiscoverySkippedReason: undefined,
@@ -3505,6 +3605,12 @@ describe('plugin-meetings', () => {
3505
3605
  stopReachability: sinon.stub(),
3506
3606
  isSubnetReachable: sinon.stub().returns(false),
3507
3607
  };
3608
+ meeting.mediaServerIp = '1.2.3.4';
3609
+ meeting.mediaConnections = [
3610
+ {
3611
+ mediaAgentCluster: 'some.cluster',
3612
+ },
3613
+ ];
3508
3614
 
3509
3615
  const forceRtcMetricsSend = sinon.stub().resolves();
3510
3616
  const closeMediaConnectionStub = sinon.stub();
@@ -3532,12 +3638,13 @@ describe('plugin-meetings', () => {
3532
3638
  isJoinWithMediaRetry: false,
3533
3639
  iceCandidatesCount: 0,
3534
3640
  reachability_public_udp_success: 5,
3535
- isSubnetReachable: false,
3536
- selectedCluster: null,
3641
+ subnet_reachable: false,
3642
+ selected_cluster: 'some.cluster',
3643
+ selected_subnet: '1.X.X.X',
3537
3644
  });
3538
3645
  });
3539
3646
 
3540
- it('should send valid isSubnetReachability if media connection fails', async () => {
3647
+ it('should send subnet reachablity metrics if media connection fails', async () => {
3541
3648
  let errorThrown = undefined;
3542
3649
 
3543
3650
  meeting.roap.doTurnDiscovery = sinon.stub().returns({
@@ -3553,6 +3660,12 @@ describe('plugin-meetings', () => {
3553
3660
  stopReachability: sinon.stub(),
3554
3661
  isSubnetReachable: sinon.stub().returns(true),
3555
3662
  };
3663
+ meeting.mediaServerIp = '1.2.3.4';
3664
+ meeting.mediaConnections = [
3665
+ {
3666
+ mediaAgentCluster: 'some.cluster',
3667
+ },
3668
+ ];
3556
3669
 
3557
3670
  const forceRtcMetricsSend = sinon.stub().resolves();
3558
3671
  const closeMediaConnectionStub = sinon.stub();
@@ -3594,8 +3707,9 @@ describe('plugin-meetings', () => {
3594
3707
  selectedCandidatePairChanges: 2,
3595
3708
  numTransports: 1,
3596
3709
  reachability_public_udp_success: 5,
3597
- isSubnetReachable: true,
3598
- selectedCluster: null,
3710
+ subnet_reachable: true,
3711
+ selected_cluster: 'some.cluster',
3712
+ selected_subnet: '1.X.X.X',
3599
3713
  iceCandidatesCount: 0,
3600
3714
  }
3601
3715
  );
@@ -4262,11 +4376,9 @@ describe('plugin-meetings', () => {
4262
4376
 
4263
4377
  const error = new Error();
4264
4378
  meeting.meetingRequest.setBrb = sinon.stub().rejects(error);
4265
-
4266
- await expect(
4267
- meeting.beRightBack(true)
4268
- ).to.be.rejectedWith(error);
4269
-
4379
+
4380
+ await expect(meeting.beRightBack(true)).to.be.rejectedWith(error);
4381
+
4270
4382
  assert.isFalse(meeting.brbState.state.syncToServerInProgress);
4271
4383
  });
4272
4384
  });
@@ -14002,4 +14114,443 @@ describe('plugin-meetings', () => {
14002
14114
  assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
14003
14115
  });
14004
14116
  });
14117
+
14118
+ describe('#setStage', () => {
14119
+ const check = async (options, expectedVideoLayout) => {
14120
+ const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
14121
+ meeting.locusUrl = locusUrl;
14122
+
14123
+ const setStagePromise = meeting.setStage(options);
14124
+
14125
+ assert.exists(setStagePromise.then);
14126
+ await setStagePromise;
14127
+
14128
+ assert.calledOnceWithExactly(
14129
+ meeting.meetingRequest.synchronizeStage,
14130
+ locusUrl,
14131
+ expectedVideoLayout
14132
+ );
14133
+ };
14134
+
14135
+ beforeEach(() => {
14136
+ meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
14137
+ });
14138
+
14139
+ it('sends the expected request when no options are provided', async () => {
14140
+ await check(undefined, {
14141
+ overrideDefault: true,
14142
+ lockAttendeeViewOnStageOnly: false,
14143
+ stageParameters: {
14144
+ activeSpeakerProportion: 0.5,
14145
+ showActiveSpeaker: {show: false, order: 0},
14146
+ stageManagerType: 0,
14147
+ },
14148
+ });
14149
+ });
14150
+
14151
+ it('sends the expected request when empty options are provided', async () => {
14152
+ await check(
14153
+ {},
14154
+ {
14155
+ overrideDefault: true,
14156
+ lockAttendeeViewOnStageOnly: false,
14157
+ stageParameters: {
14158
+ activeSpeakerProportion: 0.5,
14159
+ showActiveSpeaker: {show: false, order: 0},
14160
+ stageManagerType: 0,
14161
+ },
14162
+ }
14163
+ );
14164
+ });
14165
+
14166
+ [0.25, 0.5, 0.75].forEach((activeSpeakerProportion) => {
14167
+ it(`sends the expected request when only the active speaker proportion option is provided as ${activeSpeakerProportion}`, async () => {
14168
+ await check(
14169
+ {activeSpeakerProportion},
14170
+ {
14171
+ overrideDefault: true,
14172
+ lockAttendeeViewOnStageOnly: false,
14173
+ stageParameters: {
14174
+ activeSpeakerProportion,
14175
+ showActiveSpeaker: {show: false, order: 0},
14176
+ stageManagerType: 0,
14177
+ },
14178
+ }
14179
+ );
14180
+ });
14181
+ });
14182
+
14183
+ it('sends the expected request when only the custom background option is provided', async () => {
14184
+ const customBackground = {
14185
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14186
+ };
14187
+
14188
+ await check(
14189
+ {customBackground},
14190
+ {
14191
+ overrideDefault: true,
14192
+ lockAttendeeViewOnStageOnly: false,
14193
+ stageParameters: {
14194
+ activeSpeakerProportion: 0.5,
14195
+ showActiveSpeaker: {show: false, order: 0},
14196
+ stageManagerType: 2,
14197
+ },
14198
+ customLayouts: {background: customBackground},
14199
+ }
14200
+ );
14201
+ });
14202
+
14203
+ it('sends the expected request when only the custom logo option is provided', async () => {
14204
+ const customLogo = {
14205
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14206
+ position: 'LowerRight',
14207
+ };
14208
+
14209
+ await check(
14210
+ {customLogo},
14211
+ {
14212
+ overrideDefault: true,
14213
+ lockAttendeeViewOnStageOnly: false,
14214
+ stageParameters: {
14215
+ activeSpeakerProportion: 0.5,
14216
+ showActiveSpeaker: {show: false, order: 0},
14217
+ stageManagerType: 1,
14218
+ },
14219
+ customLayouts: {logo: customLogo},
14220
+ }
14221
+ );
14222
+ });
14223
+
14224
+ it('sends the expected request when only the custom name label option is provided', async () => {
14225
+ const customNameLabel = {
14226
+ accentColor: '#0A7806',
14227
+ background: {color: 'rgba(255, 255, 255, 1)'},
14228
+ border: {color: 'rgba(255, 255, 255, 1)'},
14229
+ content: {
14230
+ displayName: {color: 'rgba(0, 0, 0, 0.95)'},
14231
+ subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
14232
+ },
14233
+ decoration: {color: 'rgba(10, 120, 6, 1)'},
14234
+ fadeOut: {delay: 15},
14235
+ type: 'Primary',
14236
+ };
14237
+
14238
+ await check(
14239
+ {customNameLabel},
14240
+ {
14241
+ overrideDefault: true,
14242
+ lockAttendeeViewOnStageOnly: false,
14243
+ stageParameters: {
14244
+ activeSpeakerProportion: 0.5,
14245
+ showActiveSpeaker: {show: false, order: 0},
14246
+ stageManagerType: 4,
14247
+ },
14248
+ nameLabelStyle: customNameLabel,
14249
+ }
14250
+ );
14251
+ });
14252
+
14253
+ it('sends the expected request when only the custom background and logo options are provided', async () => {
14254
+ const customBackground = {
14255
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14256
+ };
14257
+ const customLogo = {
14258
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14259
+ position: 'UpperRight',
14260
+ };
14261
+
14262
+ await check(
14263
+ {customBackground, customLogo},
14264
+ {
14265
+ overrideDefault: true,
14266
+ lockAttendeeViewOnStageOnly: false,
14267
+ stageParameters: {
14268
+ activeSpeakerProportion: 0.5,
14269
+ showActiveSpeaker: {show: false, order: 0},
14270
+ stageManagerType: 3,
14271
+ },
14272
+ customLayouts: {background: customBackground, logo: customLogo},
14273
+ }
14274
+ );
14275
+ });
14276
+
14277
+ it('sends the expected request when only the custom background and name label options are provided', async () => {
14278
+ const customBackground = {
14279
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14280
+ };
14281
+ const customNameLabel = {
14282
+ accentColor: '#00A3FF',
14283
+ background: {color: 'rgba(0, 163, 255, 1)'},
14284
+ border: {color: 'rgba(0, 163, 255, 1)'},
14285
+ content: {
14286
+ displayName: {color: 'rgba(255, 255, 255, 0.95)'},
14287
+ subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
14288
+ },
14289
+ decoration: {color: 'rgba(255, 255, 255, 0.95)'},
14290
+ fadeOut: {delay: 15},
14291
+ type: 'PrimaryInverted',
14292
+ };
14293
+
14294
+ await check(
14295
+ {customBackground, customNameLabel},
14296
+ {
14297
+ overrideDefault: true,
14298
+ lockAttendeeViewOnStageOnly: false,
14299
+ stageParameters: {
14300
+ activeSpeakerProportion: 0.5,
14301
+ showActiveSpeaker: {show: false, order: 0},
14302
+ stageManagerType: 6,
14303
+ },
14304
+ customLayouts: {background: customBackground},
14305
+ nameLabelStyle: customNameLabel,
14306
+ }
14307
+ );
14308
+ });
14309
+
14310
+ it('sends the expected request when only the custom logo and name label options are provided', async () => {
14311
+ const customLogo = {
14312
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14313
+ position: 'UpperLeft',
14314
+ };
14315
+ const customNameLabel = {
14316
+ accentColor: '#942B2B',
14317
+ background: {color: 'rgba(255, 255, 255, 1)'},
14318
+ border: {color: 'rgba(148, 43, 43, 1)'},
14319
+ content: {
14320
+ displayName: {color: 'rgba(0, 0, 0, 0.95)'},
14321
+ subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
14322
+ },
14323
+ decoration: {color: 'rgba(0, 0, 0, 0)'},
14324
+ fadeOut: {delay: 15},
14325
+ type: 'Secondary',
14326
+ };
14327
+
14328
+ await check(
14329
+ {customLogo, customNameLabel},
14330
+ {
14331
+ overrideDefault: true,
14332
+ lockAttendeeViewOnStageOnly: false,
14333
+ stageParameters: {
14334
+ activeSpeakerProportion: 0.5,
14335
+ showActiveSpeaker: {show: false, order: 0},
14336
+ stageManagerType: 5,
14337
+ },
14338
+ customLayouts: {logo: customLogo},
14339
+ nameLabelStyle: customNameLabel,
14340
+ }
14341
+ );
14342
+ });
14343
+
14344
+ it('sends the expected request when only the custom background, logo, name label options are provided', async () => {
14345
+ const customBackground = {
14346
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14347
+ };
14348
+ const customLogo = {
14349
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14350
+ position: 'LowerLeft',
14351
+ };
14352
+ const customNameLabel = {
14353
+ accentColor: '#EBD960',
14354
+ background: {color: 'rgba(235, 217, 96, 0.55)'},
14355
+ border: {color: 'rgba(235, 217, 96, 0.55)'},
14356
+ content: {
14357
+ displayName: {color: 'rgba(255, 255, 255, 0.95)'},
14358
+ subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
14359
+ },
14360
+ decoration: {color: 'rgba(0, 0, 0, 0)'},
14361
+ fadeOut: {delay: 15},
14362
+ type: 'SecondaryInverted',
14363
+ };
14364
+
14365
+ await check(
14366
+ {customBackground, customLogo, customNameLabel},
14367
+ {
14368
+ overrideDefault: true,
14369
+ lockAttendeeViewOnStageOnly: false,
14370
+ stageParameters: {
14371
+ activeSpeakerProportion: 0.5,
14372
+ showActiveSpeaker: {show: false, order: 0},
14373
+ stageManagerType: 7,
14374
+ },
14375
+ customLayouts: {background: customBackground, logo: customLogo},
14376
+ nameLabelStyle: customNameLabel,
14377
+ }
14378
+ );
14379
+ });
14380
+
14381
+ it('sends the expected request when only the important participants option is provided as empty', async () => {
14382
+ await check(
14383
+ {importantParticipants: []},
14384
+ {
14385
+ overrideDefault: true,
14386
+ lockAttendeeViewOnStageOnly: false,
14387
+ stageParameters: {
14388
+ activeSpeakerProportion: 0.5,
14389
+ showActiveSpeaker: {show: false, order: 0},
14390
+ stageManagerType: 0,
14391
+ },
14392
+ }
14393
+ );
14394
+ });
14395
+
14396
+ it('sends the expected request when only the important participants option is provided as populated', async () => {
14397
+ const importantParticipants = [
14398
+ {mainCsi: 11111111, participantId: uuidv4()},
14399
+ {mainCsi: 22222222, participantId: uuidv4()},
14400
+ {mainCsi: 33333333, participantId: uuidv4()},
14401
+ {mainCsi: 44444444, participantId: uuidv4()},
14402
+ {mainCsi: 55555555, participantId: uuidv4()},
14403
+ {mainCsi: 66666666, participantId: uuidv4()},
14404
+ {mainCsi: 77777777, participantId: uuidv4()},
14405
+ {mainCsi: 88888888, participantId: uuidv4()},
14406
+ ];
14407
+
14408
+ await check(
14409
+ {importantParticipants},
14410
+ {
14411
+ overrideDefault: true,
14412
+ lockAttendeeViewOnStageOnly: false,
14413
+ stageParameters: {
14414
+ activeSpeakerProportion: 0.5,
14415
+ importantParticipants: [
14416
+ {...importantParticipants[0], order: 1},
14417
+ {...importantParticipants[1], order: 2},
14418
+ {...importantParticipants[2], order: 3},
14419
+ {...importantParticipants[3], order: 4},
14420
+ {...importantParticipants[4], order: 5},
14421
+ {...importantParticipants[5], order: 6},
14422
+ {...importantParticipants[6], order: 7},
14423
+ {...importantParticipants[7], order: 8},
14424
+ ],
14425
+ showActiveSpeaker: {show: false, order: 0},
14426
+ stageManagerType: 0,
14427
+ },
14428
+ }
14429
+ );
14430
+ });
14431
+
14432
+ [false, true].forEach((lockAttendeeViewOnStage) => {
14433
+ it(`sends the expected request when only the lock attendee view on stage option is provided as ${lockAttendeeViewOnStage}`, async () => {
14434
+ await check(
14435
+ {lockAttendeeViewOnStage},
14436
+ {
14437
+ overrideDefault: true,
14438
+ lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
14439
+ stageParameters: {
14440
+ activeSpeakerProportion: 0.5,
14441
+ showActiveSpeaker: {show: false, order: 0},
14442
+ stageManagerType: 0,
14443
+ },
14444
+ }
14445
+ );
14446
+ });
14447
+ });
14448
+
14449
+ [false, true].forEach((showActiveSpeaker) => {
14450
+ it(`sends the expected request when only the show active speaker option is provided as ${showActiveSpeaker}`, async () => {
14451
+ await check(
14452
+ {showActiveSpeaker},
14453
+ {
14454
+ overrideDefault: true,
14455
+ lockAttendeeViewOnStageOnly: false,
14456
+ stageParameters: {
14457
+ activeSpeakerProportion: 0.5,
14458
+ showActiveSpeaker: {show: showActiveSpeaker, order: 0},
14459
+ stageManagerType: 0,
14460
+ },
14461
+ }
14462
+ );
14463
+ });
14464
+ });
14465
+
14466
+ it('sends the expected request when all options are provided', async () => {
14467
+ const activeSpeakerProportion = 0.6;
14468
+ const customBackground = {
14469
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14470
+ };
14471
+ const customLogo = {
14472
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14473
+ position: 'UpperMiddle',
14474
+ };
14475
+ const customNameLabel = {
14476
+ accentColor: '#0A7806',
14477
+ background: {color: 'rgba(255, 255, 255, 1)'},
14478
+ border: {color: 'rgba(255, 255, 255, 1)'},
14479
+ content: {
14480
+ displayName: {color: 'rgba(0, 0, 0, 0.95)'},
14481
+ subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
14482
+ },
14483
+ decoration: {color: 'rgba(10, 120, 6, 1)'},
14484
+ fadeOut: {delay: 15},
14485
+ type: 'Primary',
14486
+ };
14487
+ const importantParticipants = [
14488
+ {mainCsi: 11111111, participantId: uuidv4()},
14489
+ {mainCsi: 22222222, participantId: uuidv4()},
14490
+ {mainCsi: 33333333, participantId: uuidv4()},
14491
+ {mainCsi: 44444444, participantId: uuidv4()},
14492
+ {mainCsi: 55555555, participantId: uuidv4()},
14493
+ {mainCsi: 66666666, participantId: uuidv4()},
14494
+ {mainCsi: 77777777, participantId: uuidv4()},
14495
+ {mainCsi: 88888888, participantId: uuidv4()},
14496
+ ];
14497
+ const lockAttendeeViewOnStage = true;
14498
+ const showActiveSpeaker = true;
14499
+
14500
+ await check(
14501
+ {
14502
+ activeSpeakerProportion,
14503
+ customBackground,
14504
+ customLogo,
14505
+ customNameLabel,
14506
+ importantParticipants,
14507
+ lockAttendeeViewOnStage,
14508
+ showActiveSpeaker,
14509
+ },
14510
+ {
14511
+ overrideDefault: true,
14512
+ lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
14513
+ stageParameters: {
14514
+ activeSpeakerProportion,
14515
+ importantParticipants: [
14516
+ {...importantParticipants[0], order: 1},
14517
+ {...importantParticipants[1], order: 2},
14518
+ {...importantParticipants[2], order: 3},
14519
+ {...importantParticipants[3], order: 4},
14520
+ {...importantParticipants[4], order: 5},
14521
+ {...importantParticipants[5], order: 6},
14522
+ {...importantParticipants[6], order: 7},
14523
+ {...importantParticipants[7], order: 8},
14524
+ ],
14525
+ showActiveSpeaker: {show: showActiveSpeaker, order: 0},
14526
+ stageManagerType: 7,
14527
+ },
14528
+ customLayouts: {background: customBackground, logo: customLogo},
14529
+ nameLabelStyle: customNameLabel,
14530
+ }
14531
+ );
14532
+ });
14533
+ });
14534
+
14535
+ describe('#unsetStage', () => {
14536
+ beforeEach(() => {
14537
+ meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
14538
+ });
14539
+
14540
+ it('sends the expected request', async () => {
14541
+ const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
14542
+ meeting.locusUrl = locusUrl;
14543
+
14544
+ const unsetStagePromise = meeting.unsetStage();
14545
+
14546
+ assert.exists(unsetStagePromise.then);
14547
+ await unsetStagePromise;
14548
+
14549
+ assert.calledOnceWithExactly(
14550
+ meeting.meetingRequest.synchronizeStage,
14551
+ locusUrl,
14552
+ {overrideDefault: false}
14553
+ );
14554
+ });
14555
+ });
14005
14556
  });