@webex/plugin-meetings 3.8.0-next.6 → 3.8.0-next.60

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 (156) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/common/errors/webex-errors.js +12 -2
  4. package/dist/common/errors/webex-errors.js.map +1 -1
  5. package/dist/config.js +1 -0
  6. package/dist/config.js.map +1 -1
  7. package/dist/constants.js +16 -121
  8. package/dist/constants.js.map +1 -1
  9. package/dist/controls-options-manager/enums.js +2 -0
  10. package/dist/controls-options-manager/enums.js.map +1 -1
  11. package/dist/controls-options-manager/types.js.map +1 -1
  12. package/dist/controls-options-manager/util.js +52 -0
  13. package/dist/controls-options-manager/util.js.map +1 -1
  14. package/dist/interpretation/index.js +1 -1
  15. package/dist/interpretation/siLanguage.js +1 -1
  16. package/dist/locus-info/controlsUtils.js +28 -10
  17. package/dist/locus-info/controlsUtils.js.map +1 -1
  18. package/dist/locus-info/index.js +20 -1
  19. package/dist/locus-info/index.js.map +1 -1
  20. package/dist/locus-info/selfUtils.js +405 -418
  21. package/dist/locus-info/selfUtils.js.map +1 -1
  22. package/dist/media/index.js +8 -16
  23. package/dist/media/index.js.map +1 -1
  24. package/dist/meeting/in-meeting-actions.js +13 -1
  25. package/dist/meeting/in-meeting-actions.js.map +1 -1
  26. package/dist/meeting/index.js +548 -288
  27. package/dist/meeting/index.js.map +1 -1
  28. package/dist/meeting/locusMediaRequest.js +0 -17
  29. package/dist/meeting/locusMediaRequest.js.map +1 -1
  30. package/dist/meeting/muteState.js +0 -2
  31. package/dist/meeting/muteState.js.map +1 -1
  32. package/dist/meeting/request.js +30 -0
  33. package/dist/meeting/request.js.map +1 -1
  34. package/dist/meeting/request.type.js.map +1 -1
  35. package/dist/meeting/util.js +13 -2
  36. package/dist/meeting/util.js.map +1 -1
  37. package/dist/meeting-info/meeting-info-v2.js +359 -60
  38. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  39. package/dist/meetings/index.js +91 -1
  40. package/dist/meetings/index.js.map +1 -1
  41. package/dist/meetings/util.js +14 -0
  42. package/dist/meetings/util.js.map +1 -1
  43. package/dist/member/index.js +10 -0
  44. package/dist/member/index.js.map +1 -1
  45. package/dist/member/util.js +3 -0
  46. package/dist/member/util.js.map +1 -1
  47. package/dist/members/index.js +23 -0
  48. package/dist/members/index.js.map +1 -1
  49. package/dist/members/request.js +21 -0
  50. package/dist/members/request.js.map +1 -1
  51. package/dist/members/util.js +15 -0
  52. package/dist/members/util.js.map +1 -1
  53. package/dist/metrics/constants.js +9 -0
  54. package/dist/metrics/constants.js.map +1 -1
  55. package/dist/reachability/clusterReachability.js +63 -27
  56. package/dist/reachability/clusterReachability.js.map +1 -1
  57. package/dist/reachability/index.js +112 -47
  58. package/dist/reachability/index.js.map +1 -1
  59. package/dist/reachability/reachability.types.js +14 -0
  60. package/dist/reachability/reachability.types.js.map +1 -1
  61. package/dist/reachability/request.js +19 -3
  62. package/dist/reachability/request.js.map +1 -1
  63. package/dist/reconnection-manager/index.js +2 -2
  64. package/dist/reconnection-manager/index.js.map +1 -1
  65. package/dist/recording-controller/util.js +5 -5
  66. package/dist/recording-controller/util.js.map +1 -1
  67. package/dist/roap/index.js.map +1 -1
  68. package/dist/roap/turnDiscovery.js +45 -27
  69. package/dist/roap/turnDiscovery.js.map +1 -1
  70. package/dist/roap/types.js +17 -0
  71. package/dist/roap/types.js.map +1 -0
  72. package/dist/types/common/errors/webex-errors.d.ts +7 -1
  73. package/dist/types/config.d.ts +1 -0
  74. package/dist/types/constants.d.ts +11 -85
  75. package/dist/types/controls-options-manager/enums.d.ts +3 -1
  76. package/dist/types/controls-options-manager/types.d.ts +7 -1
  77. package/dist/types/locus-info/index.d.ts +1 -0
  78. package/dist/types/locus-info/selfUtils.d.ts +247 -1
  79. package/dist/types/meeting/in-meeting-actions.d.ts +12 -0
  80. package/dist/types/meeting/index.d.ts +54 -1
  81. package/dist/types/meeting/muteState.d.ts +0 -1
  82. package/dist/types/meeting/request.d.ts +12 -1
  83. package/dist/types/meeting/request.type.d.ts +6 -0
  84. package/dist/types/meeting/util.d.ts +3 -1
  85. package/dist/types/meeting-info/meeting-info-v2.d.ts +80 -0
  86. package/dist/types/meetings/index.d.ts +38 -0
  87. package/dist/types/member/index.d.ts +1 -0
  88. package/dist/types/members/index.d.ts +8 -0
  89. package/dist/types/members/request.d.ts +19 -0
  90. package/dist/types/members/util.d.ts +13 -0
  91. package/dist/types/metrics/constants.d.ts +9 -0
  92. package/dist/types/reachability/clusterReachability.d.ts +15 -7
  93. package/dist/types/reachability/index.d.ts +10 -1
  94. package/dist/types/reachability/reachability.types.d.ts +5 -0
  95. package/dist/types/roap/index.d.ts +3 -2
  96. package/dist/types/roap/turnDiscovery.d.ts +5 -17
  97. package/dist/types/roap/types.d.ts +16 -0
  98. package/dist/webinar/index.js +1 -1
  99. package/package.json +23 -23
  100. package/src/common/errors/webex-errors.ts +8 -1
  101. package/src/config.ts +1 -0
  102. package/src/constants.ts +18 -90
  103. package/src/controls-options-manager/enums.ts +2 -0
  104. package/src/controls-options-manager/types.ts +11 -1
  105. package/src/controls-options-manager/util.ts +62 -0
  106. package/src/locus-info/controlsUtils.ts +44 -14
  107. package/src/locus-info/index.ts +23 -1
  108. package/src/locus-info/selfUtils.ts +451 -447
  109. package/src/media/index.ts +11 -21
  110. package/src/meeting/in-meeting-actions.ts +24 -0
  111. package/src/meeting/index.ts +364 -92
  112. package/src/meeting/locusMediaRequest.ts +0 -18
  113. package/src/meeting/muteState.ts +0 -2
  114. package/src/meeting/request.ts +36 -1
  115. package/src/meeting/request.type.ts +7 -0
  116. package/src/meeting/util.ts +11 -2
  117. package/src/meeting-info/meeting-info-v2.ts +247 -6
  118. package/src/meetings/index.ts +107 -1
  119. package/src/meetings/util.ts +18 -0
  120. package/src/member/index.ts +11 -0
  121. package/src/member/util.ts +3 -0
  122. package/src/members/index.ts +25 -0
  123. package/src/members/request.ts +26 -0
  124. package/src/members/util.ts +16 -0
  125. package/src/metrics/constants.ts +9 -0
  126. package/src/reachability/clusterReachability.ts +73 -26
  127. package/src/reachability/index.ts +70 -1
  128. package/src/reachability/reachability.types.ts +6 -0
  129. package/src/reachability/request.ts +7 -0
  130. package/src/reconnection-manager/index.ts +2 -2
  131. package/src/recording-controller/util.ts +17 -13
  132. package/src/roap/index.ts +3 -7
  133. package/src/roap/turnDiscovery.ts +34 -39
  134. package/src/roap/types.ts +23 -0
  135. package/test/unit/spec/controls-options-manager/util.js +120 -0
  136. package/test/unit/spec/locus-info/controlsUtils.js +103 -9
  137. package/test/unit/spec/locus-info/index.js +28 -0
  138. package/test/unit/spec/media/index.ts +36 -16
  139. package/test/unit/spec/meeting/in-meeting-actions.ts +15 -4
  140. package/test/unit/spec/meeting/index.js +518 -34
  141. package/test/unit/spec/meeting/locusMediaRequest.ts +0 -30
  142. package/test/unit/spec/meeting/muteState.js +0 -2
  143. package/test/unit/spec/meeting/request.js +32 -1
  144. package/test/unit/spec/meeting/utils.js +119 -18
  145. package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
  146. package/test/unit/spec/meetings/index.js +120 -2
  147. package/test/unit/spec/member/index.js +7 -0
  148. package/test/unit/spec/member/util.js +24 -0
  149. package/test/unit/spec/members/index.js +103 -26
  150. package/test/unit/spec/members/request.js +45 -22
  151. package/test/unit/spec/members/utils.js +33 -0
  152. package/test/unit/spec/reachability/clusterReachability.ts +88 -56
  153. package/test/unit/spec/reachability/index.ts +101 -0
  154. package/test/unit/spec/reachability/request.js +47 -2
  155. package/test/unit/spec/reconnection-manager/index.js +4 -4
  156. package/test/unit/spec/roap/turnDiscovery.ts +110 -28
