@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.
- package/README.md +17 -6
- package/dist/constants.js +12 -10
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/index.js +6 -2
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +54 -19
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/selfUtils.js +18 -5
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +32 -26
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +18 -39
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +24 -26
- package/dist/meeting/util.js.map +1 -1
- package/dist/metrics/index.js +3 -2
- package/dist/metrics/index.js.map +1 -1
- package/package.json +6 -6
- package/src/constants.js +9 -7
- package/src/locus-info/index.js +4 -4
- package/src/locus-info/infoUtils.js +30 -22
- package/src/locus-info/selfUtils.js +10 -1
- package/src/meeting/in-meeting-actions.js +25 -16
- package/src/meeting/index.js +25 -48
- package/src/meeting/util.js +18 -29
- package/src/metrics/index.js +3 -2
- package/test/unit/spec/locus-info/index.js +87 -1
- package/test/unit/spec/locus-info/infoUtils.js +122 -0
- package/test/unit/spec/locus-info/selfUtils.js +43 -0
- package/test/unit/spec/meeting/in-meeting-actions.js +55 -0
- package/test/unit/spec/meeting/index.js +120 -0
- package/test/unit/spec/meeting/utils.js +187 -0
- package/test/unit/spec/metrics/index.js +2 -2
|
@@ -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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (info && info.displayHints && info.displayHints
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
45
|
+
return displayHints;
|
|
32
46
|
};
|
|
33
47
|
|
|
34
|
-
InfoUtils.
|
|
35
|
-
const moderator = {};
|
|
48
|
+
InfoUtils.parsePolicy = (info) => InfoUtils.parseDisplayHintSection(info, 'joined');
|
|
36
49
|
|
|
37
|
-
|
|
38
|
-
info.displayHints.moderator.forEach((key) => {
|
|
39
|
-
moderator[key] = true;
|
|
40
|
-
});
|
|
41
|
-
}
|
|
50
|
+
InfoUtils.parseModerator = (info) => InfoUtils.parseDisplayHintSection(info, 'moderator');
|
|
42
51
|
|
|
43
|
-
|
|
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
|
-
|
|
22
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
37
|
+
set(actions) {
|
|
38
|
+
const old = this.get();
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
this.canAssignHost = host;
|
|
31
|
-
}
|
|
40
|
+
let changed = false;
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
42
|
+
Object.keys(old).forEach((actionKey) => {
|
|
43
|
+
const actionValue = actions[actionKey];
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
if (actionValue !== undefined && actionValue !== old[actionKey]) {
|
|
46
|
+
changed = true;
|
|
47
|
+
this[actionKey] = actionValue;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
40
50
|
|
|
41
|
-
|
|
42
|
-
return this.canAssignHost;
|
|
51
|
+
return changed;
|
|
43
52
|
}
|
|
44
53
|
}
|
|
45
54
|
|
package/src/meeting/index.js
CHANGED
|
@@ -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
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
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
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
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 (
|
|
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
|
}
|
package/src/meeting/util.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
|
|
397
|
-
};
|
|
392
|
+
MeetingUtil.canUserLock = (displayHints) => displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) && displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED);
|
|
398
393
|
|
|
399
|
-
MeetingUtil.canUserUnlock = (
|
|
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 = (
|
|
396
|
+
MeetingUtil.canUserRecord = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START);
|
|
408
397
|
|
|
409
|
-
MeetingUtil.canUserPause = (
|
|
398
|
+
MeetingUtil.canUserPause = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE);
|
|
410
399
|
|
|
411
|
-
MeetingUtil.canUserResume = (
|
|
400
|
+
MeetingUtil.canUserResume = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME);
|
|
412
401
|
|
|
413
|
-
MeetingUtil.canUserStop = (
|
|
402
|
+
MeetingUtil.canUserStop = (displayHints) => displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP);
|
|
414
403
|
|
|
415
404
|
MeetingUtil.startRecording = (request, locusUrl, locusInfo) => {
|
|
416
|
-
const
|
|
405
|
+
const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
|
|
417
406
|
|
|
418
|
-
if (
|
|
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
|
|
415
|
+
const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
|
|
427
416
|
|
|
428
|
-
if (
|
|
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
|
|
425
|
+
const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
|
|
437
426
|
|
|
438
|
-
if (
|
|
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
|
|
435
|
+
const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
|
|
447
436
|
|
|
448
|
-
if (
|
|
437
|
+
if (MeetingUtil.canUserStop(displayHints)) {
|
|
449
438
|
return request.recordMeeting({locusUrl, recording: false, paused: false});
|
|
450
439
|
}
|
|
451
440
|
|
package/src/metrics/index.js
CHANGED
|
@@ -33,8 +33,9 @@ const {
|
|
|
33
33
|
getBrowserVersion
|
|
34
34
|
} = BrowserDetection();
|
|
35
35
|
|
|
36
|
-
// Apply a CIDR /28 format to the
|
|
37
|
-
|
|
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
|
+
});
|