@webex/plugin-meetings 3.8.1-web-workers-keepalive.1 → 3.9.0-webinar5k.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.
Files changed (87) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +8 -2
  4. package/dist/constants.js.map +1 -1
  5. package/dist/hashTree/constants.js +23 -0
  6. package/dist/hashTree/constants.js.map +1 -0
  7. package/dist/hashTree/hashTree.js +516 -0
  8. package/dist/hashTree/hashTree.js.map +1 -0
  9. package/dist/hashTree/hashTreeParser.js +521 -0
  10. package/dist/hashTree/hashTreeParser.js.map +1 -0
  11. package/dist/interpretation/index.js +1 -1
  12. package/dist/interpretation/siLanguage.js +1 -1
  13. package/dist/locus-info/index.js +301 -59
  14. package/dist/locus-info/index.js.map +1 -1
  15. package/dist/meeting/brbState.js +14 -12
  16. package/dist/meeting/brbState.js.map +1 -1
  17. package/dist/meeting/index.js +110 -12
  18. package/dist/meeting/index.js.map +1 -1
  19. package/dist/meeting/muteState.js +2 -5
  20. package/dist/meeting/muteState.js.map +1 -1
  21. package/dist/meeting/request.js +19 -0
  22. package/dist/meeting/request.js.map +1 -1
  23. package/dist/meeting/request.type.js.map +1 -1
  24. package/dist/meeting/util.js +8 -11
  25. package/dist/meeting/util.js.map +1 -1
  26. package/dist/meetings/index.js +6 -2
  27. package/dist/meetings/index.js.map +1 -1
  28. package/dist/member/index.js.map +1 -1
  29. package/dist/member/types.js.map +1 -1
  30. package/dist/members/collection.js +13 -0
  31. package/dist/members/collection.js.map +1 -1
  32. package/dist/members/index.js +44 -23
  33. package/dist/members/index.js.map +1 -1
  34. package/dist/members/request.js +3 -3
  35. package/dist/members/request.js.map +1 -1
  36. package/dist/members/util.js +18 -6
  37. package/dist/members/util.js.map +1 -1
  38. package/dist/multistream/sendSlotManager.js +32 -2
  39. package/dist/multistream/sendSlotManager.js.map +1 -1
  40. package/dist/types/constants.d.ts +6 -0
  41. package/dist/types/hashTree/constants.d.ts +8 -0
  42. package/dist/types/hashTree/hashTree.d.ts +128 -0
  43. package/dist/types/hashTree/hashTreeParser.d.ts +152 -0
  44. package/dist/types/locus-info/index.d.ts +93 -3
  45. package/dist/types/meeting/brbState.d.ts +0 -1
  46. package/dist/types/meeting/index.d.ts +29 -3
  47. package/dist/types/meeting/request.d.ts +9 -1
  48. package/dist/types/meeting/request.type.d.ts +74 -0
  49. package/dist/types/meeting/util.d.ts +3 -3
  50. package/dist/types/member/types.d.ts +1 -0
  51. package/dist/types/members/collection.d.ts +6 -0
  52. package/dist/types/members/index.d.ts +15 -3
  53. package/dist/types/members/request.d.ts +1 -1
  54. package/dist/types/members/util.d.ts +5 -2
  55. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  56. package/dist/webinar/index.js +1 -1
  57. package/package.json +24 -23
  58. package/src/constants.ts +7 -0
  59. package/src/hashTree/constants.ts +12 -0
  60. package/src/hashTree/hashTree.ts +460 -0
  61. package/src/hashTree/hashTreeParser.ts +556 -0
  62. package/src/locus-info/index.ts +393 -58
  63. package/src/meeting/brbState.ts +9 -7
  64. package/src/meeting/index.ts +104 -6
  65. package/src/meeting/muteState.ts +2 -6
  66. package/src/meeting/request.ts +16 -0
  67. package/src/meeting/request.type.ts +64 -0
  68. package/src/meeting/util.ts +17 -20
  69. package/src/meetings/index.ts +17 -3
  70. package/src/member/index.ts +1 -0
  71. package/src/member/types.ts +1 -0
  72. package/src/members/collection.ts +11 -0
  73. package/src/members/index.ts +33 -7
  74. package/src/members/request.ts +2 -2
  75. package/src/members/util.ts +14 -3
  76. package/src/multistream/sendSlotManager.ts +34 -2
  77. package/test/unit/spec/hashTree/hashTree.ts +394 -0
  78. package/test/unit/spec/hashTree/hashTreeParser.ts +156 -0
  79. package/test/unit/spec/locus-info/index.js +506 -55
  80. package/test/unit/spec/meeting/brbState.ts +9 -9
  81. package/test/unit/spec/meeting/index.js +475 -42
  82. package/test/unit/spec/meeting/request.js +71 -0
  83. package/test/unit/spec/members/index.js +33 -10
  84. package/test/unit/spec/members/request.js +2 -2
  85. package/test/unit/spec/members/utils.js +27 -7
  86. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  87. package/test/unit/spec/reachability/index.ts +3 -1