@@ -182,6 +182,15 @@ describe('plugin-meetings', () => {
182
182
  metrics: {
183
183
  submitClientMetrics: sinon.stub().returns(Promise.resolve()),
184
184
  },
185
+ newMetrics: {
186
+ submitClientEvent: sinon.stub(),
187
+ callDiagnosticLatencies: {
188
+ measureLatency: sinon.stub().returns(Promise.resolve()),
189
+ },
190
+ callDiagnosticMetrics: {
191
+ clearErrorCache: sinon.stub(),
192
+ },
193
+ },
185
194
  });
186
195
  webex.emit('ready');
187
196
  });
@@ -285,7 +294,8 @@ describe('plugin-meetings', () => {
285
294
 
286
295
  describe('failure', () => {
287
296
  it('should not accept non-number input', () => {
288
- const logUploadIntervalMultiplicationFactor = webex.meetings.config.logUploadIntervalMultiplicationFactor;
297
+ const logUploadIntervalMultiplicationFactor =
298
+ webex.meetings.config.logUploadIntervalMultiplicationFactor;
289
299
 
290
300
  webex.meetings._setLogUploadIntervalMultiplicationFactor('test');
291
301
  assert.equal(
@@ -390,6 +400,19 @@ describe('plugin-meetings', () => {
390
400
  });
391
401
  });
392
402
 
403
+ describe('#_toggleDisableAudioMainDtx', () => {
404
+ it('should have _toggleDisableAudioMainDtx', () => {
405
+ assert.equal(typeof webex.meetings._toggleDisableAudioMainDtx, 'function');
406
+ });
407
+
408
+ describe('success', () => {
409
+ it('should update meetings to disable audio main dtx', () => {
410
+ webex.meetings._toggleDisableAudioMainDtx(true);
411
+ assert.equal(webex.meetings.config.experimental.disableAudioMainDtx, true);
412
+ });
413
+ });
414
+ });
415
+
393
416
  describe('Public API Contracts', () => {
394
417
  describe('#register', () => {
395
418
  it('emits an event and resolves when register succeeds', async () => {
@@ -441,6 +464,19 @@ describe('plugin-meetings', () => {
441
464
  assert.isTrue(webex.meetings.registered);
442
465
  });
443
466
 
467
+ it('resolves even if startReachability() rejects', async () => {
468
+ webex.canAuthorize = true;
469
+ webex.meetings.registered = false;
470
+ webex.meetings.startReachability = sinon.stub().rejects(new Error('fake error'));
471
+
472
+ await webex.meetings.register();
473
+ assert.calledOnceWithExactly(webex.internal.device.register, undefined);
474
+ assert.called(webex.internal.services.getMeetingPreferences);
475
+ assert.called(webex.internal.services.fetchClientRegionInfo);
476
+ assert.called(webex.internal.mercury.connect);
477
+ assert.isTrue(webex.meetings.registered);
478
+ });
479
+
444
480
  it('passes on the device registration options', async () => {
445
481
  webex.canAuthorize = true;
446
482
  webex.meetings.registered = false;
@@ -569,6 +605,24 @@ describe('plugin-meetings', () => {
569
605
  await assert.isRejected(webex.meetings.unregister());
570
606
  });
571
607
 
608
+ it('does not reject when device.unregister fails with statusCode 404', (done) => {
609
+ webex.meetings.registered = true;
610
+ webex.internal.device.unregister = sinon.stub().rejects({statusCode: 404});
611
+ webex.meetings.unregister().then(() => {
612
+ assert.calledWith(
613
+ TriggerProxy.trigger,
614
+ sinon.match.instanceOf(Meetings),
615
+ {
616
+ file: 'meetings',
617
+ function: 'unregister',
618
+ },
619
+ 'meetings:unregistered'
620
+ );
621
+ assert.isFalse(webex.meetings.registered);
622
+ done();
623
+ });
624
+ });
625
+
572
626
  it('rejects when mercury.disconnect fails', async () => {
573
627
  webex.meetings.registered = true;
574
628
  webex.internal.mercury.disconnect = sinon.stub().returns(Promise.reject());
@@ -617,6 +671,7 @@ describe('plugin-meetings', () => {
617
671
  quality: 'LOW',
618
672
  authToken: 'fake_token',
619
673
  mirror: false,
674
+ canvasResolutionScaling: 1,
620
675
  });
621
676
  assert.exists(result.enable);
622
677
  assert.exists(result.disable);
@@ -632,6 +687,7 @@ describe('plugin-meetings', () => {
632
687
  quality: 'HIGH',
633
688
  blurStrength: 'STRONG',
634
689
  bgImageUrl: 'https://test.webex.com/landscape.5a535788.jpg',
690
+ canvasResolutionScaling: 1,
635
691
  };
636
692
 
637
693
  const result = await webex.meetings.createVirtualBackgroundEffect(effectOptions);
@@ -666,7 +722,6 @@ describe('plugin-meetings', () => {
666
722
  audioContext: {},
667
723
  authToken: 'fake_token',
668
724
  mode: 'WORKLET',
669
- env: 'prod',
670
725
  avoidSimd: false,
671
726
  });
672
727
  assert.exists(result.enable);
@@ -918,6 +973,69 @@ describe('plugin-meetings', () => {
918
973
  });
919
974
  });
920
975
  });
976
+ describe('#fetchStaticMeetingLink', () => {
977
+ const conversationUrl = 'conv.fakeconversationurl.com';
978
+
979
+ afterEach(() => {
980
+ sinon.restore();
981
+ });
982
+
983
+ it('should have #fetchStaticMeetingLink', () => {
984
+ assert.exists(webex.meetings.fetchStaticMeetingLink);
985
+ });
986
+
987
+ it('should call MeetingInfo#fetchStaticMeetingLink() with proper params', () => {
988
+ webex.meetings.meetingInfo.fetchStaticMeetingLink = sinon
989
+ .stub()
990
+ .resolves(conversationUrl);
991
+
992
+ return webex.meetings.fetchStaticMeetingLink(conversationUrl).then(() => {
993
+ assert.calledWith(webex.meetings.meetingInfo.fetchStaticMeetingLink, conversationUrl);
994
+ });
995
+ });
996
+ });
997
+ describe('#enableStaticMeetingLink', () => {
998
+ const conversationUrl = 'conv.fakeconversationurl.com';
999
+
1000
+ afterEach(() => {
1001
+ sinon.restore();
1002
+ });
1003
+
1004
+ it('should have #enableStaticMeetingLink', () => {
1005
+ assert.exists(webex.meetings.enableStaticMeetingLink);
1006
+ });
1007
+
1008
+ it('should call MeetingInfo#enableStaticMeetingLink() with proper params', () => {
1009
+ webex.meetings.meetingInfo.enableStaticMeetingLink = sinon
1010
+ .stub()
1011
+ .resolves(conversationUrl);
1012
+
1013
+ return webex.meetings.enableStaticMeetingLink(conversationUrl).then(() => {
1014
+ assert.calledWith(webex.meetings.meetingInfo.enableStaticMeetingLink, conversationUrl);
1015
+ });
1016
+ });
1017
+ });
1018
+ describe('#disableStaticMeetingLink', () => {
1019
+ const conversationUrl = 'conv.fakeconversationurl.com';
1020
+
1021
+ afterEach(() => {
1022
+ sinon.restore();
1023
+ });
1024
+
1025
+ it('should have #disableStaticMeetingLink', () => {
1026
+ assert.exists(webex.meetings.disableStaticMeetingLink);
1027
+ });
1028
+
1029
+ it('should call MeetingInfo#disableStaticMeetingLink() with proper params', () => {
1030
+ webex.meetings.meetingInfo.disableStaticMeetingLink = sinon
1031
+ .stub()
1032
+ .resolves(conversationUrl);
1033
+
1034
+ return webex.meetings.disableStaticMeetingLink(conversationUrl).then(() => {
1035
+ assert.calledWith(webex.meetings.meetingInfo.disableStaticMeetingLink, conversationUrl);
1036
+ });
1037
+ });
1038
+ });
921
1039
  describe('#create', () => {
922
1040
  let infoOptions;
923
1041
 
@@ -50,6 +50,13 @@ describe('member', () => {
50
50
 
51
51
  assert.calledOnceWithExactly(MemberUtil.canReclaimHost, participant);
52
52
  });
53
+
54
+ it('checks that processParticipant calls isPresenterAssignmentProhibited', () => {
55
+ sinon.spy(MemberUtil, 'isPresenterAssignmentProhibited');
56
+ member.processParticipant(participant);
57
+
58
+ assert.calledOnceWithExactly(MemberUtil.isPresenterAssignmentProhibited, participant);
59
+ });
53
60
  })
54
61
 
55
62
  describe('#processMember', () => {
@@ -557,6 +557,30 @@ describe('plugin-meetings', () => {
557
557
  testResult(false, undefined, false);
558
558
  });
559
559
  });
560
+
561
+ describe('MemberUtil.isPresenterAssignmentProhibited', () => {
562
+ it('returns true when isPresenterAssignmentProhibited is true', () => {
563
+ const participant = {
564
+ presenterAssignmentNotAllowed: true
565
+ };
566
+
567
+ assert.isTrue(MemberUtil.isPresenterAssignmentProhibited(participant));
568
+ });
569
+
570
+ it('returns false when isPresenterAssignmentProhibited is false', () => {
571
+ const participant = {
572
+ presenterAssignmentNotAllowed: false,
573
+ };
574
+
575
+ assert.isFalse(MemberUtil.isPresenterAssignmentProhibited(participant));
576
+ });
577
+
578
+ it('returns undefined when isPresenterAssignmentProhibited is undefined', () => {
579
+ const participant = {};
580
+
581
+ assert.isUndefined(MemberUtil.isPresenterAssignmentProhibited(participant));
582
+ });
583
+ });
560
584
  });
561
585
 
562
586
  describe('extractMediaStatus', () => {
@@ -120,9 +120,9 @@ describe('plugin-meetings', () => {
120
120
  meeting = {
121
121
  request: sinon.mock().returns(Promise.resolve()),
122
122
  locusInfo: {
123
- sequence: {}
124
- }
125
- }
123
+ sequence: {},
124
+ },
125
+ };
126
126
 
127
127
  createMembers = (options) => new Members({locusUrl: options.url, meeting}, {parent: webex});
128
128
  });
@@ -349,7 +349,7 @@ describe('plugin-meetings', () => {
349
349
  {type: 'COHOST', hasRole: true},
350
350
  ];
351
351
 
352
- const resolvedValue = "it worked";
352
+ const resolvedValue = 'it worked';
353
353
 
354
354
  const genericMessage = 'Generic error from the API';
355
355
 
@@ -364,9 +364,13 @@ describe('plugin-meetings', () => {
364
364
  };
365
365
 
366
366
  if (errorCode) {
367
- spies.assignRolesMember = sandbox.stub(members.membersRequest, 'assignRolesMember').rejects({body: {errorCode}, message: genericMessage});
367
+ spies.assignRolesMember = sandbox
368
+ .stub(members.membersRequest, 'assignRolesMember')
369
+ .rejects({body: {errorCode}, message: genericMessage});
368
370
  } else {
369
- spies.assignRolesMember = sandbox.stub(members.membersRequest, 'assignRolesMember').resolves(resolvedValue);
371
+ spies.assignRolesMember = sandbox
372
+ .stub(members.membersRequest, 'assignRolesMember')
373
+ .resolves(resolvedValue);
370
374
  }
371
375
 
372
376
  return {members, spies};
@@ -378,7 +382,15 @@ describe('plugin-meetings', () => {
378
382
  assert.notCalled(spies.assignRolesMember);
379
383
  };
380
384
 
381
- const checkError = async (error, expectedMemberId, expectedRoles, expectedLocusUrl, resultPromise, expectedMessage, spies) => {
385
+ const checkError = async (
386
+ error,
387
+ expectedMemberId,
388
+ expectedRoles,
389
+ expectedLocusUrl,
390
+ resultPromise,
391
+ expectedMessage,
392
+ spies
393
+ ) => {
382
394
  await assert.isRejected(resultPromise, error, expectedMessage);
383
395
  assert.calledOnceWithExactly(
384
396
  spies.generateRoleAssignmentMemberOptions,
@@ -423,7 +435,7 @@ describe('plugin-meetings', () => {
423
435
  await checkInvalid(
424
436
  resultPromise,
425
437
  'The member id must be defined to assign the roles to a member.',
426
- spies,
438
+ spies
427
439
  );
428
440
  });
429
441
 
@@ -435,7 +447,7 @@ describe('plugin-meetings', () => {
435
447
  await checkInvalid(
436
448
  resultPromise,
437
449
  'The associated locus url for this meetings members object must be defined.',
438
- spies,
450
+ spies
439
451
  );
440
452
  });
441
453
 
@@ -452,7 +464,7 @@ describe('plugin-meetings', () => {
452
464
  url1,
453
465
  resultPromise,
454
466
  'Non converged meetings, PSTN or SIP users in converged meetings are not supported currently.',
455
- spies,
467
+ spies
456
468
  );
457
469
  });
458
470
 
@@ -469,7 +481,7 @@ describe('plugin-meetings', () => {
469
481
  url1,
470
482
  resultPromise,
471
483
  'Reclaim Host Role Not Allowed For Other Participants. Participants cannot claim host role in PMR meeting, space instant meeting or escalated instant meeting. However, the original host still can reclaim host role when it manually makes another participant to be the host.',
472
- spies,
484
+ spies
473
485
  );
474
486
  });
475
487
 
@@ -486,7 +498,7 @@ describe('plugin-meetings', () => {
486
498
  url1,
487
499
  resultPromise,
488
500
  'Host Key Not Specified Or Matched. The original host can reclaim the host role without entering the host key. However, any other person who claims the host role must enter the host key to get it.',
489
- spies,
501
+ spies
490
502
  );
491
503
  });
492
504
 
@@ -503,7 +515,7 @@ describe('plugin-meetings', () => {
503
515
  url1,
504
516
  resultPromise,
505
517
  'Participant Having Host Role Already. Participant who sends request to reclaim host role has already a host role.',
506
- spies,
518
+ spies
507
519
  );
508
520
  });
509
521
 
@@ -520,7 +532,7 @@ describe('plugin-meetings', () => {
520
532
  url1,
521
533
  resultPromise,
522
534
  genericMessage,
523
- spies,
535
+ spies
524
536
  );
525
537
  });
526
538
 
@@ -530,13 +542,7 @@ describe('plugin-meetings', () => {
530
542
 
531
543
  const resultPromise = members.assignRoles(memberId, fakeRoles);
532
544
 
533
- await checkValid(
534
- resultPromise,
535
- spies,
536
- memberId,
537
- fakeRoles,
538
- url1,
539
- );
545
+ await checkValid(resultPromise, spies, memberId, fakeRoles, url1);
540
546
  });
541
547
  });
542
548
 
@@ -661,19 +667,19 @@ describe('plugin-meetings', () => {
661
667
  spies,
662
668
  expectedRequestingMemberId,
663
669
  expectedLocusUrl,
664
- expectedRoles,
670
+ expectedRoles
665
671
  ) => {
666
672
  await assert.isFulfilled(resultPromise);
667
673
  assert.calledOnceWithExactly(
668
674
  spies.generateLowerAllHandsMemberOptions,
669
675
  expectedRequestingMemberId,
670
676
  expectedLocusUrl,
671
- expectedRoles,
677
+ expectedRoles
672
678
  );
673
679
  assert.calledOnceWithExactly(spies.lowerAllHandsMember, {
674
680
  requestingParticipantId: expectedRequestingMemberId,
675
681
  locusUrl: expectedLocusUrl,
676
- ...(expectedRoles !== undefined && { roles: expectedRoles })
682
+ ...(expectedRoles !== undefined && {roles: expectedRoles}),
677
683
  });
678
684
  assert.strictEqual(resultPromise, spies.lowerAllHandsMember.getCall(0).returnValue);
679
685
  };
@@ -714,7 +720,7 @@ describe('plugin-meetings', () => {
714
720
  it('should make the correct request when called with valid requestingMemberId and roles', async () => {
715
721
  const requestingMemberId = 'test-member-id';
716
722
  const roles = ['panelist', 'attendee'];
717
- const { members, spies } = setup('test-locus-url');
723
+ const {members, spies} = setup('test-locus-url');
718
724
 
719
725
  const resultPromise = members.lowerAllHands(requestingMemberId, roles);
720
726
 
@@ -724,7 +730,7 @@ describe('plugin-meetings', () => {
724
730
  it('should handle an empty roles array correctly', async () => {
725
731
  const requestingMemberId = 'test-member-id';
726
732
  const roles = [];
727
- const { members, spies } = setup('test-locus-url');
733
+ const {members, spies} = setup('test-locus-url');
728
734
 
729
735
  const resultPromise = members.lowerAllHands(requestingMemberId, roles);
730
736
 
@@ -977,5 +983,76 @@ describe('plugin-meetings', () => {
977
983
  );
978
984
  });
979
985
  });
986
+
987
+ describe('#moveToLobby', () => {
988
+ const setup = (locusUrl) => {
989
+ const members = createMembers({url: locusUrl});
990
+
991
+ const spies = {
992
+ getMoveMemberToLobbyRequestBody: sandbox.spy(
993
+ MembersUtil,
994
+ 'getMoveMemberToLobbyRequestBody'
995
+ ),
996
+ moveToLobbyMember: sandbox.spy(members.membersRequest, 'moveToLobbyMember'),
997
+ };
998
+
999
+ return {members, spies};
1000
+ };
1001
+
1002
+ const checkInvalid = async (resultPromise, expectedMessage, spies) => {
1003
+ await assert.isRejected(resultPromise, ParameterError, expectedMessage);
1004
+ assert.notCalled(spies.getMoveMemberToLobbyRequestBody);
1005
+ assert.notCalled(spies.moveToLobbyMember);
1006
+ };
1007
+
1008
+ const checkValid = async (resultPromise, spies, expectedMemberId, expectedLocusUrl) => {
1009
+ await assert.isFulfilled(resultPromise);
1010
+ assert.calledOnceWithExactly(spies.getMoveMemberToLobbyRequestBody, expectedMemberId);
1011
+ assert.calledOnceWithExactly(
1012
+ spies.moveToLobbyMember,
1013
+ {
1014
+ locusUrl: expectedLocusUrl,
1015
+ memberId: expectedMemberId,
1016
+ },
1017
+ {
1018
+ moveToLobby: {participantIds: [expectedMemberId]},
1019
+ }
1020
+ );
1021
+ assert.strictEqual(resultPromise, spies.moveToLobbyMember.getCall(0).returnValue);
1022
+ };
1023
+
1024
+ it('should not make a request if there is no member id', async () => {
1025
+ const {members, spies} = setup(url1);
1026
+
1027
+ const resultPromise = members.moveToLobby();
1028
+
1029
+ await checkInvalid(
1030
+ resultPromise,
1031
+ 'The member id must be defined to move the member to lobby.',
1032
+ spies
1033
+ );
1034
+ });
1035
+
1036
+ it('should not make a request if there is no locus url', async () => {
1037
+ const {members, spies} = setup();
1038
+
1039
+ const resultPromise = members.moveToLobby(uuid.v4());
1040
+
1041
+ await checkInvalid(
1042
+ resultPromise,
1043
+ 'The associated locus url for this meetings members object must be defined.',
1044
+ spies
1045
+ );
1046
+ });
1047
+
1048
+ it('should make the correct request when called with valid memberId and locusUrl', async () => {
1049
+ const memberId = uuid.v4();
1050
+ const {members, spies} = setup(url1);
1051
+
1052
+ const resultPromise = members.moveToLobby(memberId);
1053
+
1054
+ await checkValid(resultPromise, spies, memberId, url1);
1055
+ });
1056
+ });
980
1057
  });
981
1058
  });
@@ -9,7 +9,7 @@ import Meetings from '@webex/plugin-meetings';
9
9
  import MembersRequest from '@webex/plugin-meetings/src/members/request';
10
10
  import membersUtil from '@webex/plugin-meetings/src/members/util';
11
11
  import ParameterError from '@webex/plugin-meetings/src/common/errors/parameter';
12
- import { merge } from 'lodash';
12
+ import {merge} from 'lodash';
13
13
 
14
14
  const {assert} = chai;
15
15
 
@@ -65,10 +65,7 @@ describe('plugin-meetings', () => {
65
65
 
66
66
  const checkRequest = (expectedParams) => {
67
67
  assert.calledOnceWithExactly(locusDeltaRequestSpy, expectedParams);
68
- assert.calledOnceWithExactly(
69
- membersRequest.request,
70
- merge(expectedParams, {body: {sequence}})
71
- );
68
+ assert.calledOnceWithExactly(membersRequest.request, merge(expectedParams, {body: {sequence}}));
72
69
  };
73
70
 
74
71
  describe('members request library', () => {
@@ -98,8 +95,8 @@ describe('plugin-meetings', () => {
98
95
  },
99
96
  device: {
100
97
  url,
101
- }
102
- }
98
+ },
99
+ },
103
100
  });
104
101
  });
105
102
  });
@@ -120,9 +117,9 @@ describe('plugin-meetings', () => {
120
117
  uri: url1,
121
118
  body: {
122
119
  alertIfActive: undefined,
123
- invitees: [{address: '+18578675309'}]
124
- }
125
- })
120
+ invitees: [{address: '+18578675309'}],
121
+ },
122
+ });
126
123
  });
127
124
  });
