@webex/plugin-meetings 3.0.0-beta.24 → 3.0.0-beta.26
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/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +5 -1
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js +14 -0
- package/dist/controls-options-manager/constants.js.map +1 -0
- package/dist/controls-options-manager/enums.js +15 -0
- package/dist/controls-options-manager/enums.js.map +1 -0
- package/dist/controls-options-manager/index.js +203 -0
- package/dist/controls-options-manager/index.js.map +1 -0
- package/dist/controls-options-manager/util.js +28 -0
- package/dist/controls-options-manager/util.js.map +1 -0
- package/dist/meeting/in-meeting-actions.js +8 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +59 -12
- package/dist/meeting/index.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +4 -3
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/types/constants.d.ts +4 -0
- package/dist/types/controls-options-manager/constants.d.ts +4 -0
- package/dist/types/controls-options-manager/enums.d.ts +5 -0
- package/dist/types/controls-options-manager/index.d.ts +120 -0
- package/dist/types/controls-options-manager/util.d.ts +7 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +8 -0
- package/dist/types/meeting/index.d.ts +18 -0
- package/package.json +19 -19
- package/src/constants.ts +4 -0
- package/src/controls-options-manager/constants.ts +5 -0
- package/src/controls-options-manager/enums.ts +6 -0
- package/src/controls-options-manager/index.ts +183 -0
- package/src/controls-options-manager/util.ts +20 -0
- package/src/meeting/in-meeting-actions.ts +16 -0
- package/src/meeting/index.ts +49 -0
- package/src/multistream/remoteMediaManager.ts +2 -2
- package/test/unit/spec/controls-options-manager/index.js +124 -0
- package/test/unit/spec/controls-options-manager/util.js +66 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +8 -0
- package/test/unit/spec/meeting/index.js +15 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import {camelCase} from 'lodash';
|
|
2
|
+
import PermissionError from '../common/errors/permission';
|
|
3
|
+
import {CONTROLS, HTTP_VERBS} from '../constants';
|
|
4
|
+
import MeetingRequest from '../meeting/request';
|
|
5
|
+
import LoggerProxy from '../common/logs/logger-proxy';
|
|
6
|
+
import Setting from './enums';
|
|
7
|
+
import Util from './util';
|
|
8
|
+
import {CAN_SET, CAN_UNSET, ENABLED} from './constants';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* docs
|
|
12
|
+
* https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html
|
|
13
|
+
* https://confluence-eng-gpk2.cisco.com/conf/display/LOCUS/Hard+Mute+and+Audio+Privacy#HardMuteandAudioPrivacy-SelfMuteonEntry
|
|
14
|
+
* https://confluence-eng-gpk2.cisco.com/conf/pages/viewpage.action?spaceKey=UC&title=WEBEX-124454%3A+UCF%3A+Hard+mute+support+for+Teams+joining+Webex+meeting
|
|
15
|
+
* https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-180867
|
|
16
|
+
* https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-393351
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @description ControlsOptionsManager is responsible for handling the behavior of participant controls when somebody joins a meeting
|
|
21
|
+
* @export
|
|
22
|
+
* @private
|
|
23
|
+
* @class Recording
|
|
24
|
+
*/
|
|
25
|
+
export default class ControlsOptionsManager {
|
|
26
|
+
/**
|
|
27
|
+
* @instance
|
|
28
|
+
* @type {MeetingRequest}
|
|
29
|
+
* @private
|
|
30
|
+
* @memberof ControlsOptionsManager
|
|
31
|
+
*/
|
|
32
|
+
private request: MeetingRequest;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @instance
|
|
36
|
+
* @type {Array}
|
|
37
|
+
* @private
|
|
38
|
+
* @memberof ControlsOptionsManager
|
|
39
|
+
*/
|
|
40
|
+
private displayHints: Array<string> = [];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @instance
|
|
44
|
+
* @type {string}
|
|
45
|
+
* @private
|
|
46
|
+
* @memberof ControlsOptionsManager
|
|
47
|
+
*/
|
|
48
|
+
private locusUrl: string;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {MeetingRequest} request
|
|
52
|
+
* @param {Object} options
|
|
53
|
+
* @constructor
|
|
54
|
+
* @memberof ControlsOptionsManager
|
|
55
|
+
*/
|
|
56
|
+
constructor(
|
|
57
|
+
request: MeetingRequest,
|
|
58
|
+
options?: {
|
|
59
|
+
locusUrl: string;
|
|
60
|
+
displayHints?: Array<string>;
|
|
61
|
+
}
|
|
62
|
+
) {
|
|
63
|
+
this.initialize(request);
|
|
64
|
+
this.set(options);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {MeetingRequest} request
|
|
69
|
+
* @returns {void}
|
|
70
|
+
* @private
|
|
71
|
+
* @memberof ControlsOptionsManager
|
|
72
|
+
*/
|
|
73
|
+
private initialize(request: MeetingRequest) {
|
|
74
|
+
this.request = request;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {Object} options
|
|
79
|
+
* @returns {void}
|
|
80
|
+
* @public
|
|
81
|
+
* @memberof ControlsOptionsManager
|
|
82
|
+
*/
|
|
83
|
+
public set(options?: {locusUrl: string; displayHints?: Array<string>}) {
|
|
84
|
+
this.extract(options);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {string} url
|
|
89
|
+
* @returns {void}
|
|
90
|
+
* @public
|
|
91
|
+
* @memberof ControlsOptionsManager
|
|
92
|
+
*/
|
|
93
|
+
public setLocusUrl(url: string) {
|
|
94
|
+
this.locusUrl = url;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {Array} hints
|
|
99
|
+
* @returns {void}
|
|
100
|
+
* @public
|
|
101
|
+
* @memberof ControlsOptionsManager
|
|
102
|
+
*/
|
|
103
|
+
public setDisplayHints(hints: Array<string>) {
|
|
104
|
+
this.displayHints = hints;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @returns {string}
|
|
109
|
+
* @public
|
|
110
|
+
* @memberof ControlsOptionsManager
|
|
111
|
+
*/
|
|
112
|
+
public getLocusUrl() {
|
|
113
|
+
return this.locusUrl;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @returns {Array}
|
|
118
|
+
* @public
|
|
119
|
+
* @memberof ControlsOptionsManager
|
|
120
|
+
*/
|
|
121
|
+
public getDisplayHints() {
|
|
122
|
+
return this.displayHints;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @param {Object} options
|
|
127
|
+
* @returns {void}
|
|
128
|
+
* @private
|
|
129
|
+
* @memberof ControlsOptionsManager
|
|
130
|
+
*/
|
|
131
|
+
private extract(options?: {locusUrl: string; displayHints?: Array<string>}) {
|
|
132
|
+
this.setDisplayHints(options?.displayHints);
|
|
133
|
+
this.setLocusUrl(options?.locusUrl);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @param {Setting} setting
|
|
138
|
+
* @param {boolean} enabled
|
|
139
|
+
* @private
|
|
140
|
+
* @memberof ControlsOptionsManager
|
|
141
|
+
* @returns {Promise}
|
|
142
|
+
*/
|
|
143
|
+
private setControls(setting: Setting, enabled: boolean): Promise<any> {
|
|
144
|
+
LoggerProxy.logger.log(`ControlsOptionsManager:index#setControls --> ${setting} [${enabled}]`);
|
|
145
|
+
|
|
146
|
+
if (Util?.[`${enabled ? CAN_SET : CAN_UNSET}${setting}`](this.displayHints)) {
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
return this.request.request({
|
|
149
|
+
uri: `${this.locusUrl}/${CONTROLS}`,
|
|
150
|
+
body: {
|
|
151
|
+
[camelCase(setting)]: {
|
|
152
|
+
[ENABLED]: enabled,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
method: HTTP_VERBS.PATCH,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return Promise.reject(
|
|
160
|
+
new PermissionError(`${setting} [${enabled}] not allowed, due to moderator property.`)
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @public
|
|
166
|
+
* @param {boolean} enabled
|
|
167
|
+
* @memberof ControlsOptionsManager
|
|
168
|
+
* @returns {Promise}
|
|
169
|
+
*/
|
|
170
|
+
public setMuteOnEntry(enabled: boolean): Promise<any> {
|
|
171
|
+
return this.setControls(Setting.muteOnEntry, enabled);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @public
|
|
176
|
+
* @param {boolean} enabled
|
|
177
|
+
* @memberof ControlsOptionsManager
|
|
178
|
+
* @returns {Promise}
|
|
179
|
+
*/
|
|
180
|
+
public setDisallowUnmute(enabled: boolean): Promise<any> {
|
|
181
|
+
return this.setControls(Setting.disallowUnmute, enabled);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {DISPLAY_HINTS} from '../constants';
|
|
2
|
+
|
|
3
|
+
const canSetMuteOnEntry = (displayHints: Array<string>): boolean =>
|
|
4
|
+
displayHints.includes(DISPLAY_HINTS.ENABLE_MUTE_ON_ENTRY);
|
|
5
|
+
|
|
6
|
+
const canSetDisallowUnmute = (displayHints: Array<string>): boolean =>
|
|
7
|
+
displayHints.includes(DISPLAY_HINTS.ENABLE_HARD_MUTE);
|
|
8
|
+
|
|
9
|
+
const canUnsetMuteOnEntry = (displayHints: Array<string>): boolean =>
|
|
10
|
+
displayHints.includes(DISPLAY_HINTS.DISABLE_MUTE_ON_ENTRY);
|
|
11
|
+
|
|
12
|
+
const canUnsetDisallowUnmute = (displayHints: Array<string>): boolean =>
|
|
13
|
+
displayHints.includes(DISPLAY_HINTS.DISABLE_HARD_MUTE);
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
canSetMuteOnEntry,
|
|
17
|
+
canSetDisallowUnmute,
|
|
18
|
+
canUnsetMuteOnEntry,
|
|
19
|
+
canUnsetDisallowUnmute,
|
|
20
|
+
};
|
|
@@ -13,6 +13,10 @@ interface IInMeetingActions {
|
|
|
13
13
|
canAdmitParticipant?: boolean;
|
|
14
14
|
canLock?: boolean;
|
|
15
15
|
canUnlock?: boolean;
|
|
16
|
+
canSetMuteOnEntry?: boolean;
|
|
17
|
+
canUnsetMuteOnEntry?: boolean;
|
|
18
|
+
canSetDisallowUnmute?: boolean;
|
|
19
|
+
canUnsetDisallowUnmute?: boolean;
|
|
16
20
|
canAssignHost?: boolean;
|
|
17
21
|
canStartRecording?: boolean;
|
|
18
22
|
canPauseRecording?: boolean;
|
|
@@ -59,6 +63,14 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
59
63
|
|
|
60
64
|
canStopRecording = null;
|
|
61
65
|
|
|
66
|
+
canSetMuteOnEntry = null;
|
|
67
|
+
|
|
68
|
+
canUnsetMuteOnEntry = null;
|
|
69
|
+
|
|
70
|
+
canSetDisallowUnmute = null;
|
|
71
|
+
|
|
72
|
+
canUnsetDisallowUnmute = null;
|
|
73
|
+
|
|
62
74
|
canRaiseHand = null;
|
|
63
75
|
|
|
64
76
|
canLowerAllHands = null;
|
|
@@ -99,6 +111,10 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
99
111
|
canLock: this.canLock,
|
|
100
112
|
canUnlock: this.canUnlock,
|
|
101
113
|
canAssignHost: this.canAssignHost,
|
|
114
|
+
canSetMuteOnEntry: this.canSetMuteOnEntry,
|
|
115
|
+
canUnsetMuteOnEntry: this.canUnsetMuteOnEntry,
|
|
116
|
+
canSetDisallowUnmute: this.canSetDisallowUnmute,
|
|
117
|
+
canUnsetDisallowUnmute: this.canUnsetDisallowUnmute,
|
|
102
118
|
canStartRecording: this.canStartRecording,
|
|
103
119
|
canPauseRecording: this.canPauseRecording,
|
|
104
120
|
canResumeRecording: this.canResumeRecording,
|
package/src/meeting/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ import MeetingRequest from './request';
|
|
|
37
37
|
import Members from '../members/index';
|
|
38
38
|
import MeetingUtil from './util';
|
|
39
39
|
import RecordingUtil from '../recording-controller/util';
|
|
40
|
+
import ControlsOptionsUtil from '../controls-options-manager/util';
|
|
40
41
|
import MediaUtil from '../media/util';
|
|
41
42
|
import Transcription from '../transcription';
|
|
42
43
|
import {Reactions, SkinTones} from '../reactions/reactions';
|
|
@@ -106,6 +107,7 @@ import Breakouts from '../breakouts';
|
|
|
106
107
|
import InMeetingActions from './in-meeting-actions';
|
|
107
108
|
import {REACTION_RELAY_TYPES} from '../reactions/constants';
|
|
108
109
|
import RecordingController from '../recording-controller';
|
|
110
|
+
import ControlsOptionsManager from '../controls-options-manager';
|
|
109
111
|
|
|
110
112
|
const {isBrowser} = BrowserDetection();
|
|
111
113
|
|
|
@@ -485,6 +487,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
485
487
|
recording: any;
|
|
486
488
|
remoteMediaManager: RemoteMediaManager | null;
|
|
487
489
|
recordingController: RecordingController;
|
|
490
|
+
controlsOptionsManager: ControlsOptionsManager;
|
|
488
491
|
requiredCaptcha: any;
|
|
489
492
|
receiveSlotManager: ReceiveSlotManager;
|
|
490
493
|
shareStatus: string;
|
|
@@ -1098,6 +1101,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1098
1101
|
displayHints: [],
|
|
1099
1102
|
});
|
|
1100
1103
|
|
|
1104
|
+
/**
|
|
1105
|
+
* The class that helps to control recording functions: start, stop, pause, resume, etc
|
|
1106
|
+
* @instance
|
|
1107
|
+
* @type {ControlsOptionsManager}
|
|
1108
|
+
* @public
|
|
1109
|
+
* @memberof Meeting
|
|
1110
|
+
*/
|
|
1111
|
+
this.controlsOptionsManager = new ControlsOptionsManager(this.meetingRequest, {
|
|
1112
|
+
locusUrl: this.locusInfo?.url,
|
|
1113
|
+
displayHints: [],
|
|
1114
|
+
});
|
|
1115
|
+
|
|
1101
1116
|
this.setUpLocusInfoListeners();
|
|
1102
1117
|
this.locusInfo.init(attrs.locus ? attrs.locus : {});
|
|
1103
1118
|
this.hasJoinedOnce = false;
|
|
@@ -2187,6 +2202,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2187
2202
|
this.locusUrl = payload;
|
|
2188
2203
|
this.locusId = this.locusUrl?.split('/').pop();
|
|
2189
2204
|
this.recordingController.setLocusUrl(this.locusUrl);
|
|
2205
|
+
this.controlsOptionsManager.setLocusUrl(this.locusUrl);
|
|
2190
2206
|
});
|
|
2191
2207
|
}
|
|
2192
2208
|
|
|
@@ -2252,6 +2268,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2252
2268
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(payload.info.userDisplayHints),
|
|
2253
2269
|
canLock: MeetingUtil.canUserLock(payload.info.userDisplayHints),
|
|
2254
2270
|
canUnlock: MeetingUtil.canUserUnlock(payload.info.userDisplayHints),
|
|
2271
|
+
canSetDisallowUnmute: ControlsOptionsUtil.canSetDisallowUnmute(
|
|
2272
|
+
payload.info.userDisplayHints
|
|
2273
|
+
),
|
|
2274
|
+
canUnsetDisallowUnmute: ControlsOptionsUtil.canUnsetDisallowUnmute(
|
|
2275
|
+
payload.info.userDisplayHints
|
|
2276
|
+
),
|
|
2277
|
+
canSetMuteOnEntry: ControlsOptionsUtil.canSetMuteOnEntry(payload.info.userDisplayHints),
|
|
2278
|
+
canUnsetMuteOnEntry: ControlsOptionsUtil.canUnsetMuteOnEntry(
|
|
2279
|
+
payload.info.userDisplayHints
|
|
2280
|
+
),
|
|
2255
2281
|
canStartRecording: RecordingUtil.canUserStart(payload.info.userDisplayHints),
|
|
2256
2282
|
canStopRecording: RecordingUtil.canUserStop(payload.info.userDisplayHints),
|
|
2257
2283
|
canPauseRecording: RecordingUtil.canUserPause(payload.info.userDisplayHints),
|
|
@@ -2288,6 +2314,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2288
2314
|
});
|
|
2289
2315
|
|
|
2290
2316
|
this.recordingController.setDisplayHints(payload.info.userDisplayHints);
|
|
2317
|
+
this.controlsOptionsManager.setDisplayHints(payload.info.userDisplayHints);
|
|
2291
2318
|
|
|
2292
2319
|
if (changed) {
|
|
2293
2320
|
Trigger.trigger(
|
|
@@ -6131,6 +6158,28 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6131
6158
|
return this.recordingController.startRecording();
|
|
6132
6159
|
}
|
|
6133
6160
|
|
|
6161
|
+
/**
|
|
6162
|
+
* set the mute on entry flag for participants if you're the host
|
|
6163
|
+
* @returns {Promise}
|
|
6164
|
+
* @param {boolean} enabled
|
|
6165
|
+
* @public
|
|
6166
|
+
* @memberof Meeting
|
|
6167
|
+
*/
|
|
6168
|
+
public setMuteOnEntry(enabled: boolean) {
|
|
6169
|
+
return this.controlsOptionsManager.setMuteOnEntry(enabled);
|
|
6170
|
+
}
|
|
6171
|
+
|
|
6172
|
+
/**
|
|
6173
|
+
* set the disallow unmute flag for participants if you're the host
|
|
6174
|
+
* @returns {Promise}
|
|
6175
|
+
* @param {boolean} enabled
|
|
6176
|
+
* @public
|
|
6177
|
+
* @memberof Meeting
|
|
6178
|
+
*/
|
|
6179
|
+
public setDisallowUnmute(enabled: boolean) {
|
|
6180
|
+
return this.controlsOptionsManager.setDisallowUnmute(enabled);
|
|
6181
|
+
}
|
|
6182
|
+
|
|
6134
6183
|
/**
|
|
6135
6184
|
* End the recording of this meeting
|
|
6136
6185
|
* @returns {Promise}
|
|
@@ -115,7 +115,7 @@ const TwoMainPlusSixSmallLayout: VideoLayout = {
|
|
|
115
115
|
|
|
116
116
|
// A strip of 8 small video panes (thumbnails) displayed at the top of a remote screenshare:
|
|
117
117
|
const RemoteScreenShareWithSmallThumbnailsLayout: VideoLayout = {
|
|
118
|
-
|
|
118
|
+
screenShareVideo: {size: 'best'},
|
|
119
119
|
activeSpeakerVideoPaneGroups: [
|
|
120
120
|
{
|
|
121
121
|
id: 'thumbnails',
|
|
@@ -153,7 +153,7 @@ const Stage2x2With6ThumbnailsLayout: VideoLayout = {
|
|
|
153
153
|
export const DefaultConfiguration: Configuration = {
|
|
154
154
|
audio: {
|
|
155
155
|
numOfActiveSpeakerStreams: 3,
|
|
156
|
-
numOfScreenShareStreams:
|
|
156
|
+
numOfScreenShareStreams: 1,
|
|
157
157
|
},
|
|
158
158
|
video: {
|
|
159
159
|
preferLiveVideo: true,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import ControlsOptionsManager from '@webex/plugin-meetings/src/controls-options-manager';
|
|
2
|
+
import sinon from 'sinon';
|
|
3
|
+
import {assert} from '@webex/test-helper-chai';
|
|
4
|
+
import { HTTP_VERBS } from '@webex/plugin-meetings/src/constants';
|
|
5
|
+
|
|
6
|
+
describe('plugin-meetings', () => {
|
|
7
|
+
describe('controls-options-manager tests', () => {
|
|
8
|
+
describe('index', () => {
|
|
9
|
+
let request;
|
|
10
|
+
|
|
11
|
+
describe('class tests', () => {
|
|
12
|
+
it('can set and extract new values later on', () => {
|
|
13
|
+
const manager = new ControlsOptionsManager({});
|
|
14
|
+
assert.isUndefined(manager.getLocusUrl());
|
|
15
|
+
manager.set({
|
|
16
|
+
locusUrl: 'test/id',
|
|
17
|
+
})
|
|
18
|
+
assert(manager.getLocusUrl(), 'test/id');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('Mute On Entry', () => {
|
|
23
|
+
let manager;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
request = {
|
|
27
|
+
request: sinon.stub().returns(Promise.resolve()),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
manager = new ControlsOptionsManager(request);
|
|
31
|
+
|
|
32
|
+
manager.set({
|
|
33
|
+
locusUrl: 'test/id',
|
|
34
|
+
displayHints: [],
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('setMuteOnEntry', () => {
|
|
39
|
+
it('rejects when correct display hint is not present enabled=false', () => {
|
|
40
|
+
const result = manager.setMuteOnEntry(false);
|
|
41
|
+
|
|
42
|
+
assert.notCalled(request.request);
|
|
43
|
+
|
|
44
|
+
assert.isRejected(result);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('rejects when correct display hint is not present enabled=true', () => {
|
|
48
|
+
const result = manager.setMuteOnEntry(true);
|
|
49
|
+
|
|
50
|
+
assert.notCalled(request.request);
|
|
51
|
+
|
|
52
|
+
assert.isRejected(result);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('can set mute on entry when the display hint is available enabled=true', () => {
|
|
56
|
+
manager.setDisplayHints(['ENABLE_MUTE_ON_ENTRY']);
|
|
57
|
+
|
|
58
|
+
const result = manager.setMuteOnEntry(true);
|
|
59
|
+
|
|
60
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
61
|
+
body: { muteOnEntry: { enabled: true } },
|
|
62
|
+
method: HTTP_VERBS.PATCH});
|
|
63
|
+
|
|
64
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('can set mute on entry when the display hint is available enabled=false', () => {
|
|
68
|
+
manager.setDisplayHints(['DISABLE_MUTE_ON_ENTRY']);
|
|
69
|
+
|
|
70
|
+
const result = manager.setMuteOnEntry(false);
|
|
71
|
+
|
|
72
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
73
|
+
body: { muteOnEntry: { enabled: false } },
|
|
74
|
+
method: HTTP_VERBS.PATCH});
|
|
75
|
+
|
|
76
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('setDisallowUnmute', () => {
|
|
81
|
+
it('rejects when correct display hint is not present enabled=false', () => {
|
|
82
|
+
const result = manager.setDisallowUnmute(false);
|
|
83
|
+
|
|
84
|
+
assert.notCalled(request.request);
|
|
85
|
+
|
|
86
|
+
assert.isRejected(result);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('rejects when correct display hint is not present enabled=true', () => {
|
|
90
|
+
const result = manager.setDisallowUnmute(true);
|
|
91
|
+
|
|
92
|
+
assert.notCalled(request.request);
|
|
93
|
+
|
|
94
|
+
assert.isRejected(result);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('can set mute on entry when the display hint is available enabled=true', () => {
|
|
98
|
+
manager.setDisplayHints(['ENABLE_HARD_MUTE']);
|
|
99
|
+
|
|
100
|
+
const result = manager.setDisallowUnmute(true);
|
|
101
|
+
|
|
102
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
103
|
+
body: { disallowUnmute: { enabled: true } },
|
|
104
|
+
method: HTTP_VERBS.PATCH});
|
|
105
|
+
|
|
106
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('can set mute on entry when the display hint is available enabled=false', () => {
|
|
110
|
+
manager.setDisplayHints(['DISABLE_HARD_MUTE']);
|
|
111
|
+
|
|
112
|
+
const result = manager.setDisallowUnmute(false);
|
|
113
|
+
|
|
114
|
+
assert.calledWith(request.request, { uri: 'test/id/controls',
|
|
115
|
+
body: { disallowUnmute: { enabled: false } },
|
|
116
|
+
method: HTTP_VERBS.PATCH});
|
|
117
|
+
|
|
118
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import ControlsOptionsUtil from '@webex/plugin-meetings/src/controls-options-manager/util';
|
|
2
|
+
import { assert } from 'chai';
|
|
3
|
+
|
|
4
|
+
describe('plugin-meetings', () => {
|
|
5
|
+
describe('controls-option-manager tests', () => {
|
|
6
|
+
describe('util tests', () => {
|
|
7
|
+
|
|
8
|
+
let locusInfo;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
locusInfo = {
|
|
12
|
+
parsedLocus: {
|
|
13
|
+
info: {
|
|
14
|
+
userDisplayHints: [],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('canUserSetMuteOnEntry', () => {
|
|
21
|
+
it('can set mute on entry enable', () => {
|
|
22
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('ENABLE_MUTE_ON_ENTRY');
|
|
23
|
+
|
|
24
|
+
assert.equal(ControlsOptionsUtil.canSetMuteOnEntry(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('can set mute on entry disable', () => {
|
|
28
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('DISABLE_MUTE_ON_ENTRY');
|
|
29
|
+
|
|
30
|
+
assert.equal(ControlsOptionsUtil.canUnsetMuteOnEntry(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('rejects when correct display hint is not present for setting mute on entry', () => {
|
|
34
|
+
assert.equal(ControlsOptionsUtil.canSetMuteOnEntry(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('rejects when correct display hint is not present for unsetting mute on entry', () => {
|
|
38
|
+
assert.equal(ControlsOptionsUtil.canUnsetMuteOnEntry(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('canSetDisallowUnmute', () => {
|
|
43
|
+
it('can set disallow unmute enable', () => {
|
|
44
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('ENABLE_HARD_MUTE');
|
|
45
|
+
|
|
46
|
+
assert.equal(ControlsOptionsUtil.canSetDisallowUnmute(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('can set disallow unmute disable', () => {
|
|
50
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('DISABLE_HARD_MUTE');
|
|
51
|
+
|
|
52
|
+
assert.equal(ControlsOptionsUtil.canUnsetDisallowUnmute(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('rejects when correct display hint is not present', () => {
|
|
56
|
+
assert.equal(ControlsOptionsUtil.canSetDisallowUnmute(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('rejects when correct display hint is not present', () => {
|
|
60
|
+
assert.equal(ControlsOptionsUtil.canUnsetDisallowUnmute(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -13,6 +13,10 @@ describe('plugin-meetings', () => {
|
|
|
13
13
|
canStartRecording: null,
|
|
14
14
|
canPauseRecording: null,
|
|
15
15
|
canResumeRecording: null,
|
|
16
|
+
canSetMuteOnEntry: null,
|
|
17
|
+
canUnsetMuteOnEntry: null,
|
|
18
|
+
canSetDisallowUnmute: null,
|
|
19
|
+
canUnsetDisallowUnmute: null,
|
|
16
20
|
canStopRecording: null,
|
|
17
21
|
canRaiseHand: null,
|
|
18
22
|
canLowerAllHands: null,
|
|
@@ -51,6 +55,10 @@ describe('plugin-meetings', () => {
|
|
|
51
55
|
'canPauseRecording',
|
|
52
56
|
'canResumeRecording',
|
|
53
57
|
'canStopRecording',
|
|
58
|
+
'canSetMuteOnEntry',
|
|
59
|
+
'canUnsetMuteOnEntry',
|
|
60
|
+
'canSetDisallowUnmute',
|
|
61
|
+
'canUnsetDisallowUnmute',
|
|
54
62
|
'canRaiseHand',
|
|
55
63
|
'canLowerAllHands',
|
|
56
64
|
'canLowerSomeoneElsesHand',
|
|
@@ -38,6 +38,7 @@ import Media from '@webex/plugin-meetings/src/media/index';
|
|
|
38
38
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
|
39
39
|
import MediaUtil from '@webex/plugin-meetings/src/media/util';
|
|
40
40
|
import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
|
|
41
|
+
import ControlsOptionsUtil from '@webex/plugin-meetings/src/controls-options-manager/util';
|
|
41
42
|
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
42
43
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
43
44
|
import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
|
|
@@ -4419,6 +4420,7 @@ describe('plugin-meetings', () => {
|
|
|
4419
4420
|
|
|
4420
4421
|
meeting.members = {locusUrlUpdate: sinon.stub().returns(Promise.resolve(test1))};
|
|
4421
4422
|
meeting.recordingController = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
4423
|
+
meeting.controlsOptionsManager = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
4422
4424
|
|
|
4423
4425
|
meeting.breakouts.locusUrlUpdate = sinon.stub();
|
|
4424
4426
|
|
|
@@ -4430,6 +4432,7 @@ describe('plugin-meetings', () => {
|
|
|
4430
4432
|
assert.calledOnceWithExactly(meeting.breakouts.locusUrlUpdate, newLocusUrl);
|
|
4431
4433
|
assert.calledWith(meeting.members.locusUrlUpdate, newLocusUrl);
|
|
4432
4434
|
assert.calledWith(meeting.recordingController.setLocusUrl, newLocusUrl);
|
|
4435
|
+
assert.calledWith(meeting.controlsOptionsManager.setLocusUrl, newLocusUrl);
|
|
4433
4436
|
assert.equal(meeting.locusUrl, newLocusUrl);
|
|
4434
4437
|
assert(meeting.locusId, '12345');
|
|
4435
4438
|
done();
|
|
@@ -4870,6 +4873,10 @@ describe('plugin-meetings', () => {
|
|
|
4870
4873
|
let canUserStopSpy;
|
|
4871
4874
|
let canUserPauseSpy;
|
|
4872
4875
|
let canUserResumeSpy;
|
|
4876
|
+
let canSetMuteOnEntrySpy;
|
|
4877
|
+
let canUnsetMuteOnEntrySpy;
|
|
4878
|
+
let canSetDisallowUnmuteSpy;
|
|
4879
|
+
let canUnsetDisallowUnmuteSpy;
|
|
4873
4880
|
let canUserRaiseHandSpy;
|
|
4874
4881
|
let bothLeaveAndEndMeetingAvailableSpy;
|
|
4875
4882
|
let canUserLowerAllHandsSpy;
|
|
@@ -4887,6 +4894,10 @@ describe('plugin-meetings', () => {
|
|
|
4887
4894
|
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
4888
4895
|
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
4889
4896
|
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
4897
|
+
canSetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canSetMuteOnEntry');
|
|
4898
|
+
canUnsetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canUnsetMuteOnEntry');
|
|
4899
|
+
canSetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canSetDisallowUnmute');
|
|
4900
|
+
canUnsetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canUnsetDisallowUnmute');
|
|
4890
4901
|
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
4891
4902
|
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
4892
4903
|
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
@@ -4932,6 +4943,10 @@ describe('plugin-meetings', () => {
|
|
|
4932
4943
|
assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
|
|
4933
4944
|
assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
|
|
4934
4945
|
assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
|
|
4946
|
+
assert.calledWith(canSetMuteOnEntrySpy, payload.info.userDisplayHints);
|
|
4947
|
+
assert.calledWith(canUnsetMuteOnEntrySpy, payload.info.userDisplayHints);
|
|
4948
|
+
assert.calledWith(canSetDisallowUnmuteSpy, payload.info.userDisplayHints);
|
|
4949
|
+
assert.calledWith(canUnsetDisallowUnmuteSpy, payload.info.userDisplayHints);
|
|
4935
4950
|
assert.calledWith(canUserRaiseHandSpy, payload.info.userDisplayHints);
|
|
4936
4951
|
assert.calledWith(bothLeaveAndEndMeetingAvailableSpy, payload.info.userDisplayHints);
|
|
4937
4952
|
assert.calledWith(canUserLowerAllHandsSpy, payload.info.userDisplayHints);
|