@webex/plugin-meetings 3.8.0-next.37 → 3.8.0-next.39

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 (43) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +11 -1
  4. package/dist/constants.js.map +1 -1
  5. package/dist/controls-options-manager/enums.js +2 -0
  6. package/dist/controls-options-manager/enums.js.map +1 -1
  7. package/dist/controls-options-manager/types.js.map +1 -1
  8. package/dist/controls-options-manager/util.js +52 -0
  9. package/dist/controls-options-manager/util.js.map +1 -1
  10. package/dist/interpretation/index.js +1 -1
  11. package/dist/interpretation/siLanguage.js +1 -1
  12. package/dist/locus-info/controlsUtils.js +14 -2
  13. package/dist/locus-info/controlsUtils.js.map +1 -1
  14. package/dist/locus-info/index.js +18 -0
  15. package/dist/locus-info/index.js.map +1 -1
  16. package/dist/meeting/in-meeting-actions.js +9 -1
  17. package/dist/meeting/in-meeting-actions.js.map +1 -1
  18. package/dist/meeting/index.js +42 -8
  19. package/dist/meeting/index.js.map +1 -1
  20. package/dist/meeting/util.js +3 -1
  21. package/dist/meeting/util.js.map +1 -1
  22. package/dist/types/constants.d.ts +8 -0
  23. package/dist/types/controls-options-manager/enums.d.ts +3 -1
  24. package/dist/types/controls-options-manager/types.d.ts +7 -1
  25. package/dist/types/meeting/in-meeting-actions.d.ts +8 -0
  26. package/dist/types/meeting/util.d.ts +1 -1
  27. package/dist/webinar/index.js +1 -1
  28. package/package.json +3 -3
  29. package/src/constants.ts +13 -0
  30. package/src/controls-options-manager/enums.ts +2 -0
  31. package/src/controls-options-manager/types.ts +11 -1
  32. package/src/controls-options-manager/util.ts +62 -0
  33. package/src/locus-info/controlsUtils.ts +18 -0
  34. package/src/locus-info/index.ts +18 -0
  35. package/src/meeting/in-meeting-actions.ts +16 -0
  36. package/src/meeting/index.ts +34 -0
  37. package/src/meeting/util.ts +2 -1
  38. package/test/unit/spec/controls-options-manager/util.js +120 -0
  39. package/test/unit/spec/locus-info/controlsUtils.js +46 -12
  40. package/test/unit/spec/locus-info/index.js +28 -0
  41. package/test/unit/spec/meeting/in-meeting-actions.ts +8 -1
  42. package/test/unit/spec/meeting/index.js +52 -0
  43. package/test/unit/spec/meeting/utils.js +4 -0
@@ -817,6 +817,8 @@ export default class LocusInfo extends EventsScope {
817
817
  hasMeetingFullChanged,
818
818
  hasPracticeSessionEnabledChanged,
819
819
  hasStageViewChanged,
820
+ hasAnnotationControlChanged,
821
+ hasRemoteDesktopControlChanged,
820
822
  },
821
823
  current,
822
824
  } = ControlsUtils.getControls(this.controls, controls);
@@ -1052,6 +1054,22 @@ export default class LocusInfo extends EventsScope {
1052
1054
  );
1053
1055
  }
1054
1056
 
1057
+ if (hasAnnotationControlChanged) {
1058
+ this.emitScoped(
1059
+ {file: 'locus-info', function: 'updateControls'},
1060
+ LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED,
1061
+ {state: current.annotationControl}
1062
+ );
1063
+ }
1064
+
1065
+ if (hasRemoteDesktopControlChanged) {
1066
+ this.emitScoped(
1067
+ {file: 'locus-info', function: 'updateControls'},
1068
+ LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED,
1069
+ {state: current.rdcControl}
1070
+ );
1071
+ }
1072
+
1055
1073
  this.controls = controls;
1056
1074
  }
1057
1075
  }