128
125
 
@@ -133,16 +130,16 @@ describe('plugin-meetings', () => {
133
130
  memberIds: ['1', '2'],
134
131
  };
135
132
 
136
- await membersRequest.admitMember(options)
133
+ await membersRequest.admitMember(options);
137
134
 
138
135
  checkRequest({
139
136
  method: 'PUT',
140
137
  uri: 'https://example.com/12345/controls',
141
138
  body: {
142
139
  admit: {
143
- participantIds: options.memberIds
144
- }
145
- }
140
+ participantIds: options.memberIds,
141
+ },
142
+ },
146
143
  });
147
144
  });
148
145
  });
@@ -160,7 +157,7 @@ describe('plugin-meetings', () => {
160
157
  method: 'PUT',
161
158
  uri: 'https://example.com/12345/participant/member1/leave',
162
159
  body: {
163
- reason: undefined
160
+ reason: undefined,
164
161
  },
165
162
  });
166
163
  });
@@ -247,9 +244,9 @@ describe('plugin-meetings', () => {
247
244
  uri: `${locusUrl}/participant/${memberId}/controls`,
248
245
  body: {
249
246
  role: {
250
- roles
251
- }
252
- }
247
+ roles,
248
+ },
249
+ },
253
250
  });
254
251
  });
255
252
  });