@@ -614,20 +614,20 @@ describe('plugin-meetings', () => {
614
614
  assert.calledWith(meeting.members.cancelPhoneInvite, uuid1);
615
615
  });
616
616
  });
617
- describe('#cancelSIPInvite', () => {
618
- it('should have #cancelSIPInvite', () => {
619
- assert.exists(meeting.cancelSIPInvite);
617
+ describe('#cancelInviteByMemberId', () => {
618
+ it('should have #cancelInviteByMemberId', () => {
619
+ assert.exists(meeting.cancelInviteByMemberId);
620
620
  });
621
621
  beforeEach(() => {
622
- meeting.members.cancelSIPInvite = sinon.stub().returns(Promise.resolve(test1));
622
+ meeting.members.cancelInviteByMemberId = sinon.stub().returns(Promise.resolve(test1));
623
623
  });
624
- it('should proxy members #cancelSIPInvite and return a promise', async () => {
625
- const cancel = meeting.cancelSIPInvite({memberId: uuid1});
624
+ it('should proxy members #cancelInviteByMemberId and return a promise', async () => {
625
+ const cancel = meeting.cancelInviteByMemberId({memberId: uuid1});
626
626
 
627
627
  assert.exists(cancel.then);
628
628
  await cancel;
629
- assert.calledOnce(meeting.members.cancelSIPInvite);
630
- assert.calledWith(meeting.members.cancelSIPInvite, {memberId: uuid1});
629
+ assert.calledOnce(meeting.members.cancelInviteByMemberId);
630
+ assert.calledWith(meeting.members.cancelInviteByMemberId, {memberId: uuid1});
631
631
  });
632
632
  });
633
633
  describe('#admit', () => {
@@ -1219,14 +1219,13 @@ describe('plugin-meetings', () => {
1219
1219
  allowMediaInLobby: true,
1220
1220
  },
1221
1221
  });
1222
-
1222
+
1223
1223
  assert.calledWithMatch(
1224
1224
  meeting.addMediaInternal,
1225
1225
  sinon.match.any,
1226
1226
  sinon.match.any,
1227
1227
  sinon.match.any,
1228
- sinon.match.has('videoEnabled', false)
1229
- .and(sinon.match.has('allowMediaInLobby', true))
1228
+ sinon.match.has('videoEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
1230
1229
  );
1231
1230
  });
1232
1231
 
@@ -1235,23 +1234,21 @@ describe('plugin-meetings', () => {
1235
1234
  joinOptions,
1236
1235
  mediaOptions: {
1237
1236
  audioEnabled: false,
1238
- sendAudio: true,
1239
- receiveAudio: false,
1237
+ sendAudio: true,
1238
+ receiveAudio: false,
1240
1239
  allowMediaInLobby: true,
1241
1240
  },
1242
1241
  });
1243
-
1242
+
1244
1243
  assert.calledWithMatch(
1245
1244
  meeting.addMediaInternal,
1246
1245
  sinon.match.any,
1247
1246
  sinon.match.any,
1248
1247
  sinon.match.any,
1249
- sinon.match.has('audioEnabled', false)
1250
- .and(sinon.match.has('allowMediaInLobby', true))
1248
+ sinon.match.has('audioEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
1251
1249
  );
1252
- });
1250
+ });
1253
1251
 
1254
-
1255
1252
  it('should use provided send/receive values when videoEnabled/audioEnabled are true or not set', async () => {
1256
1253
  await meeting.joinWithMedia({
1257
1254
  joinOptions,
@@ -1263,7 +1260,7 @@ describe('plugin-meetings', () => {
1263
1260
  allowMediaInLobby: true,
1264
1261
  },
1265
1262
  });
1266
-
1263
+
1267
1264
  assert.calledWith(
1268
1265
  meeting.addMediaInternal,
1269
1266
  sinon.match.any,
@@ -1301,12 +1298,11 @@ describe('plugin-meetings', () => {
1301
1298
  sinon.restore();
1302
1299
  });
1303
1300
  it('should call voicea.onSpokenLanguageUpdate when joined', async () => {
1304
-
1305
1301
  meeting.joinedWith = {state: 'JOINED'};
1306
1302
  await meeting.locusInfo.emitScoped(
1307
1303
  {function: 'test', file: 'test'},
1308
1304
  LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
1309
- {spokenLanguage: 'fr'},
1305
+ {spokenLanguage: 'fr'}
1310
1306
  );
1311
1307
  assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr', meeting.id);
1312
1308
  assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'fr');
@@ -1319,12 +1315,11 @@ describe('plugin-meetings', () => {
1319
1315
  });
1320
1316
 
1321
1317
  it('should also call voicea.onSpokenLanguageUpdate when not joined', async () => {
1322
-
1323
1318
  meeting.joinedWith = {state: 'NOT_JOINED'};
1324
1319
  await meeting.locusInfo.emitScoped(
1325
1320
  {function: 'test', file: 'test'},
1326
1321
  LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
1327
- {spokenLanguage: 'de'},
1322
+ {spokenLanguage: 'de'}
1328
1323
  );
1329
1324
  assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'de');
1330
1325
  assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'de');
@@ -2169,14 +2164,12 @@ describe('plugin-meetings', () => {
2169
2164
  };
2170
2165
  meeting.mediaProperties.setMediaDirection = sinon.stub().returns(true);
2171
2166
  meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
2172
- meeting.mediaProperties.getCurrentConnectionInfo = sinon
2173
- .stub()
2174
- .resolves({
2175
- connectionType: 'udp',
2176
- selectedCandidatePairChanges: 2,
2177
- numTransports: 1,
2178
- ipVersion: 'IPv6',
2179
- });
2167
+ meeting.mediaProperties.getCurrentConnectionInfo = sinon.stub().resolves({
2168
+ connectionType: 'udp',
2169
+ selectedCandidatePairChanges: 2,
2170
+ numTransports: 1,
2171
+ ipVersion: 'IPv6',
2172
+ });
2180
2173
  meeting.audio = muteStateStub;
2181
2174
  meeting.video = muteStateStub;
2182
2175
  sinon.stub(Media, 'createMediaConnection').returns(fakeMediaConnection);
@@ -3401,8 +3394,8 @@ describe('plugin-meetings', () => {
3401
3394
  meeting.mediaConnections = [
3402
3395
  {
3403
3396
  mediaAgentCluster: 'some.cluster',
3404
- }
3405
- ]
3397
+ },
3398
+ ];
3406
3399
  meeting.iceCandidatesCount = 3;
3407
3400
  meeting.iceCandidateErrors.set('701_error', 3);
3408
3401
  meeting.iceCandidateErrors.set('701_turn_host_lookup_received_error', 1);
@@ -3583,12 +3576,12 @@ describe('plugin-meetings', () => {
3583
3576
  stopReachability: sinon.stub(),
3584
3577
  isSubnetReachable: sinon.stub().returns(false),
3585
3578
  };
3586
- meeting.mediaServerIp = '1.2.3.4';
3579
+ meeting.mediaServerIp = '1.2.3.4';
3587
3580
  meeting.mediaConnections = [
3588
3581
  {
3589
3582
  mediaAgentCluster: 'some.cluster',
3590
- }
3591
- ]
3583
+ },
3584
+ ];
3592
3585
 
3593
3586
  const forceRtcMetricsSend = sinon.stub().resolves();
3594
3587
  const closeMediaConnectionStub = sinon.stub();
@@ -3638,12 +3631,12 @@ describe('plugin-meetings', () => {
3638
3631
  stopReachability: sinon.stub(),
3639
3632
  isSubnetReachable: sinon.stub().returns(true),
3640
3633
  };
3641
- meeting.mediaServerIp = '1.2.3.4';
3634
+ meeting.mediaServerIp = '1.2.3.4';
3642
3635
  meeting.mediaConnections = [
3643
3636
  {
3644
3637
  mediaAgentCluster: 'some.cluster',
3645
- }
3646
- ]
3638
+ },
3639
+ ];
3647
3640
 
3648
3641
  const forceRtcMetricsSend = sinon.stub().resolves();
3649
3642
  const closeMediaConnectionStub = sinon.stub();
@@ -4355,9 +4348,7 @@ describe('plugin-meetings', () => {
4355
4348
  const error = new Error();
4356
4349
  meeting.meetingRequest.setBrb = sinon.stub().rejects(error);
4357
4350
 
4358
- await expect(
4359
- meeting.beRightBack(true)
4360
- ).to.be.rejectedWith(error);
4351
+ await expect(meeting.beRightBack(true)).to.be.rejectedWith(error);
4361
4352
 
4362
4353
  assert.isFalse(meeting.brbState.state.syncToServerInProgress);
4363
4354
  });
@@ -8016,11 +8007,13 @@ describe('plugin-meetings', () => {
8016
8007
  meeting.isoLocalClientMeetingJoinTime = undefined;
8017
8008
  assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
8018
8009
  });
8010
+
8019
8011
  it('should fallback to system clock ISO string when given an invalid value', () => {
8020
8012
  const currentSystemTime = new Date().toISOString();
8021
8013
  meeting.isoLocalClientMeetingJoinTime = 'invalid-date';
8022
8014
  assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
8023
8015
  });
8016
+
8024
8017
  it('should set the isoLocalClientMeetingJoinTime correctly for a valid date string', () => {
8025
8018
  const validDateString = 'Tue, 01 Apr 2025 13:00:36 GMT';
8026
8019
  const expectedISOString = new Date(validDateString).toISOString();
@@ -9194,6 +9187,7 @@ describe('plugin-meetings', () => {
9194
9187
  meeting.deferSDPAnswer = {
9195
9188
  reject: sinon.stub(),
9196
9189
  };
9190
+
9197
9191
  const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
9198
9192
 
9199
9193
  const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
@@ -14091,4 +14085,443 @@ describe('plugin-meetings', () => {
14091
14085
  assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
14092
14086
  });
14093
14087
  });
14088
+
14089
+ describe('#setStage', () => {
14090
+ const check = async (options, expectedVideoLayout) => {
14091
+ const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
14092
+ meeting.locusUrl = locusUrl;
14093
+
14094
+ const setStagePromise = meeting.setStage(options);
14095
+
14096
+ assert.exists(setStagePromise.then);
14097
+ await setStagePromise;
14098
+
14099
+ assert.calledOnceWithExactly(
14100
+ meeting.meetingRequest.synchronizeStage,
14101
+ locusUrl,
14102
+ expectedVideoLayout
14103
+ );
14104
+ };
14105
+
14106
+ beforeEach(() => {
14107
+ meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
14108
+ });
14109
+
14110
+ it('sends the expected request when no options are provided', async () => {
14111
+ await check(undefined, {
14112
+ overrideDefault: true,
14113
+ lockAttendeeViewOnStageOnly: false,
14114
+ stageParameters: {
14115
+ activeSpeakerProportion: 0.5,
14116
+ showActiveSpeaker: {show: false, order: 0},
14117
+ stageManagerType: 0,
14118
+ },
14119
+ });
14120
+ });
14121
+
14122
+ it('sends the expected request when empty options are provided', async () => {
14123
+ await check(
14124
+ {},
14125
+ {
14126
+ overrideDefault: true,
14127
+ lockAttendeeViewOnStageOnly: false,
14128
+ stageParameters: {
14129
+ activeSpeakerProportion: 0.5,
14130
+ showActiveSpeaker: {show: false, order: 0},
14131
+ stageManagerType: 0,
14132
+ },
14133
+ }
14134
+ );
14135
+ });
14136
+
14137
+ [0.25, 0.5, 0.75].forEach((activeSpeakerProportion) => {
14138
+ it(`sends the expected request when only the active speaker proportion option is provided as ${activeSpeakerProportion}`, async () => {
14139
+ await check(
14140
+ {activeSpeakerProportion},
14141
+ {
14142
+ overrideDefault: true,
14143
+ lockAttendeeViewOnStageOnly: false,
14144
+ stageParameters: {
14145
+ activeSpeakerProportion,
14146
+ showActiveSpeaker: {show: false, order: 0},
14147
+ stageManagerType: 0,
14148
+ },
14149
+ }
14150
+ );
14151
+ });
14152
+ });
14153
+
14154
+ it('sends the expected request when only the custom background option is provided', async () => {
14155
+ const customBackground = {
14156
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14157
+ };
14158
+
14159
+ await check(
14160
+ {customBackground},
14161
+ {
14162
+ overrideDefault: true,
14163
+ lockAttendeeViewOnStageOnly: false,
14164
+ stageParameters: {
14165
+ activeSpeakerProportion: 0.5,
14166
+ showActiveSpeaker: {show: false, order: 0},
14167
+ stageManagerType: 2,
14168
+ },
14169
+ customLayouts: {background: customBackground},
14170
+ }
14171
+ );
14172
+ });
14173
+
14174
+ it('sends the expected request when only the custom logo option is provided', async () => {
14175
+ const customLogo = {
14176
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14177
+ position: 'LowerRight',
14178
+ };
14179
+
14180
+ await check(
14181
+ {customLogo},
14182
+ {
14183
+ overrideDefault: true,
14184
+ lockAttendeeViewOnStageOnly: false,
14185
+ stageParameters: {
14186
+ activeSpeakerProportion: 0.5,
14187
+ showActiveSpeaker: {show: false, order: 0},
14188
+ stageManagerType: 1,
14189
+ },
14190
+ customLayouts: {logo: customLogo},
14191
+ }
14192
+ );
14193
+ });
14194
+
14195
+ it('sends the expected request when only the custom name label option is provided', async () => {
14196
+ const customNameLabel = {
14197
+ accentColor: '#0A7806',
14198
+ background: {color: 'rgba(255, 255, 255, 1)'},
14199
+ border: {color: 'rgba(255, 255, 255, 1)'},
14200
+ content: {
14201
+ displayName: {color: 'rgba(0, 0, 0, 0.95)'},
14202
+ subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
14203
+ },
14204
+ decoration: {color: 'rgba(10, 120, 6, 1)'},
14205
+ fadeOut: {delay: 15},
14206
+ type: 'Primary',
14207
+ };
14208
+
14209
+ await check(
14210
+ {customNameLabel},
14211
+ {
14212
+ overrideDefault: true,
14213
+ lockAttendeeViewOnStageOnly: false,
14214
+ stageParameters: {
14215
+ activeSpeakerProportion: 0.5,
14216
+ showActiveSpeaker: {show: false, order: 0},
14217
+ stageManagerType: 4,
14218
+ },
14219
+ nameLabelStyle: customNameLabel,
14220
+ }
14221
+ );
14222
+ });
14223
+
14224
+ it('sends the expected request when only the custom background and logo options are provided', async () => {
14225
+ const customBackground = {
14226
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14227
+ };
14228
+ const customLogo = {
14229
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14230
+ position: 'UpperRight',
14231
+ };
14232
+
14233
+ await check(
14234
+ {customBackground, customLogo},
14235
+ {
14236
+ overrideDefault: true,
14237
+ lockAttendeeViewOnStageOnly: false,
14238
+ stageParameters: {
14239
+ activeSpeakerProportion: 0.5,
14240
+ showActiveSpeaker: {show: false, order: 0},
14241
+ stageManagerType: 3,
14242
+ },
14243
+ customLayouts: {background: customBackground, logo: customLogo},
14244
+ }
14245
+ );
14246
+ });
14247
+
14248
+ it('sends the expected request when only the custom background and name label options are provided', async () => {
14249
+ const customBackground = {
14250
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14251
+ };
14252
+ const customNameLabel = {
14253
+ accentColor: '#00A3FF',
14254
+ background: {color: 'rgba(0, 163, 255, 1)'},
14255
+ border: {color: 'rgba(0, 163, 255, 1)'},
14256
+ content: {
14257
+ displayName: {color: 'rgba(255, 255, 255, 0.95)'},
14258
+ subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
14259
+ },
14260
+ decoration: {color: 'rgba(255, 255, 255, 0.95)'},
14261
+ fadeOut: {delay: 15},
14262
+ type: 'PrimaryInverted',
14263
+ };
14264
+
14265
+ await check(
14266
+ {customBackground, customNameLabel},
14267
+ {
14268
+ overrideDefault: true,
14269
+ lockAttendeeViewOnStageOnly: false,
14270
+ stageParameters: {
14271
+ activeSpeakerProportion: 0.5,
14272
+ showActiveSpeaker: {show: false, order: 0},
14273
+ stageManagerType: 6,
14274
+ },
14275
+ customLayouts: {background: customBackground},
14276
+ nameLabelStyle: customNameLabel,
14277
+ }
14278
+ );
14279
+ });
14280
+
14281
+ it('sends the expected request when only the custom logo and name label options are provided', async () => {
14282
+ const customLogo = {
14283
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14284
+ position: 'UpperLeft',
14285
+ };
14286
+ const customNameLabel = {
14287
+ accentColor: '#942B2B',
14288
+ background: {color: 'rgba(255, 255, 255, 1)'},
14289
+ border: {color: 'rgba(148, 43, 43, 1)'},
14290
+ content: {
14291
+ displayName: {color: 'rgba(0, 0, 0, 0.95)'},
14292
+ subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
14293
+ },
14294
+ decoration: {color: 'rgba(0, 0, 0, 0)'},
14295
+ fadeOut: {delay: 15},
14296
+ type: 'Secondary',
14297
+ };
14298
+
14299
+ await check(
14300
+ {customLogo, customNameLabel},
14301
+ {
14302
+ overrideDefault: true,
14303
+ lockAttendeeViewOnStageOnly: false,
14304
+ stageParameters: {
14305
+ activeSpeakerProportion: 0.5,
14306
+ showActiveSpeaker: {show: false, order: 0},
14307
+ stageManagerType: 5,
14308
+ },
14309
+ customLayouts: {logo: customLogo},
14310
+ nameLabelStyle: customNameLabel,
14311
+ }
14312
+ );
14313
+ });
14314
+
14315
+ it('sends the expected request when only the custom background, logo, name label options are provided', async () => {
14316
+ const customBackground = {
14317
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14318
+ };
14319
+ const customLogo = {
14320
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14321
+ position: 'LowerLeft',
14322
+ };
14323
+ const customNameLabel = {
14324
+ accentColor: '#EBD960',
14325
+ background: {color: 'rgba(235, 217, 96, 0.55)'},
14326
+ border: {color: 'rgba(235, 217, 96, 0.55)'},
14327
+ content: {
14328
+ displayName: {color: 'rgba(255, 255, 255, 0.95)'},
14329
+ subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
14330
+ },
14331
+ decoration: {color: 'rgba(0, 0, 0, 0)'},
14332
+ fadeOut: {delay: 15},
14333
+ type: 'SecondaryInverted',
14334
+ };
14335
+
14336
+ await check(
14337
+ {customBackground, customLogo, customNameLabel},
14338
+ {
14339
+ overrideDefault: true,
14340
+ lockAttendeeViewOnStageOnly: false,
14341
+ stageParameters: {
14342
+ activeSpeakerProportion: 0.5,
14343
+ showActiveSpeaker: {show: false, order: 0},
14344
+ stageManagerType: 7,
14345
+ },
14346
+ customLayouts: {background: customBackground, logo: customLogo},
14347
+ nameLabelStyle: customNameLabel,
14348
+ }
14349
+ );
14350
+ });
14351
+
14352
+ it('sends the expected request when only the important participants option is provided as empty', async () => {
14353
+ await check(
14354
+ {importantParticipants: []},
14355
+ {
14356
+ overrideDefault: true,
14357
+ lockAttendeeViewOnStageOnly: false,
14358
+ stageParameters: {
14359
+ activeSpeakerProportion: 0.5,
14360
+ showActiveSpeaker: {show: false, order: 0},
14361
+ stageManagerType: 0,
14362
+ },
14363
+ }
14364
+ );
14365
+ });
14366
+
14367
+ it('sends the expected request when only the important participants option is provided as populated', async () => {
14368
+ const importantParticipants = [
14369
+ {mainCsi: 11111111, participantId: uuidv4()},
14370
+ {mainCsi: 22222222, participantId: uuidv4()},
14371
+ {mainCsi: 33333333, participantId: uuidv4()},
14372
+ {mainCsi: 44444444, participantId: uuidv4()},
14373
+ {mainCsi: 55555555, participantId: uuidv4()},
14374
+ {mainCsi: 66666666, participantId: uuidv4()},
14375
+ {mainCsi: 77777777, participantId: uuidv4()},
14376
+ {mainCsi: 88888888, participantId: uuidv4()},
14377
+ ];
14378
+
14379
+ await check(
14380
+ {importantParticipants},
14381
+ {
14382
+ overrideDefault: true,
14383
+ lockAttendeeViewOnStageOnly: false,
14384
+ stageParameters: {
14385
+ activeSpeakerProportion: 0.5,
14386
+ importantParticipants: [
14387
+ {...importantParticipants[0], order: 1},
14388
+ {...importantParticipants[1], order: 2},
14389
+ {...importantParticipants[2], order: 3},
14390
+ {...importantParticipants[3], order: 4},
14391
+ {...importantParticipants[4], order: 5},
14392
+ {...importantParticipants[5], order: 6},
14393
+ {...importantParticipants[6], order: 7},
14394
+ {...importantParticipants[7], order: 8},
14395
+ ],
14396
+ showActiveSpeaker: {show: false, order: 0},
14397
+ stageManagerType: 0,
14398
+ },
14399
+ }
14400
+ );
14401
+ });
14402
+
14403
+ [false, true].forEach((lockAttendeeViewOnStage) => {
14404
+ it(`sends the expected request when only the lock attendee view on stage option is provided as ${lockAttendeeViewOnStage}`, async () => {
14405
+ await check(
14406
+ {lockAttendeeViewOnStage},
14407
+ {
14408
+ overrideDefault: true,
14409
+ lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
14410
+ stageParameters: {
14411
+ activeSpeakerProportion: 0.5,
14412
+ showActiveSpeaker: {show: false, order: 0},
14413
+ stageManagerType: 0,
14414
+ },
14415
+ }
14416
+ );
14417
+ });
14418
+ });
14419
+
14420
+ [false, true].forEach((showActiveSpeaker) => {
14421
+ it(`sends the expected request when only the show active speaker option is provided as ${showActiveSpeaker}`, async () => {
14422
+ await check(
14423
+ {showActiveSpeaker},
14424
+ {
14425
+ overrideDefault: true,
14426
+ lockAttendeeViewOnStageOnly: false,
14427
+ stageParameters: {
14428
+ activeSpeakerProportion: 0.5,
14429
+ showActiveSpeaker: {show: showActiveSpeaker, order: 0},
14430
+ stageManagerType: 0,
14431
+ },
14432
+ }
14433
+ );
14434
+ });
14435
+ });
14436
+
14437
+ it('sends the expected request when all options are provided', async () => {
14438
+ const activeSpeakerProportion = 0.6;
14439
+ const customBackground = {
14440
+ url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
14441
+ };
14442
+ const customLogo = {
14443
+ url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
14444
+ position: 'UpperMiddle',
14445
+ };
14446
+ const customNameLabel = {
14447
+ accentColor: '#0A7806',
14448
+ background: {color: 'rgba(255, 255, 255, 1)'},
14449
+ border: {color: 'rgba(255, 255, 255, 1)'},
14450
+ content: {
14451
+ displayName: {color: 'rgba(0, 0, 0, 0.95)'},
14452
+ subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
14453
+ },
14454
+ decoration: {color: 'rgba(10, 120, 6, 1)'},
14455
+ fadeOut: {delay: 15},
14456
+ type: 'Primary',
14457
+ };
14458
+ const importantParticipants = [
14459
+ {mainCsi: 11111111, participantId: uuidv4()},
14460
+ {mainCsi: 22222222, participantId: uuidv4()},
14461
+ {mainCsi: 33333333, participantId: uuidv4()},
14462
+ {mainCsi: 44444444, participantId: uuidv4()},
14463
+ {mainCsi: 55555555, participantId: uuidv4()},
14464
+ {mainCsi: 66666666, participantId: uuidv4()},
14465
+ {mainCsi: 77777777, participantId: uuidv4()},
14466
+ {mainCsi: 88888888, participantId: uuidv4()},
14467
+ ];
14468
+ const lockAttendeeViewOnStage = true;
14469
+ const showActiveSpeaker = true;
14470
+
14471
+ await check(
14472
+ {
14473
+ activeSpeakerProportion,
14474
+ customBackground,
14475
+ customLogo,
14476
+ customNameLabel,
14477
+ importantParticipants,
14478
+ lockAttendeeViewOnStage,
14479
+ showActiveSpeaker,
14480
+ },
14481
+ {
14482
+ overrideDefault: true,
14483
+ lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
14484
+ stageParameters: {
14485
+ activeSpeakerProportion,
14486
+ importantParticipants: [
14487
+ {...importantParticipants[0], order: 1},
14488
+ {...importantParticipants[1], order: 2},
14489
+ {...importantParticipants[2], order: 3},
14490
+ {...importantParticipants[3], order: 4},
14491
+ {...importantParticipants[4], order: 5},
14492
+ {...importantParticipants[5], order: 6},
14493
+ {...importantParticipants[6], order: 7},
14494
+ {...importantParticipants[7], order: 8},
14495
+ ],
14496
+ showActiveSpeaker: {show: showActiveSpeaker, order: 0},
14497
+ stageManagerType: 7,
14498
+ },
14499
+ customLayouts: {background: customBackground, logo: customLogo},
14500
+ nameLabelStyle: customNameLabel,
14501
+ }
14502
+ );
14503
+ });
14504
+ });
14505
+
14506
+ describe('#unsetStage', () => {
14507
+ beforeEach(() => {
14508
+ meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
14509
+ });
14510
+
14511
+ it('sends the expected request', async () => {
14512
+ const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
14513
+ meeting.locusUrl = locusUrl;
14514
+
14515
+ const unsetStagePromise = meeting.unsetStage();
14516
+
14517
+ assert.exists(unsetStagePromise.then);
14518
+ await unsetStagePromise;
14519
+
14520
+ assert.calledOnceWithExactly(
14521
+ meeting.meetingRequest.synchronizeStage,
14522
+ locusUrl,
14523
+ {overrideDefault: false}
14524
+ );
14525
+ });
14526
+ });
14094
14527
  });