@@ -99,6 +99,10 @@ interface IInMeetingActions {
99
99
  isPracticeSessionOff?: boolean;
100
100
  canStartPracticeSession?: boolean;
101
101
  canStopPracticeSession?: boolean;
102
+ canEnableAnnotation?: boolean;
103
+ canDisableAnnotation?: boolean;
104
+ canEnableRemoteDesktopControl?: boolean;
105
+ canDisableRemoteDesktopControl?: boolean;
102
106
  }
103
107
 
104
108
  /**
@@ -285,6 +289,14 @@ export default class InMeetingActions implements IInMeetingActions {
285
289
 
286
290
  canStopPracticeSession = null;
287
291
 
292
+ canEnableAnnotation = null;
293
+
294
+ canDisableAnnotation = null;
295
+
296
+ canEnableRemoteDesktopControl = null;
297
+
298
+ canDisableRemoteDesktopControl = null;
299
+
288
300
  /**
289
301
  * Returns all meeting action options
290
302
  * @returns {Object}
@@ -379,6 +391,10 @@ export default class InMeetingActions implements IInMeetingActions {
379
391
  isPracticeSessionOff: this.isPracticeSessionOff,
380
392
  canStartPracticeSession: this.canStartPracticeSession,
381
393
  canStopPracticeSession: this.canStopPracticeSession,
394
+ canEnableAnnotation: this.canEnableAnnotation,
395
+ canDisableAnnotation: this.canDisableAnnotation,
396
+ canEnableRemoteDesktopControl: this.canEnableRemoteDesktopControl,
397
+ canDisableRemoteDesktopControl: this.canDisableRemoteDesktopControl,
382
398
  });
383
399
 
384
400
  /**
@@ -2871,6 +2871,24 @@ export default class Meeting extends StatelessWebexPlugin {
2871
2871
  {state}
2872
2872
  );
2873
2873
  });
2874
+
2875
+ this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED, ({state}) => {
2876
+ Trigger.trigger(
2877
+ this,
2878
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
2879
+ EVENT_TRIGGERS.MEETING_CONTROLS_ANNOTATION_UPDATED,
2880
+ {state}
2881
+ );
2882
+ });
2883
+
2884
+ this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED, ({state}) => {
2885
+ Trigger.trigger(
2886
+ this,
2887
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
2888
+ EVENT_TRIGGERS.MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED,
2889
+ {state}
2890
+ );
2891
+ });
2874
2892
  }
2875
2893
 
2876
2894
  /**
@@ -4269,6 +4287,22 @@ export default class Meeting extends StatelessWebexPlugin {
4269
4287
  requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
4270
4288
  policies: this.selfUserPolicies,
4271
4289
  }),
4290
+ canEnableAnnotation: ControlsOptionsUtil.hasHints({
4291
+ requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
4292
+ displayHints: this.userDisplayHints,
4293
+ }),
4294
+ canDisableAnnotation: ControlsOptionsUtil.hasHints({
4295
+ requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
4296
+ displayHints: this.userDisplayHints,
4297
+ }),
4298
+ canEnableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
4299
+ requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
4300
+ displayHints: this.userDisplayHints,
4301
+ }),
4302
+ canDisableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
4303
+ requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
4304
+ displayHints: this.userDisplayHints,
4305
+ }),
4272
4306
  }) || changed;
4273
4307
  }
4274
4308
  if (changed) {
@@ -575,7 +575,8 @@ const MeetingUtil = {
575
575
 
576
576
  canUserRenameOthers: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAN_RENAME_OTHERS),
577
577
 
578
- canShareWhiteBoard: (displayHints, policies) =>
578
+ // Default empty value for policies if we get an undefined value (ie permissionToken is not available)
579
+ canShareWhiteBoard: (displayHints, policies = {}) =>
579
580
  displayHints.includes(DISPLAY_HINTS.SHARE_WHITEBOARD) &&
580
581
  !!policies[SELF_POLICY.SUPPORT_WHITEBOARD],
581
582
 
@@ -406,6 +406,74 @@ describe('plugin-meetings', () => {
406
406
  });
407
407
  });
408
408
 
409
+ describe('canUpdateAnnotation()', () => {
410
+ beforeEach(() => {
411
+ sinon.stub(ControlsOptionsUtil, 'hasHints').returns(true);
412
+ });
413
+
414
+ it('should call hasHints() with proper hints when `enabled` is true', () => {
415
+ ControlsOptionsUtil.canUpdateAnnotation({properties: {enabled: true}}, []);
416
+
417
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
418
+ requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
419
+ displayHints: [],
420
+ });
421
+ });
422
+
423
+ it('should call hasHints() with proper hints when `enabled` is false', () => {
424
+ ControlsOptionsUtil.canUpdateAnnotation({properties: {enabled: false}}, []);
425
+
426
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
427
+ requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
428
+ displayHints: [],
429
+ });
430
+ });
431
+
432
+ it('should return the resolution of hasHints()', () => {
433
+ const expected = 'example-return-value';
434
+ ControlsOptionsUtil.hasHints.returns(expected);
435
+
436
+ const results = ControlsOptionsUtil.canUpdateAnnotation({properties: {}}, []);
437
+
438
+ assert.calledOnce(ControlsOptionsUtil.hasHints);
439
+ assert.equal(results, expected);
440
+ });
441
+ });
442
+
443
+ describe('canUpdateRemoteDesktopControl()', () => {
444
+ beforeEach(() => {
445
+ sinon.stub(ControlsOptionsUtil, 'hasHints').returns(true);
446
+ });
447
+
448
+ it('should call hasHints() with proper hints when `enabled` is true', () => {
449
+ ControlsOptionsUtil.canUpdateRemoteDesktopControl({properties: {enabled: true}}, []);
450
+
451
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
452
+ requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
453
+ displayHints: [],
454
+ });
455
+ });
456
+
457
+ it('should call hasHints() with proper hints when `enabled` is false', () => {
458
+ ControlsOptionsUtil.canUpdateRemoteDesktopControl({properties: {enabled: false}}, []);
459
+
460
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
461
+ requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
462
+ displayHints: [],
463
+ });
464
+ });
465
+
466
+ it('should return the resolution of hasHints()', () => {
467
+ const expected = 'example-return-value';
468
+ ControlsOptionsUtil.hasHints.returns(expected);
469
+
470
+ const results = ControlsOptionsUtil.canUpdateRemoteDesktopControl({properties: {}}, []);
471
+
472
+ assert.calledOnce(ControlsOptionsUtil.hasHints);
473
+ assert.equal(results, expected);
474
+ });
475
+ });
476
+
409
477
  describe('canUpdate()', () => {
410
478
  const displayHints = [];
411
479
 
@@ -416,6 +484,8 @@ describe('plugin-meetings', () => {
416
484
  ControlsOptionsUtil.canUpdateShareControl = sinon.stub().returns(true);
417
485
  ControlsOptionsUtil.canUpdateVideo = sinon.stub().returns(true);
418
486
  ControlsOptionsUtil.canUpdateViewTheParticipantsList = sinon.stub().returns(true);
487
+ ControlsOptionsUtil.canUpdateAnnotation = sinon.stub().returns(true);
488
+ ControlsOptionsUtil.canUpdateRemoteDesktopControl = sinon.stub().returns(true);
419
489
  });
420
490
 
421
491
  it('should only call canUpdateAudio() if the scope is audio', () => {
@@ -429,6 +499,8 @@ describe('plugin-meetings', () => {
429
499
  assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
430
500
  assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
431
501
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
502
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
503
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
432
504
  assert.isTrue(results);
433
505
  });
434
506
 
@@ -443,6 +515,8 @@ describe('plugin-meetings', () => {
443
515
  assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
444
516
  assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
445
517
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
518
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
519
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
446
520
  assert.isTrue(results);
447
521
  });
448
522
 
@@ -457,6 +531,8 @@ describe('plugin-meetings', () => {
457
531
  assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
458
532
  assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
459
533
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
534
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
535
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
460
536
  assert.isTrue(results);
461
537
  });
462
538
 
@@ -471,6 +547,8 @@ describe('plugin-meetings', () => {
471
547
  assert.calledWith(ControlsOptionsUtil.canUpdateShareControl, displayHints);
472
548
  assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
473
549
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
550
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
551
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
474
552
  assert.isTrue(results);
475
553
  });
476
554
 
@@ -485,6 +563,8 @@ describe('plugin-meetings', () => {
485
563
  assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
486
564
  assert.calledWith(ControlsOptionsUtil.canUpdateVideo, control, displayHints);
487
565
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
566
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
567
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
488
568
  assert.isTrue(results);
489
569
  });
490
570
 
@@ -503,6 +583,44 @@ describe('plugin-meetings', () => {
503
583
  control,
504
584
  displayHints
505
585
  );
586
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
587
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
588
+ assert.isTrue(results);
589
+ });
590
+
591
+ it('should only call canUpdateAnnotation() if the scope is annotation', () => {
592
+ const control = {scope: 'annotation'};
593
+
594
+ const results = ControlsOptionsUtil.canUpdate(control, displayHints);
595
+
596
+ assert.callCount(ControlsOptionsUtil.canUpdateAudio, 0);
597
+ assert.callCount(ControlsOptionsUtil.canUpdateRaiseHand, 0);
598
+ assert.callCount(ControlsOptionsUtil.canUpdateReactions, 0);
599
+ assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
600
+ assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
601
+ assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
602
+ assert.calledWith(ControlsOptionsUtil.canUpdateAnnotation, control, displayHints);
603
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
604
+ assert.isTrue(results);
605
+ });
606
+
607
+ it('should only call canUpdateRemoteDesktopControl() if the scope is rdc', () => {
608
+ const control = {scope: 'rdc'};
609
+
610
+ const results = ControlsOptionsUtil.canUpdate(control, displayHints);
611
+
612
+ assert.callCount(ControlsOptionsUtil.canUpdateAudio, 0);
613
+ assert.callCount(ControlsOptionsUtil.canUpdateRaiseHand, 0);
614
+ assert.callCount(ControlsOptionsUtil.canUpdateReactions, 0);
615
+ assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
616
+ assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
617
+ assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
618
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
619
+ assert.calledWith(
620
+ ControlsOptionsUtil.canUpdateRemoteDesktopControl,
621
+ control,
622
+ displayHints
623
+ );
506
624
  assert.isTrue(results);
507
625
  });
508
626
 
@@ -517,6 +635,8 @@ describe('plugin-meetings', () => {
517
635
  assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
518
636
  assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
519
637
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
638
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
639
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
520
640
  assert.isFalse(results);
521
641
  });
522
642
  });
@@ -144,7 +144,25 @@ describe('plugin-meetings', () => {
144
144
  assert.equal(parsedControls.videoLayout.overrideDefault, newControls.videoLayout.overrideDefault);
145
145
  assert.equal(parsedControls.videoLayout.lockAttendeeViewOnStageOnly, newControls.videoLayout.lockAttendeeViewOnStageOnly);
146
146
  assert.equal(parsedControls.videoLayout.stageParameters, newControls.videoLayout.stageParameters);
147
+ });
148
+
149
+ it('should parse the annotationControl control', () => {
150
+ const newControls = {annotationControl: {enabled: true}};
151
+
152
+ const parsedControls = ControlsUtils.parse(newControls);
147
153
 
154
+ assert.equal(
155
+ parsedControls.annotationControl.enabled,
156
+ newControls.annotationControl.enabled
157
+ );
158
+ });
159
+
160
+ it('should parse the rdcControl control', () => {
161
+ const newControls = {rdcControl: {enabled: true}};
162
+
163
+ const parsedControls = ControlsUtils.parse(newControls);
164
+
165
+ assert.equal(parsedControls.rdcControl.enabled, newControls.rdcControl.enabled);
148
166
  });
149
167
 
150
168
  describe('videoEnabled', () => {
@@ -377,6 +395,22 @@ describe('plugin-meetings', () => {
377
395
  assert.equal(updates.hasManualCaptionChanged, false);
378
396
  });
379
397
 
398
+ it('returns hasAnnotationControlChanged = true when changed', () => {
399
+ const newControls = {annotationControl: {enabled: true}};
400
+
401
+ const {updates} = ControlsUtils.getControls(defaultControls, newControls);
402
+
403
+ assert.equal(updates.hasAnnotationControlChanged, true);
404
+ });
405
+
406
+ it('returns hasRemoteDesktopControlChanged = true when changed', () => {
407
+ const newControls = {rdcControl: {enabled: true}};
408
+
409
+ const {updates} = ControlsUtils.getControls(defaultControls, newControls);
410
+
411
+ assert.equal(updates.hasRemoteDesktopControlChanged, true);
412
+ });
413
+
380
414
  describe('videoEnabled', () => {
381
415
  const testVideoEnabled = (oldControls, newControls, updatedProperty) => {
382
416
  const result = ControlsUtils.getControls(oldControls, newControls);
@@ -464,31 +498,31 @@ describe('plugin-meetings', () => {
464
498
  self: { isCreator: true },
465
499
  controls: { breakout: { sessionType: BREAKOUTS.SESSION_TYPES.MAIN} },
466
500
  };
467
-
501
+
468
502
  const newLocus = {
469
503
  participants: [
470
- { isCreator: true, state: MEETING_STATE.STATES.JOINED },
504
+ { isCreator: true, state: MEETING_STATE.STATES.JOINED },
471
505
  ],
472
506
  controls: {
473
507
  breakout: {
474
- sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
475
- groups: [{ id: 'group1' }]
508
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
509
+ groups: [{ id: 'group1' }]
476
510
  },
477
511
  },
478
512
  };
479
-
513
+
480
514
  assert.deepEqual(controlsUtils.getSessionSwitchStatus(oldLocus, newLocus), {
481
- isReturnToMain: true,
515
+ isReturnToMain: true,
482
516
  isJoinToBreakout: false
483
517
  });
484
518
  });
485
-
519
+
486
520
  it('if needUseCache conditions are not met, return newLocus and isReturnToMain as false', () => {
487
521
  const oldLocus = {
488
- self: { isCreator: false },
522
+ self: { isCreator: false },
489
523
  controls: { breakout: { sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT} },
490
524
  };
491
-
525
+
492
526
  const newLocus = {
493
527
  participants: [
494
528
  { isCreator: true, state: MEETING_STATE.STATES.JOINED },
@@ -496,13 +530,13 @@ describe('plugin-meetings', () => {
496
530
  controls: {
497
531
  breakout: {
498
532
  sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
499
- groups: []
533
+ groups: []
500
534
  },
501
535
  },
502
536
  };
503
-
537
+
504
538
  assert.deepEqual(controlsUtils.getSessionSwitchStatus(oldLocus, newLocus), {
505
- isReturnToMain: false,
539
+ isReturnToMain: false,
506
540
  isJoinToBreakout: false
507
541
  });
508
542
  });
@@ -111,6 +111,8 @@ describe('plugin-meetings', () => {
111
111
  },
112
112
  webcastControl: {streaming: false},
113
113
  practiceSession: {enabled: true},
114
+ annotationControl: {enabled: true},
115
+ rdcControl: {enabled: true},
114
116
  };
115
117
  });
116
118
 
@@ -278,6 +280,32 @@ describe('plugin-meetings', () => {
278
280
  });
279
281
  });
280
282
 
283
+ it('should trigger the CONTROLS_ANNOTATION_CHANGED event when necessary', () => {
284
+ locusInfo.controls = {};
285
+ locusInfo.emitScoped = sinon.stub();
286
+ locusInfo.updateControls(newControls);
287
+
288
+ assert.calledWith(
289
+ locusInfo.emitScoped,
290
+ {file: 'locus-info', function: 'updateControls'},
291
+ LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED,
292
+ {state: newControls.annotationControl}
293
+ );
294
+ });
295
+
296
+ it('should trigger the CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED event when necessary', () => {
297
+ locusInfo.controls = {};
298
+ locusInfo.emitScoped = sinon.stub();
299
+ locusInfo.updateControls(newControls);
300
+
301
+ assert.calledWith(
302
+ locusInfo.emitScoped,
303
+ {file: 'locus-info', function: 'updateControls'},
304
+ LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED,
305
+ {state: newControls.rdcControl}
306
+ );
307
+ });
308
+
281
309
  it('should keep the recording state to `IDLE`', () => {
282
310
  locusInfo.controls = {
283
311
  record: {
@@ -94,6 +94,10 @@ describe('plugin-meetings', () => {
94
94
  isPracticeSessionOff : null,
95
95
  canStartPracticeSession: null,
96
96
  canStopPracticeSession: null,
97
+ canEnableAnnotation: null,
98
+ canDisableAnnotation: null,
99
+ canEnableRemoteDesktopControl: null,
100
+ canDisableRemoteDesktopControl: null,
97
101
 
98
102
  ...expected,
99
103
  };
@@ -194,7 +198,10 @@ describe('plugin-meetings', () => {
194
198
  'isPracticeSessionOff',
195
199
  'canStartPracticeSession',
196
200
  'canStopPracticeSession',
197
-
201
+ 'canEnableAnnotation',
202
+ 'canDisableAnnotation',
203
+ 'canEnableRemoteDesktopControl',
204
+ 'canDisableRemoteDesktopControl',
198
205
  ].forEach((key) => {
199
206
  it(`get and set for ${key} work as expected`, () => {
200
207
  const inMeetingActions = new InMeetingActions();
@@ -9791,6 +9791,42 @@ describe('plugin-meetings', () => {
9791
9791
  );
9792
9792
  });
9793
9793
 
9794
+ it('listens to CONTROLS_ANNOTATION_CHANGED', async () => {
9795
+ const state = {example: 'value'};
9796
+
9797
+ await meeting.locusInfo.emitScoped(
9798
+ {function: 'test', file: 'test'},
9799
+ LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED,
9800
+ {state}
9801
+ );
9802
+
9803
+ assert.calledWith(
9804
+ TriggerProxy.trigger,
9805
+ meeting,
9806
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
9807
+ EVENT_TRIGGERS.MEETING_CONTROLS_ANNOTATION_UPDATED,
9808
+ {state}
9809
+ );
9810
+ });
9811
+
9812
+ it('listens to CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED', async () => {
9813
+ const state = {example: 'value'};
9814
+
9815
+ await meeting.locusInfo.emitScoped(
9816
+ {function: 'test', file: 'test'},
9817
+ LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED,
9818
+ {state}
9819
+ );
9820
+
9821
+ assert.calledWith(
9822
+ TriggerProxy.trigger,
9823
+ meeting,
9824
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
9825
+ EVENT_TRIGGERS.MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED,
9826
+ {state}
9827
+ );
9828
+ });
9829
+
9794
9830
  it('listens to the locus interpretation update event', () => {
9795
9831
  const interpretation = {
9796
9832
  siLanguages: [{languageCode: 20, languageName: 'en'}],
@@ -11348,6 +11384,22 @@ describe('plugin-meetings', () => {
11348
11384
  requiredPolicies: [SELF_POLICY.SUPPORT_VOIP],
11349
11385
  policies: selfUserPolicies,
11350
11386
  });
11387
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
11388
+ requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
11389
+ displayHints: userDisplayHints,
11390
+ });
11391
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
11392
+ requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
11393
+ displayHints: userDisplayHints,
11394
+ });
11395
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
11396
+ requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
11397
+ displayHints: userDisplayHints,
11398
+ });
11399
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
11400
+ requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
11401
+ displayHints: userDisplayHints,
11402
+ });
11351
11403
 
11352
11404
  assert.calledWith(
11353
11405
  TriggerProxy.trigger,
@@ -777,6 +777,10 @@ describe('plugin-meetings', () => {
777
777
  }),
778
778
  false
779
779
  );
780
+ assert.deepEqual(
781
+ MeetingUtil.canShareWhiteBoard(['SHARE_WHITEBOARD'], undefined),
782
+ false
783
+ );
780
784
  });
781
785
  });
782
786