@@ -272,9 +269,9 @@ describe('plugin-meetings', () => {
272
269
  uri: `${locusUrl}/participant/${memberId}/controls`,
273
270
  body: {
274
271
  hand: {
275
- raised: true
276
- }
277
- }
272
+ raised: true,
273
+ },
274
+ },
278
275
  });
279
276
  });
280
277
  });
@@ -406,7 +403,33 @@ describe('plugin-meetings', () => {
406
403
  body: {
407
404
  aliasValue,
408
405
  requestingParticipantId,
409
- }
406
+ },
407
+ });
408
+ });
409
+ });
410
+
411
+ describe('#moveToLobby', () => {
412
+ it('sends a moveToLobbyMember PATCH to the locus endpoint', async () => {
413
+ const locusUrl = url1;
414
+ const memberId = 'test1';
415
+ const options = {
416
+ locusUrl: locusUrl,
417
+ memberId,
418
+ };
419
+ const body = {
420
+ moveToLobby: {participantIds: [memberId]},
421
+ };
422
+
423
+ const getRequestParamsSpy = sandbox.spy(membersUtil, 'getMoveMemberToLobbyRequestParams');
424
+
425
+ await membersRequest.moveToLobbyMember(options, body);
426
+
427
+ assert.calledOnceWithExactly(getRequestParamsSpy, options, body);
428
+
429
+ checkRequest({
430
+ method: 'PATCH',
431
+ uri: `${locusUrl}/participant/${memberId}/controls`,
432
+ body: {moveToLobby: {participantIds: [memberId]}},
410
433
  });
411
434
  });
412
435
  });
