@webex/plugin-meetings 2.37.2 → 2.38.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.
Files changed (69) hide show
  1. package/dist/config.js +1 -1
  2. package/dist/config.js.map +1 -1
  3. package/dist/constants.js +2 -1
  4. package/dist/constants.js.map +1 -1
  5. package/dist/locus-info/index.js +24 -0
  6. package/dist/locus-info/index.js.map +1 -1
  7. package/dist/locus-info/parser.js +1 -0
  8. package/dist/locus-info/parser.js.map +1 -1
  9. package/dist/media/properties.js.map +1 -1
  10. package/dist/meeting/index.js +405 -352
  11. package/dist/meeting/index.js.map +1 -1
  12. package/dist/meeting/request.js +0 -27
  13. package/dist/meeting/request.js.map +1 -1
  14. package/dist/meeting/util.js +0 -56
  15. package/dist/meeting/util.js.map +1 -1
  16. package/dist/meeting-info/meeting-info-v2.js +2 -0
  17. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  18. package/dist/meetings/index.js +27 -17
  19. package/dist/meetings/index.js.map +1 -1
  20. package/dist/meetings/request.js +14 -12
  21. package/dist/meetings/request.js.map +1 -1
  22. package/dist/member/util.js +3 -1
  23. package/dist/member/util.js.map +1 -1
  24. package/dist/members/request.js +3 -1
  25. package/dist/members/request.js.map +1 -1
  26. package/dist/reachability/index.js +4 -4
  27. package/dist/reachability/index.js.map +1 -1
  28. package/dist/reactions/reactions.type.js +1 -0
  29. package/dist/reactions/reactions.type.js.map +1 -1
  30. package/dist/recording-controller/enums.js +17 -0
  31. package/dist/recording-controller/enums.js.map +1 -0
  32. package/dist/recording-controller/index.js +343 -0
  33. package/dist/recording-controller/index.js.map +1 -0
  34. package/dist/recording-controller/util.js +63 -0
  35. package/dist/recording-controller/util.js.map +1 -0
  36. package/dist/roap/turnDiscovery.js.map +1 -1
  37. package/dist/statsAnalyzer/mqaUtil.js +18 -6
  38. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  39. package/package.json +23 -18
  40. package/src/config.ts +1 -1
  41. package/src/constants.ts +1 -0
  42. package/src/locus-info/index.ts +24 -0
  43. package/src/locus-info/parser.ts +1 -0
  44. package/src/media/properties.ts +1 -1
  45. package/src/meeting/index.ts +121 -70
  46. package/src/meeting/request.ts +0 -31
  47. package/src/meeting/util.ts +0 -60
  48. package/src/meeting-info/meeting-info-v2.ts +2 -0
  49. package/src/meetings/index.ts +8 -3
  50. package/src/meetings/request.ts +1 -1
  51. package/src/member/util.ts +2 -1
  52. package/src/members/request.ts +1 -0
  53. package/src/reachability/index.ts +2 -1
  54. package/src/reactions/reactions.type.ts +2 -1
  55. package/src/recording-controller/enums.ts +8 -0
  56. package/src/recording-controller/index.ts +315 -0
  57. package/src/recording-controller/util.ts +58 -0
  58. package/src/roap/turnDiscovery.ts +1 -1
  59. package/src/statsAnalyzer/mqaUtil.ts +6 -0
  60. package/test/integration/spec/journey.js +1 -1
  61. package/test/integration/spec/space-meeting.js +1 -1
  62. package/test/integration/spec/transcription.js +1 -1
  63. package/test/unit/spec/meeting/index.js +33 -6
  64. package/test/unit/spec/meeting/utils.js +0 -127
  65. package/test/unit/spec/recording-controller/index.js +231 -0
  66. package/test/unit/spec/recording-controller/util.js +102 -0
  67. package/test/unit/spec/roap/index.ts +2 -1
  68. package/test/unit/spec/roap/turnDiscovery.ts +5 -4
  69. package/tsconfig.json +6 -0
