@webex/plugin-meetings 2.2.2 → 2.3.0

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.
@@ -1,12 +1,27 @@
1
1
 
2
+ import {SELF_ROLES} from '../constants';
3
+
2
4
  const InfoUtils = {};
3
5
 
4
- InfoUtils.parse = (info) => {
6
+ InfoUtils.parse = (info, roles) => {
5
7
  const parsed = {
6
8
  policy: InfoUtils.parsePolicy(info),
7
- moderator: InfoUtils.parseModerator(info)
9
+ moderator: InfoUtils.parseModerator(info),
10
+ coHost: InfoUtils.parseCoHost(info),
8
11
  };
9
12
 
13
+ let userDisplayHints = {...parsed.policy};
14
+
15
+ if (roles.includes(SELF_ROLES.COHOST)) {
16
+ userDisplayHints = {...userDisplayHints, ...parsed.coHost};
17
+ }
18
+
19
+ if (roles.includes(SELF_ROLES.MODERATOR)) {
20
+ userDisplayHints = {...userDisplayHints, ...parsed.moderator};
21
+ }
22
+
23
+ parsed.userDisplayHints = Object.keys(userDisplayHints);
24
+
10
25
  if (info.sipUri) {
11
26
  parsed.sipUri = info.sipUri;
12
27
  }
@@ -17,43 +32,36 @@ InfoUtils.parse = (info) => {
17
32
 
18
33
  return parsed;
19
34
  };
20
- InfoUtils.parsePolicy = (info) => {
21
- const policy = {};
22
-
23
- // Parses the policy to show valid uses
24
- if (info && info.displayHints && info.displayHints.joined && info.displayHints.joined.length > 0) {
25
- // TODO: find a better way
26
- info.displayHints.joined.forEach((key) => {
27
- policy[key] = true;
35
+
36
+ InfoUtils.parseDisplayHintSection = (info, displayHintKey) => {
37
+ const displayHints = {};
38
+
39
+ if (info && info.displayHints && info.displayHints[displayHintKey] && info.displayHints[displayHintKey].length > 0) {
40
+ info.displayHints[displayHintKey].forEach((key) => {
41
+ displayHints[key] = true;
28
42
  });
29
43
  }
30
44
 
31
- return policy;
45
+ return displayHints;
32
46
  };
33
47
 
34
- InfoUtils.parseModerator = (info) => {
35
- const moderator = {};
48
+ InfoUtils.parsePolicy = (info) => InfoUtils.parseDisplayHintSection(info, 'joined');
36
49
 
37
- if (info && info.displayHints && info.displayHints.moderator && info.displayHints.moderator.length > 0) {
38
- info.displayHints.moderator.forEach((key) => {
39
- moderator[key] = true;
40
- });
41
- }
50
+ InfoUtils.parseModerator = (info) => InfoUtils.parseDisplayHintSection(info, 'moderator');
42
51
 
43
- return moderator;
44
- };
52
+ InfoUtils.parseCoHost = (info) => InfoUtils.parseDisplayHintSection(info, 'coHost');
45
53
 
46
54
  InfoUtils.isLocked = (policy) => policy.LOCK_STATUS_LOCKED || false;
47
55
 
48
56
  InfoUtils.isUnlocked = (policy) => policy.LOCK_STATUS_UNLOCKED || false;
49
57
 
50
- InfoUtils.getInfos = (oldInfo, newInfo) => {
58
+ InfoUtils.getInfos = (oldInfo, newInfo, roles) => {
51
59
  let previous = null;
52
60
 
53
61
  if (oldInfo) {
54
62
  previous = oldInfo;
55
63
  }
56
- const current = newInfo && InfoUtils.parse(newInfo);
64
+ const current = newInfo && InfoUtils.parse(newInfo, roles);
57
65
  const updates = {};
58
66
 
59
67
  if (current) {
@@ -53,13 +53,22 @@ SelfUtils.parse = (self, deviceId) => {
53
53
  selfId: self.id,
54
54
  selfIdentity: SelfUtils.getSelfIdentity(self),
55
55
  selfUrl: self.url,
56
- removed: self.removed
56
+ removed: self.removed,
57
+ roles: SelfUtils.getRoles(self)
57
58
  };
58
59
  }
59
60
 
60
61
  return null;
61
62
  };
62
63
 
64
+ SelfUtils.getRoles = (self) => (self?.controls?.role?.roles || []).reduce((roles, role) => {
65
+ if (role.hasRole) {
66
+ roles.push(role.type);
67
+ }
68
+
69
+ return roles;
70
+ }, []);
71
+
63
72
  SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
64
73
  const previous = oldSelf && SelfUtils.parse(oldSelf, deviceId);
65
74
  const current = newSelf && SelfUtils.parse(newSelf, deviceId);
@@ -16,30 +16,39 @@ export default class InMeetingActions {
16
16
  this.canLock = null;
17
17
  this.canUnlock = null;
18
18
  this.canAssignHost = null;
19
+ this.canStartRecording = null;
20
+ this.canPauseRecording = null;
21
+ this.canResumeRecording = null;
22
+ this.canStopRecording = null;
19
23
  }
20
24
 
21
- setCanLock(lock) {
22
- this.canLock = lock;
25
+ get() {
26
+ return {
27
+ canLock: this.canLock,
28
+ canUnlock: this.canUnlock,
29
+ canAssignHost: this.canAssignHost,
30
+ canStartRecording: this.canStartRecording,
31
+ canPauseRecording: this.canPauseRecording,
32
+ canResumeRecording: this.canResumeRecording,
33
+ canStopRecording: this.canStopRecording
34
+ };
23
35
  }
24
36
 
25
- setCanUnlock(unlock) {
26
- this.canUnlock = unlock;
27
- }
37
+ set(actions) {
38
+ const old = this.get();
28
39
 
29
- setCanAssignHost(host) {
30
- this.canAssignHost = host;
31
- }
40
+ let changed = false;
32
41
 
33
- getCanLock() {
34
- return this.canLock;
35
- }
42
+ Object.keys(old).forEach((actionKey) => {
43
+ const actionValue = actions[actionKey];
36
44
 
37
- getCanUnlock() {
38
- return this.canUnlock;
39
- }
45
+ if (actionValue !== undefined && actionValue !== old[actionKey]) {
46
+ changed = true;
47
+ this[actionKey] = actionValue;
48
+ }
49
+ });
40
50
 
41
- getCanAssignHost() {
42
- return this.canAssignHost;
51
+ return changed;
43
52
  }
44
53
  }
45
54
 
@@ -1144,20 +1144,21 @@ export default class Meeting extends StatelessWebexPlugin {
1144
1144
  */
1145
1145
  setUpLocusInfoAssignHostListener() {
1146
1146
  this.locusInfo.on(EVENTS.LOCUS_INFO_CAN_ASSIGN_HOST, (payload) => {
1147
- Trigger.trigger(
1148
- this,
1149
- {
1150
- file: 'meeting/index',
1151
- function: 'setUpLocusInfoAssignHostListener'
1152
- },
1153
- EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
1154
- {
1155
- canAssignHost: payload.canAssignHost,
1156
- canLock: this.inMeetingActions.getCanLock(),
1157
- canUnlock: this.inMeetingActions.getCanUnlock()
1158
- }
1159
- );
1160
- this.inMeetingActions.setCanAssignHost(payload.canAssignHost);
1147
+ const changed = this.inMeetingActions.set({
1148
+ canAssignHost: payload.canAssignHost,
1149
+ });
1150
+
1151
+ if (changed) {
1152
+ Trigger.trigger(
1153
+ this,
1154
+ {
1155
+ file: 'meeting/index',
1156
+ function: 'setUpLocusInfoAssignHostListener'
1157
+ },
1158
+ EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
1159
+ this.inMeetingActions.get()
1160
+ );
1161
+ }
1161
1162
  });
1162
1163
  }
1163
1164
 
@@ -1862,34 +1863,16 @@ export default class Meeting extends StatelessWebexPlugin {
1862
1863
  });
1863
1864
  this.locusInfo.on(LOCUSINFO.EVENTS.MEETING_INFO_UPDATED, (payload) => {
1864
1865
  if (payload && payload.info) {
1865
- let newCanLock;
1866
- let newCanUnlock;
1867
-
1868
- if (payload.self && !payload.self.moderator) {
1869
- newCanLock = false;
1870
- newCanUnlock = false;
1871
- }
1872
- else {
1873
- newCanLock = MeetingUtil.canUserLock(payload.info.moderator, payload.info.policy);
1874
- newCanUnlock = MeetingUtil.canUserUnlock(payload.info.moderator, payload.info.policy);
1875
- }
1866
+ const changed = this.inMeetingActions.set({
1867
+ canLock: MeetingUtil.canUserLock(payload.info.userDisplayHints),
1868
+ canUnlock: MeetingUtil.canUserUnlock(payload.info.userDisplayHints),
1869
+ canStartRecording: MeetingUtil.canUserRecord(payload.info.userDisplayHints),
1870
+ canStopRecording: MeetingUtil.canUserStop(payload.info.userDisplayHints),
1871
+ canPauseRecording: MeetingUtil.canUserPause(payload.info.userDisplayHints),
1872
+ canResumeRecording: MeetingUtil.canUserResume(payload.info.userDisplayHints)
1873
+ });
1876
1874
 
1877
- if (newCanLock && !this.inMeetingActions.canLock) {
1878
- Trigger.trigger(
1879
- this,
1880
- {
1881
- file: 'meeting/index',
1882
- function: 'setUpLocusInfoMeetingInfoListener'
1883
- },
1884
- EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
1885
- {
1886
- canLock: true,
1887
- canUnlock: false,
1888
- canAssignHost: this.inMeetingActions.getCanAssignHost()
1889
- }
1890
- );
1891
- }
1892
- if (newCanUnlock && !this.inMeetingActions.canUnlock || !newCanLock) {
1875
+ if (changed) {
1893
1876
  Trigger.trigger(
1894
1877
  this,
1895
1878
  {
@@ -1897,15 +1880,9 @@ export default class Meeting extends StatelessWebexPlugin {
1897
1880
  function: 'setUpLocusInfoMeetingInfoListener'
1898
1881
  },
1899
1882
  EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
1900
- {
1901
- canLock: false,
1902
- canUnlock: true,
1903
- canAssignHost: this.inMeetingActions.getCanAssignHost()
1904
- }
1883
+ this.inMeetingActions.get()
1905
1884
  );
1906
1885
  }
1907
- this.inMeetingActions.setCanLock(newCanLock || false);
1908
- this.inMeetingActions.setCanUnlock(newCanUnlock || false);
1909
1886
  }
1910
1887
  });
1911
1888
  }
@@ -7,16 +7,15 @@ import {eventType, trigger, mediaType} from '../metrics/config';
7
7
  import Media from '../media';
8
8
  import LoggerProxy from '../common/logs/logger-proxy';
9
9
  import WebRTCStats from '../stats/index';
10
- import {
11
- INTENT_TO_JOIN,
10
+ import {INTENT_TO_JOIN,
12
11
  _LEFT_,
13
12
  _IDLE_,
14
13
  _JOINED_,
15
14
  STATS,
16
15
  EVENT_TRIGGERS,
17
- FULL_STATE,
18
16
  PASSWORD_STATUS,
19
- } from '../constants';
17
+ DISPLAY_HINTS,
18
+ FULL_STATE} from '../constants';
20
19
  import Trigger from '../common/events/trigger-proxy';
21
20
  import IntentToJoinError from '../common/errors/intent-to-join';
22
21
  import JoinMeetingError from '../common/errors/join-meeting';
@@ -388,34 +387,24 @@ MeetingUtil.getPolicyFromLocusInfo = (locusInfo) =>
388
387
  locusInfo.parsedLocus.info &&
389
388
  locusInfo.parsedLocus.info.policy;
390
389
 
391
- MeetingUtil.canUserLock = (moderator, joined) => {
392
- if (moderator.LOCK_CONTROL_LOCK && joined.LOCK_STATUS_UNLOCKED) {
393
- return true;
394
- }
390
+ MeetingUtil.getUserDisplayHintsFromLocusInfo = (locusInfo) => locusInfo?.parsedLocus?.info?.userDisplayHints || [];
395
391
 
396
- return false;
397
- };
392
+ MeetingUtil.canUserLock = (displayHints) => displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) && displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED);
398
393
 
399
- MeetingUtil.canUserUnlock = (moderator, joined) => {
400
- if (moderator.LOCK_CONTROL_UNLOCK && joined.LOCK_STATUS_LOCKED) {
401
- return true;
402
- }
403
-
404
- return false;
405
- };
394
+ MeetingUtil.canUserUnlock = (displayHints) => displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_UNLOCK) && displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_LOCKED);
406
395
 
407
- MeetingUtil.canUserRecord = (moderator) => moderator.RECORDING_CONTROL_START;
396
+ MeetingUtil.canUserRecord = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START);
408
397
 
409
- MeetingUtil.canUserPause = (moderator) => moderator.RECORDING_CONTROL_PAUSE;
398
+ MeetingUtil.canUserPause = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE);
410
399
 
411
- MeetingUtil.canUserResume = (moderator) => moderator.RECORDING_CONTROL_RESUME;
400
+ MeetingUtil.canUserResume = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME);
412
401
 
413
- MeetingUtil.canUserStop = (moderator) => moderator.RECORDING_CONTROL_STOP;
402
+ MeetingUtil.canUserStop = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP);
414
403
 
415
404
  MeetingUtil.startRecording = (request, locusUrl, locusInfo) => {
416
- const moderator = MeetingUtil.getModeratorFromLocusInfo(locusInfo);
405
+ const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
417
406
 
418
- if (moderator && MeetingUtil.canUserRecord(moderator)) {
407
+ if (MeetingUtil.canUserRecord(displayHints)) {
419
408
  return request.recordMeeting({locusUrl, recording: true, paused: false});
420
409
  }
421
410
 
@@ -423,9 +412,9 @@ MeetingUtil.startRecording = (request, locusUrl, locusInfo) => {
423
412
  };
424
413
 
425
414
  MeetingUtil.pauseRecording = (request, locusUrl, locusInfo) => {
426
- const moderator = MeetingUtil.getModeratorFromLocusInfo(locusInfo);
415
+ const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
427
416
 
428
- if (moderator && MeetingUtil.canUserPause(moderator)) {
417
+ if (MeetingUtil.canUserPause(displayHints)) {
429
418
  return request.recordMeeting({locusUrl, recording: true, paused: true});
430
419
  }
431
420
 
@@ -433,9 +422,9 @@ MeetingUtil.pauseRecording = (request, locusUrl, locusInfo) => {
433
422
  };
434
423
 
435
424
  MeetingUtil.resumeRecording = (request, locusUrl, locusInfo) => {
436
- const moderator = MeetingUtil.getModeratorFromLocusInfo(locusInfo);
425
+ const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
437
426
 
438
- if (moderator && MeetingUtil.canUserResume(moderator)) {
427
+ if (MeetingUtil.canUserResume(displayHints)) {
439
428
  return request.recordMeeting({locusUrl, recording: true, paused: false});
440
429
  }
441
430
 
@@ -443,9 +432,9 @@ MeetingUtil.resumeRecording = (request, locusUrl, locusInfo) => {
443
432
  };
444
433
 
445
434
  MeetingUtil.stopRecording = (request, locusUrl, locusInfo) => {
446
- const moderator = MeetingUtil.getModeratorFromLocusInfo(locusInfo);
435
+ const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
447
436
 
448
- if (moderator && MeetingUtil.canUserStop(moderator)) {
437
+ if (MeetingUtil.canUserStop(displayHints)) {
449
438
  return request.recordMeeting({locusUrl, recording: false, paused: false});
450
439
  }
451
440
 
@@ -33,8 +33,9 @@ const {
33
33
  getBrowserVersion
34
34
  } = BrowserDetection();
35
35
 
36
- // Apply a CIDR /28 format to the IP address
37
- const anonymizeIPAddress = (localIp) => anonymize(localIp);
36
+ // Apply a CIDR /28 format to the IPV4 and /96 to the IPV6 addresses
37
+ // For reference : https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
38
+ const anonymizeIPAddress = (localIp) => anonymize(localIp, 28, 96);
38
39
 
39
40
  const triggerTimers = ({event, meeting, data}) => {
40
41
  switch (event) {
@@ -7,13 +7,15 @@ import MockWebex from '@webex/test-helper-mock-webex';
7
7
  import Meetings from '@webex/plugin-meetings';
8
8
  import LocusInfo from '@webex/plugin-meetings/src/locus-info';
9
9
  import SelfUtils from '@webex/plugin-meetings/src/locus-info/selfUtils';
10
+ import InfoUtils from '@webex/plugin-meetings/src/locus-info/infoUtils';
10
11
  import LocusDeltaParser from '@webex/plugin-meetings/src/locus-info/parser';
11
12
 
12
13
  import {
13
14
  LOCUSINFO,
14
15
  RECORDING_STATE,
15
16
  LOCUSEVENT,
16
- EVENTS
17
+ EVENTS,
18
+ DISPLAY_HINTS
17
19
  } from '../../../../src/constants';
18
20
 
19
21
  import {self, selfWithInactivity} from './selfConstant';
@@ -587,6 +589,8 @@ describe('plugin-meetings', () => {
587
589
 
588
590
  describe('#updateMeetingInfo', () => {
589
591
  let meetingInfo;
592
+ let getInfosSpy;
593
+ let getRolesSpy;
590
594
 
591
595
  beforeEach('setup meeting info', () => {
592
596
  meetingInfo = {
@@ -595,8 +599,14 @@ describe('plugin-meetings', () => {
595
599
  moderator: []
596
600
  }
597
601
  };
602
+ getInfosSpy = sinon.spy(InfoUtils, 'getInfos');
603
+ getRolesSpy = sinon.spy(SelfUtils, 'getRoles');
598
604
  });
599
605
 
606
+ afterEach(() => {
607
+ getRolesSpy.restore();
608
+ getInfosSpy.restore();
609
+ });
600
610
 
601
611
  it('should trigger MEETING_LOCKED/UNLOCKED when meeting gets locked/unlocked', () => {
602
612
  const meetingInfoLocked = cloneDeep(meetingInfo);
@@ -630,6 +640,82 @@ describe('plugin-meetings', () => {
630
640
  LOCUSINFO.EVENTS.MEETING_UNLOCKED,
631
641
  meetingInfoUnlocked);
632
642
  });
643
+
644
+ const checkMeetingInfoUpdatedCalled = (expected) => {
645
+ const expectedArgs = [locusInfo.emitScoped, {
646
+ file: 'locus-info',
647
+ function: 'updateMeetingInfo'
648
+ },
649
+ LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
650
+ {info: locusInfo.parsedLocus.info, self}];
651
+
652
+ if (expected) {
653
+ assert.calledWith(...expectedArgs);
654
+ }
655
+ else {
656
+ assert.neverCalledWith(...expectedArgs);
657
+ }
658
+ locusInfo.emitScoped.resetHistory();
659
+ };
660
+
661
+ it('emits MEETING_INFO_UPDATED if the info changes', () => {
662
+ const initialInfo = cloneDeep(meetingInfo);
663
+
664
+ locusInfo.emitScoped = sinon.stub();
665
+
666
+ // set the info initially as locusInfo.info starts as undefined
667
+ locusInfo.updateMeetingInfo(initialInfo, self);
668
+
669
+ // since it was initially undefined, this should trigger the event
670
+ checkMeetingInfoUpdatedCalled(true);
671
+
672
+ const newInfo = cloneDeep(meetingInfo);
673
+
674
+ newInfo.displayHints.coHost = [DISPLAY_HINTS.LOCK_CONTROL_LOCK];
675
+
676
+ // Updating with different info should trigger the event
677
+ locusInfo.updateMeetingInfo(newInfo, self);
678
+
679
+ checkMeetingInfoUpdatedCalled(true);
680
+
681
+ // update it with the same info
682
+ locusInfo.updateMeetingInfo(newInfo, self);
683
+
684
+ // since the info is the same it should not call trigger the event
685
+ checkMeetingInfoUpdatedCalled(false);
686
+ });
687
+
688
+ it('gets roles from self if available', () => {
689
+ const initialInfo = cloneDeep(meetingInfo);
690
+
691
+ const parsedLocusInfo = cloneDeep(locusInfo.parsedLocus.info);
692
+
693
+ locusInfo.updateMeetingInfo(initialInfo, self);
694
+
695
+ assert.calledWith(getRolesSpy, self);
696
+ assert.calledWith(
697
+ getInfosSpy,
698
+ parsedLocusInfo, initialInfo, ['PRESENTER']
699
+ );
700
+ });
701
+
702
+ it('gets roles from parsedLocus if self not passed in', () => {
703
+ const initialInfo = cloneDeep(meetingInfo);
704
+
705
+ locusInfo.parsedLocus.self = {
706
+ roles: ['MODERATOR', 'COHOST']
707
+ };
708
+
709
+ const parsedLocusInfo = cloneDeep(locusInfo.parsedLocus.info);
710
+
711
+ locusInfo.updateMeetingInfo(initialInfo);
712
+
713
+ assert.neverCalledWith(getRolesSpy, self);
714
+ assert.calledWith(
715
+ getInfosSpy,
716
+ parsedLocusInfo, initialInfo, ['MODERATOR', 'COHOST']
717
+ );
718
+ });
633
719
  });
634
720
 
635
721
  describe('#LocusDeltaEvents', () => {
@@ -0,0 +1,122 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import Sinon from 'sinon';
3
+
4
+ import InfoUtils from '@webex/plugin-meetings/src/locus-info/infoUtils';
5
+
6
+
7
+ describe('plugin-meetings', () => {
8
+ describe('infoUtils', () => {
9
+ const info = {
10
+ displayHints: {
11
+ moderator: [
12
+ 'HINT_1',
13
+ 'HINT_2'
14
+ ],
15
+ joined: ['HINT_3'],
16
+ coHost: ['HINT_4']
17
+ }
18
+ };
19
+
20
+ describe('getInfos', () => {
21
+ it('passes roles to parse', () => {
22
+ const parseSpy = Sinon.spy(InfoUtils, 'parse');
23
+
24
+ const roles = ['COHOST', 'MODERATOR'];
25
+
26
+ InfoUtils.getInfos({}, info, roles);
27
+
28
+ assert.calledWith(parseSpy, info, roles);
29
+ });
30
+ });
31
+
32
+ describe('parse', () => {
33
+ it('only gives includes display hints when user has the correct role', () => {
34
+ assert.deepEqual(InfoUtils.parse(info, ['MODERATOR']), {
35
+ policy: {HINT_3: true},
36
+ moderator: {HINT_1: true, HINT_2: true},
37
+ coHost: {HINT_4: true},
38
+ userDisplayHints: ['HINT_3', 'HINT_1', 'HINT_2']
39
+ });
40
+
41
+ assert.deepEqual(InfoUtils.parse(info, ['COHOST']), {
42
+ policy: {HINT_3: true},
43
+ moderator: {HINT_1: true, HINT_2: true},
44
+ coHost: {HINT_4: true},
45
+ userDisplayHints: ['HINT_3', 'HINT_4']
46
+ });
47
+
48
+ assert.deepEqual(InfoUtils.parse(info, []), {
49
+ policy: {HINT_3: true},
50
+ moderator: {HINT_1: true, HINT_2: true},
51
+ coHost: {HINT_4: true},
52
+ userDisplayHints: ['HINT_3']
53
+ });
54
+ });
55
+ });
56
+
57
+ describe('parseDisplayHintsSection', () => {
58
+ it('returns the correct hints', () => {
59
+ assert.deepEqual(
60
+ InfoUtils.parseDisplayHintSection(info, 'moderator'),
61
+ {HINT_1: true, HINT_2: true}
62
+ );
63
+
64
+ assert.deepEqual(
65
+ InfoUtils.parseDisplayHintSection(info, 'joined'),
66
+ {HINT_3: true}
67
+ );
68
+
69
+ assert.deepEqual(
70
+ InfoUtils.parseDisplayHintSection({}, 'joined'),
71
+ {}
72
+ );
73
+
74
+ assert.deepEqual(
75
+ InfoUtils.parseDisplayHintSection({displayHints: {}}, 'joined'),
76
+ {}
77
+ );
78
+
79
+ assert.deepEqual(
80
+ InfoUtils.parseDisplayHintSection({displayHints: {joined: {}}}, 'joined'),
81
+ {}
82
+ );
83
+ });
84
+ });
85
+
86
+ describe('parse display hint tests', () => {
87
+ let parseDisplayHintSectionSpy;
88
+
89
+ beforeEach(() => {
90
+ parseDisplayHintSectionSpy = Sinon.spy(InfoUtils, 'parseDisplayHintSection');
91
+ });
92
+
93
+ afterEach(() => {
94
+ parseDisplayHintSectionSpy.restore();
95
+ });
96
+
97
+ it('parseModerator calls parseDisplayHintSection correctly and returns the result', () => {
98
+ const result = InfoUtils.parseModerator(info);
99
+
100
+ assert.calledWith(parseDisplayHintSectionSpy, info, 'moderator');
101
+
102
+ assert.deepEqual(result, parseDisplayHintSectionSpy.firstCall.returnValue);
103
+ });
104
+
105
+ it('parsePolicy calls parseDisplayHintSection correctly and returns the result', () => {
106
+ const result = InfoUtils.parsePolicy(info);
107
+
108
+ assert.calledWith(parseDisplayHintSectionSpy, info, 'joined');
109
+
110
+ assert.deepEqual(result, parseDisplayHintSectionSpy.firstCall.returnValue);
111
+ });
112
+
113
+ it('parseCoHost calls parseDisplayHintSection correctly and returns the result', () => {
114
+ const result = InfoUtils.parseCoHost(info);
115
+
116
+ assert.calledWith(parseDisplayHintSectionSpy, info, 'coHost');
117
+
118
+ assert.deepEqual(result, parseDisplayHintSectionSpy.firstCall.returnValue);
119
+ });
120
+ });
121
+ });
122
+ });
@@ -0,0 +1,43 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import Sinon from 'sinon';
3
+
4
+ import SelfUtils from '@webex/plugin-meetings/src/locus-info/selfUtils';
5
+
6
+ import {self} from './selfConstant';
7
+
8
+ describe('plugin-meetings', () => {
9
+ describe('selfUtils', () => {
10
+ describe('parse', () => {
11
+ it('parse calls getRoles and returns the resulting roles', () => {
12
+ const getRolesSpy = Sinon.spy(SelfUtils, 'getRoles');
13
+
14
+ const parsedSelf = SelfUtils.parse(self);
15
+
16
+ assert.calledWith(getRolesSpy, self);
17
+
18
+ assert.deepEqual(parsedSelf.roles, ['PRESENTER']);
19
+ });
20
+ });
21
+
22
+ describe('getRoles', () => {
23
+ it('get roles works', () => {
24
+ assert.deepEqual(SelfUtils.getRoles(self), ['PRESENTER']);
25
+
26
+ assert.deepEqual(SelfUtils.getRoles({
27
+ controls: {
28
+ role: {roles: [{type: 'SOME_ARBITRARY_ROLE', hasRole: true}]}
29
+ }
30
+ }), ['SOME_ARBITRARY_ROLE']);
31
+
32
+ assert.deepEqual(SelfUtils.getRoles({
33
+ controls: {
34
+ role: {roles: [{type: 'SOME_ARBITRARY_ROLE', hasRole: false}]}
35
+ }
36
+ }), []);
37
+
38
+ assert.deepEqual(SelfUtils.getRoles({}), []);
39
+ assert.deepEqual(SelfUtils.getRoles(), []);
40
+ });
41
+ });
42
+ });
43
+ });