@@ -357,5 +357,38 @@ describe('plugin-meetings', () => {
357
357
  });
358
358
  });
359
359
  });
360
+
361
+ describe('#getMoveMemberToLobbyRequestBody', () => {
362
+ it('returns the correct options', () => {
363
+ const memberId = 'test1';
364
+ assert.deepEqual(MembersUtil.getMoveMemberToLobbyRequestBody(memberId), {
365
+ moveToLobby: {
366
+ participantIds: [memberId],
367
+ },
368
+ });
369
+ });
370
+ });
371
+
372
+ describe('#getMoveMemberToLobbyRequestParams', () => {
373
+ it('returns the correct params', () => {
374
+ const locusUrl = 'TestLocusUrl';
375
+ const memberId = 'test1';
376
+ const options = {
377
+ locusUrl: locusUrl,
378
+ memberId,
379
+ };
380
+ const body = {
381
+ moveToLobby: {participantIds: [memberId]},
382
+ };
383
+
384
+ const uri = `${options.locusUrl}/${PARTICIPANT}/${options.memberId}/${CONTROLS}`;
385
+
386
+ assert.deepEqual(MembersUtil.getMoveMemberToLobbyRequestParams(options, body), {
387
+ method: HTTP_VERBS.PATCH,
388
+ uri,
389
+ body,
390
+ });
391
+ });
392
+ });
360
393
  });
361
394
  });