@@ -0,0 +1,315 @@
1
+ import PermissionError from '../common/errors/permission';
2
+ import {CONTROLS, HTTP_VERBS} from '../constants';
3
+ import MeetingRequest from '../meeting/request';
4
+ import RecordingAction from './enums';
5
+ import Util from './util';
6
+ import LoggerProxy from '../common/logs/logger-proxy';
7
+
8
+ /**
9
+ * @description Recording manages the recording functionality of the meeting object, there should only be one instantation of recording per meeting
10
+ * @export
11
+ * @private
12
+ * @class Recording
13
+ */
14
+ export default class RecordingController {
15
+ /**
16
+ * @instance
17
+ * @type {MeetingRequest}
18
+ * @private
19
+ * @memberof RecordingController
20
+ */
21
+ private request: MeetingRequest;
22
+
23
+ /**
24
+ * @instance
25
+ * @type {Array}
26
+ * @private
27
+ * @memberof RecordingInfo
28
+ */
29
+ private displayHints: Array<string> = [];
30
+
31
+ /**
32
+ * @instance
33
+ * @type {string}
34
+ * @private
35
+ * @memberof RecordingInfo
36
+ */
37
+ private serviceUrl: string;
38
+
39
+ /**
40
+ * @instance
41
+ * @type {string}
42
+ * @private
43
+ * @memberof RecordingInfo
44
+ */
45
+ private sessionId: string;
46
+
47
+ /**
48
+ * @instance
49
+ * @type {string}
50
+ * @private
51
+ * @memberof RecordingInfo
52
+ */
53
+ private locusUrl: string;
54
+
55
+ /**
56
+ * @instance
57
+ * @type {string}
58
+ * @private
59
+ * @memberof RecordingInfo
60
+ */
61
+ private locusId: string;
62
+
63
+ /**
64
+ * @param {MeetingRequest} request
65
+ * @param {Object} options
66
+ * @constructor
67
+ * @memberof RecordingController
68
+ */
69
+ constructor(
70
+ request: MeetingRequest,
71
+ options?: {
72
+ serviceUrl?: string;
73
+ sessionId: string;
74
+ locusUrl: string;
75
+ displayHints?: Array<string>;
76
+ }
77
+ ) {
78
+ this.initialize(request);
79
+ this.set(options);
80
+ }
81
+
82
+ /**
83
+ * @param {MeetingRequest} request
84
+ * @param {LocusInfo} info
85
+ * @returns {void}
86
+ * @private
87
+ * @memberof RecordingController
88
+ */
89
+ private initialize(request: MeetingRequest) {
90
+ this.request = request;
91
+ }
92
+
93
+ /**
94
+ * @param {Object} options
95
+ * @returns {void}
96
+ * @public
97
+ * @memberof RecordingController
98
+ */
99
+ public set(options?: {
100
+ serviceUrl?: string;
101
+ sessionId: string;
102
+ locusUrl: string;
103
+ displayHints?: Array<string>;
104
+ }) {
105
+ this.extract(options);
106
+ }
107
+
108
+ /**
109
+ * @param {string} url
110
+ * @returns {void}
111
+ * @public
112
+ * @memberof RecordingController
113
+ */
114
+ public setLocusUrl(url: string) {
115
+ this.locusUrl = url;
116
+ this.locusId = Util.extractLocusId(this.locusUrl);
117
+ }
118
+
119
+ /**
120
+ * @param {Array} hints
121
+ * @returns {void}
122
+ * @public
123
+ * @memberof RecordingController
124
+ */
125
+ public setDisplayHints(hints: Array<string>) {
126
+ this.displayHints = hints;
127
+ }
128
+
129
+ /**
130
+ * @param {string} id
131
+ * @returns {void}
132
+ * @public
133
+ * @memberof RecordingController
134
+ */
135
+ public setSessionId(id: string) {
136
+ this.sessionId = id;
137
+ }
138
+
139
+ /**
140
+ * @param {string} url
141
+ * @returns {void}
142
+ * @public
143
+ * @memberof RecordingController
144
+ */
145
+ public setServiceUrl(url: string) {
146
+ this.serviceUrl = url;
147
+ }
148
+
149
+ /**
150
+ * @returns {string}
151
+ * @public
152
+ * @memberof RecordingController
153
+ */
154
+ public getLocusUrl() {
155
+ return this.locusUrl;
156
+ }
157
+
158
+ /**
159
+ * @returns {string}
160
+ * @public
161
+ * @memberof RecordingController
162
+ */
163
+ public getLocusId() {
164
+ return this.locusId;
165
+ }
166
+
167
+ /**
168
+ * @returns {string}
169
+ * @public
170
+ * @memberof RecordingController
171
+ */
172
+ public getSessionId() {
173
+ return this.sessionId;
174
+ }
175
+
176
+ /**
177
+ * @returns {string}
178
+ * @public
179
+ * @memberof RecordingController
180
+ */
181
+ public getServiceUrl() {
182
+ return this.serviceUrl;
183
+ }
184
+
185
+ /**
186
+ * @returns {Array}
187
+ * @public
188
+ * @memberof RecordingController
189
+ */
190
+ public getDisplayHints() {
191
+ return this.displayHints;
192
+ }
193
+
194
+ /**
195
+ * @param {Object} options
196
+ * @returns {void}
197
+ * @private
198
+ * @memberof RecordingController
199
+ */
200
+ private extract(options?: {
201
+ serviceUrl?: string;
202
+ sessionId: string;
203
+ locusUrl: string;
204
+ displayHints?: Array<string>;
205
+ }) {
206
+ this.setServiceUrl(options?.serviceUrl);
207
+ this.setSessionId(options?.sessionId);
208
+ this.setDisplayHints(options?.displayHints);
209
+ this.setLocusUrl(options?.locusUrl);
210
+ }
211
+
212
+ /**
213
+ * @param {RecordingAction} action
214
+ * @private
215
+ * @memberof RecordingController
216
+ * @returns {Promise}
217
+ */
218
+ private recordingService(action: RecordingAction): Promise<any> {
219
+ // @ts-ignore
220
+ return this.request.request({
221
+ body: {
222
+ meetingInfo: {
223
+ locusSessionId: this.sessionId,
224
+ },
225
+ recording: {
226
+ action: action.toLowerCase(),
227
+ },
228
+ },
229
+ uri: `${this.serviceUrl}/loci/${this.locusId}/recording`,
230
+ method: HTTP_VERBS.PUT,
231
+ });
232
+ }
233
+
234
+ /**
235
+ * @param {RecordingAction} action
236
+ * @private
237
+ * @memberof RecordingController
238
+ * @returns {Promise}
239
+ */
240
+ private recordingControls(action: RecordingAction): Promise<any> {
241
+ const record = Util.deriveRecordingStates(action);
242
+
243
+ LoggerProxy.logger.log(`RecordingController:index#recordingControls --> ${record}`);
244
+
245
+ // @ts-ignore
246
+ return this.request.request({
247
+ uri: `${this.locusUrl}/${CONTROLS}`,
248
+ body: {
249
+ record,
250
+ },
251
+ method: HTTP_VERBS.PATCH,
252
+ });
253
+ }
254
+
255
+ /**
256
+ * @param {RecordingAction} action
257
+ * @private
258
+ * @memberof RecordingController
259
+ * @returns {Promise}
260
+ */
261
+ private recordingFacade(action: RecordingAction): Promise<any> {
262
+ LoggerProxy.logger.log(
263
+ `RecordingController:index#recordingFacade --> recording action [${action}]`
264
+ );
265
+
266
+ // assumes action is proper cased (i.e., Example)
267
+ if (Util?.[`canUser${action}`](this.displayHints)) {
268
+ if (this.serviceUrl) {
269
+ return this.recordingService(action);
270
+ }
271
+
272
+ return this.recordingControls(action);
273
+ }
274
+
275
+ return Promise.reject(
276
+ new PermissionError(`${action} recording not allowed, due to moderator property.`)
277
+ );
278
+ }
279
+
280
+ /**
281
+ * @private
282
+ * @memberof RecordingController
283
+ * @returns {Promise}
284
+ */
285
+ public startRecording(): Promise<any> {
286
+ return this.recordingFacade(RecordingAction.Start);
287
+ }
288
+
289
+ /**
290
+ * @private
291
+ * @memberof RecordingController
292
+ * @returns {Promise}
293
+ */
294
+ public stopRecording(): Promise<any> {
295
+ return this.recordingFacade(RecordingAction.Stop);
296
+ }
297
+
298
+ /**
299
+ * @private
300
+ * @memberof RecordingController
301
+ * @returns {Promise}
302
+ */
303
+ public pauseRecording(): Promise<any> {
304
+ return this.recordingFacade(RecordingAction.Pause);
305
+ }
306
+
307
+ /**
308
+ * @private
309
+ * @memberof RecordingController
310
+ * @returns {Promise}
311
+ */
312
+ public resumeRecording(): Promise<any> {
313
+ return this.recordingFacade(RecordingAction.Resume);
314
+ }
315
+ }
@@ -0,0 +1,58 @@
1
+ import {DISPLAY_HINTS} from '../constants';
2
+ import RecordingAction from './enums';
3
+
4
+ const canUserStart = (displayHints: Array<string>): boolean =>
5
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START);
6
+
7
+ const canUserPause = (displayHints: Array<string>): boolean =>
8
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE);
9
+
10
+ const canUserResume = (displayHints: Array<string>): boolean =>
11
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME);
12
+
13
+ const canUserStop = (displayHints: Array<string>): boolean =>
14
+ displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP);
15
+
16
+ const extractLocusId = (url: string) => {
17
+ return url?.split('/').pop();
18
+ };
19
+
20
+ const deriveRecordingStates = (action: RecordingAction): {recording: boolean; paused: boolean} => {
21
+ let recording;
22
+ let paused;
23
+
24
+ switch (action) {
25
+ case RecordingAction.Start:
26
+ recording = true;
27
+ paused = false;
28
+ break;
29
+ case RecordingAction.Stop:
30
+ recording = false;
31
+ paused = false;
32
+ break;
33
+ case RecordingAction.Resume:
34
+ recording = true;
35
+ paused = false;
36
+ break;
37
+ case RecordingAction.Pause:
38
+ recording = true;
39
+ paused = true;
40
+ break;
41
+ default:
42
+ throw new Error(`Recording state cannot be derived from invalid action: ${action}`);
43
+ }
44
+
45
+ return {
46
+ recording,
47
+ paused,
48
+ };
49
+ };
50
+
51
+ export default {
52
+ canUserStart,
53
+ canUserPause,
54
+ canUserResume,
55
+ canUserStop,
56
+ deriveRecordingStates,
57
+ extractLocusId,
58
+ };
@@ -230,7 +230,7 @@ export default class TurnDiscovery {
230
230
  * media connection just after a reconnection
231
231
  * @returns {Promise}
232
232
  */
233
- doTurnDiscovery(meeting: Meeting, isReconnecting: boolean) {
233
+ doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {
234
234
  // @ts-ignore - fix type
235
235
  const isAnyClusterReachable = meeting.webex.meetings.reachability.isAnyClusterReachable();
236
236
 
@@ -26,6 +26,7 @@ export const getAudioReceiverMqa = ({audioReceiver, statsResults, lastMqaDataSen
26
26
 
27
27
  // @ts-ignore
28
28
  audioReceiver.streams[0].common.maxRtpJitter =
29
+ // @ts-ignore
29
30
  max(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
30
31
  audioReceiver.streams[0].common.meanRtpJitter =
31
32
  mean(statsResults[mediaType][sendrecvType].meanRtpJitter) * 1000 || 0;
@@ -72,6 +73,7 @@ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent})
72
73
 
73
74
  // @ts-ignore
74
75
  audioSender.common.maxRemoteJitter =
76
+ // @ts-ignore
75
77
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
76
78
  audioSender.common.meanRemoteJitter =
77
79
  mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
@@ -96,6 +98,7 @@ export const getAudioSenderMqa = ({audioSender, statsResults, lastMqaDataSent})
96
98
 
97
99
  // @ts-ignore
98
100
  audioSender.common.maxRoundTripTime =
101
+ // @ts-ignore
99
102
  max(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
100
103
  audioSender.common.meanRoundTripTime =
101
104
  mean(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
@@ -152,6 +155,7 @@ export const getVideoReceiverMqa = ({
152
155
 
153
156
  // @ts-ignore
154
157
  videoReceiver.common.maxRemoteJitter =
158
+ // @ts-ignore
155
159
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
156
160
  videoReceiver.common.meanRemoteJitter =
157
161
  mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
@@ -217,6 +221,7 @@ export const getVideoSenderMqa = ({
217
221
 
218
222
  // @ts-ignore
219
223
  videoSender.common.maxRemoteJitter =
224
+ // @ts-ignore
220
225
  max(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
221
226
  videoSender.common.meanRemoteJitter =
222
227
  mean(statsResults[mediaType][sendrecvType].meanRemoteJitter) * 1000 || 0;
@@ -239,6 +244,7 @@ export const getVideoSenderMqa = ({
239
244
 
240
245
  // @ts-ignore
241
246
  videoSender.common.maxRoundTripTime =
247
+ // @ts-ignore
242
248
  max(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
243
249
  videoSender.common.meanRoundTripTime =
244
250
  mean(statsResults[mediaType][sendrecvType].meanRoundTripTime) * 1000 || 0;
@@ -5,7 +5,7 @@ import {assert} from '@webex/test-helper-chai';
5
5
  import {skipInNode} from '@webex/test-helper-mocha';
6
6
  import sinon from 'sinon';
7
7
 
8
- import BrowserDetection from '@webex/plugin-meetings/src/common/browser-detection';
8
+ import BrowserDetection from '@webex/plugin-meetings/dist/common/browser-detection';
9
9
 
10
10
  import DEFAULT_RESOLUTIONS from '../../../src/config';
11
11
  import testUtils from '../../utils/testUtils';
@@ -2,7 +2,7 @@
2
2
  import {assert} from '@webex/test-helper-chai';
3
3
  import {skipInNode, jenkinsOnly} from '@webex/test-helper-mocha';
4
4
  import {patterns} from '@webex/common';
5
- import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
5
+ import MeetingInfoUtil from '@webex/plugin-meetings/dist/meeting-info/utilv2';
6
6
 
7
7
  import CMR from '../../utils/cmr';
8
8
  import testUtils from '../../utils/testUtils';
@@ -1,4 +1,4 @@
1
- import Transcription from '@webex/plugin-meetings/src/transcription';
1
+ import Transcription from '@webex/plugin-meetings/dist/transcription';
2
2
  import {assert} from '@webex/test-helper-chai';
3
3
  import sinon from 'sinon';
4
4
 
@@ -35,6 +35,7 @@ import Media from '@webex/plugin-meetings/src/media/index';
35
35
  import PeerConnectionManager from '@webex/plugin-meetings/src/peer-connection-manager';
36
36
  import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
37
37
  import MediaUtil from '@webex/plugin-meetings/src/media/util';
38
+ import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
38
39
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
39
40
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
40
41
  import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
@@ -3583,6 +3584,7 @@ describe('plugin-meetings', () => {
3583
3584
  const newLocusUrl = 'newLocusUrl/12345';
3584
3585
 
3585
3586
  meeting.members = {locusUrlUpdate: sinon.stub().returns(Promise.resolve(test1))};
3587
+ meeting.recordingController = {setLocusUrl: sinon.stub().returns(undefined)};
3586
3588
 
3587
3589
  meeting.locusInfo.emit(
3588
3590
  {function: 'test', file: 'test'},
@@ -3590,11 +3592,36 @@ describe('plugin-meetings', () => {
3590
3592
  newLocusUrl
3591
3593
  );
3592
3594
  assert.calledWith(meeting.members.locusUrlUpdate, newLocusUrl);
3595
+ assert.calledWith(meeting.recordingController.setLocusUrl, newLocusUrl);
3593
3596
  assert.equal(meeting.locusUrl, newLocusUrl);
3594
3597
  assert(meeting.locusId, '12345');
3595
3598
  done();
3596
3599
  });
3597
3600
  });
3601
+
3602
+ describe('#setUpLocusServicesListener', () => {
3603
+ it('listens to the locus services update event', (done) => {
3604
+ const newLocusServices = {
3605
+ services: {
3606
+ record: {
3607
+ url: 'url',
3608
+ }
3609
+ },
3610
+ };
3611
+
3612
+ meeting.recordingController = {setServiceUrl: sinon.stub().returns(undefined), setSessionId: sinon.stub().returns(undefined)};
3613
+
3614
+ meeting.locusInfo.emit(
3615
+ {function: 'test', file: 'test'},
3616
+ 'LINKS_SERVICES',
3617
+ newLocusServices
3618
+ );
3619
+
3620
+ assert.calledWith(meeting.recordingController.setServiceUrl, newLocusServices.services.record.url);
3621
+ assert.calledOnce(meeting.recordingController.setSessionId);
3622
+ done();
3623
+ });
3624
+ });
3598
3625
  describe('#setUpLocusInfoMediaInactiveListener', () => {
3599
3626
  it('listens to disconnect due to un activity ', (done) => {
3600
3627
  TriggerProxy.trigger.reset();
@@ -4009,7 +4036,7 @@ describe('plugin-meetings', () => {
4009
4036
  let inMeetingActionsSetSpy;
4010
4037
  let canUserLockSpy;
4011
4038
  let canUserUnlockSpy;
4012
- let canUserRecordSpy;
4039
+ let canUserStartSpy;
4013
4040
  let canUserStopSpy;
4014
4041
  let canUserPauseSpy;
4015
4042
  let canUserResumeSpy;
@@ -4023,10 +4050,10 @@ describe('plugin-meetings', () => {
4023
4050
  locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
4024
4051
  canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
4025
4052
  canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
4026
- canUserRecordSpy = sinon.spy(MeetingUtil, 'canUserRecord');
4027
- canUserStopSpy = sinon.spy(MeetingUtil, 'canUserStop');
4028
- canUserPauseSpy = sinon.spy(MeetingUtil, 'canUserPause');
4029
- canUserResumeSpy = sinon.spy(MeetingUtil, 'canUserResume');
4053
+ canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
4054
+ canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
4055
+ canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
4056
+ canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
4030
4057
  inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
4031
4058
  canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
4032
4059
  canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
@@ -4064,7 +4091,7 @@ describe('plugin-meetings', () => {
4064
4091
 
4065
4092
  assert.calledWith(canUserLockSpy, payload.info.userDisplayHints);
4066
4093
  assert.calledWith(canUserUnlockSpy, payload.info.userDisplayHints);
4067
- assert.calledWith(canUserRecordSpy, payload.info.userDisplayHints);
4094
+ assert.calledWith(canUserStartSpy, payload.info.userDisplayHints);
4068
4095
  assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
4069
4096
  assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
4070
4097
  assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
@@ -297,34 +297,6 @@ describe('plugin-meetings', () => {
297
297
  });
298
298
  });
299
299
 
300
- describe('canUserRecord', () => {
301
- it('works as expected', () => {
302
- assert.deepEqual(MeetingUtil.canUserRecord(['RECORDING_CONTROL_START']), true);
303
- assert.deepEqual(MeetingUtil.canUserRecord([]), false);
304
- });
305
- });
306
-
307
- describe('canUserPause', () => {
308
- it('works as expected', () => {
309
- assert.deepEqual(MeetingUtil.canUserPause(['RECORDING_CONTROL_PAUSE']), true);
310
- assert.deepEqual(MeetingUtil.canUserPause([]), false);
311
- });
312
- });
313
-
314
- describe('canUserResume', () => {
315
- it('works as expected', () => {
316
- assert.deepEqual(MeetingUtil.canUserResume(['RECORDING_CONTROL_RESUME']), true);
317
- assert.deepEqual(MeetingUtil.canUserResume([]), false);
318
- });
319
- });
320
-
321
- describe('canUserStop', () => {
322
- it('works as expected', () => {
323
- assert.deepEqual(MeetingUtil.canUserStop(['RECORDING_CONTROL_STOP']), true);
324
- assert.deepEqual(MeetingUtil.canUserStop([]), false);
325
- });
326
- });
327
-
328
300
  [
329
301
  {functionName: 'canEnableClosedCaption', displayHint: 'CAPTION_START'},
330
302
  {functionName: 'canStartTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_START'},
@@ -343,104 +315,5 @@ describe('plugin-meetings', () => {
343
315
  });
344
316
  });
345
317
  });
346
-
347
- describe('recording tests', () => {
348
- let request;
349
- let locusInfo;
350
- const locusUrl = 'locusUrl';
351
-
352
- beforeEach(() => {
353
- locusInfo = {
354
- parsedLocus: {
355
- info: {
356
- userDisplayHints: ['RECORDING_CONTROL_START'],
357
- },
358
- },
359
- };
360
- request = {
361
- recordMeeting: sinon.stub().returns(Promise.resolve()),
362
- };
363
- });
364
-
365
- describe('startRecording', () => {
366
- it('can start recording when the correct display hint is present', () => {
367
- locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_START');
368
-
369
- const result = MeetingUtil.startRecording(request, locusUrl, locusInfo);
370
-
371
- assert.calledWith(request.recordMeeting, {locusUrl, recording: true, paused: false});
372
-
373
- assert.deepEqual(result, request.recordMeeting.firstCall.returnValue);
374
- });
375
-
376
- it('rejects when correct display hint is not present', () => {
377
- const result = MeetingUtil.startRecording(request, locusUrl, {});
378
-
379
- assert.notCalled(request.recordMeeting);
380
-
381
- assert.isRejected(result);
382
- });
383
- });
384
-
385
- describe('pauseRecording', () => {
386
- it('can pause recording when the correct display hint is present', () => {
387
- locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_PAUSE');
388
-
389
- const result = MeetingUtil.pauseRecording(request, locusUrl, locusInfo);
390
-
391
- assert.calledWith(request.recordMeeting, {locusUrl, recording: true, paused: true});
392
-
393
- assert.deepEqual(result, request.recordMeeting.firstCall.returnValue);
394
- });
395
-
396
- it('rejects when correct display hint is not present', () => {
397
- const result = MeetingUtil.pauseRecording(request, locusUrl, {});
398
-
399
- assert.notCalled(request.recordMeeting);
400
-
401
- assert.isRejected(result);
402
- });
403
- });
404
-
405
- describe('resumeRecording', () => {
406
- it('can resume recording when the correct display hint is present', () => {
407
- locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_RESUME');
408
-
409
- const result = MeetingUtil.resumeRecording(request, locusUrl, locusInfo);
410
-
411
- assert.calledWith(request.recordMeeting, {locusUrl, recording: true, paused: false});
412
-
413
- assert.deepEqual(result, request.recordMeeting.firstCall.returnValue);
414
- });
415
-
416
- it('rejects when correct display hint is not present', () => {
417
- const result = MeetingUtil.resumeRecording(request, locusUrl, {});
418
-
419
- assert.notCalled(request.recordMeeting);
420
-
421
- assert.isRejected(result);
422
- });
423
- });
424
-
425
- describe('stopRecording', () => {
426
- it('can stop recording when the correct display hint is present', () => {
427
- locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_STOP');
428
-
429
- const result = MeetingUtil.stopRecording(request, locusUrl, locusInfo);
430
-
431
- assert.calledWith(request.recordMeeting, {locusUrl, recording: false, paused: false});
432
-
433
- assert.deepEqual(result, request.recordMeeting.firstCall.returnValue);
434
- });
435
-
436
- it('rejects when correct display hint is not present', () => {
437
- const result = MeetingUtil.stopRecording(request, locusUrl, {});
438
-
439
- assert.notCalled(request.recordMeeting);
440
-
441
- assert.isRejected(result);
442
- });
443
- });
444
- });
445
318
  });
446
319
  });