@webex/plugin-meetings 2.37.2 → 2.38.1
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/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/index.js +24 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +1 -0
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +405 -352
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +13 -0
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +0 -27
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +0 -56
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -0
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +27 -17
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +14 -12
- package/dist/meetings/request.js.map +1 -1
- package/dist/member/util.js +3 -1
- package/dist/member/util.js.map +1 -1
- package/dist/members/request.js +3 -1
- package/dist/members/request.js.map +1 -1
- package/dist/reachability/index.js +4 -4
- package/dist/reachability/index.js.map +1 -1
- package/dist/reactions/reactions.type.js +1 -0
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/recording-controller/enums.js +17 -0
- package/dist/recording-controller/enums.js.map +1 -0
- package/dist/recording-controller/index.js +343 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +63 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/index.js +16 -10
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +6 -4
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +18 -6
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/package.json +23 -18
- package/src/config.ts +1 -1
- package/src/constants.ts +1 -0
- package/src/locus-info/index.ts +24 -0
- package/src/locus-info/parser.ts +1 -0
- package/src/media/properties.ts +1 -1
- package/src/meeting/index.ts +121 -70
- package/src/meeting/muteState.ts +11 -0
- package/src/meeting/request.ts +0 -31
- package/src/meeting/util.ts +0 -60
- package/src/meeting-info/meeting-info-v2.ts +2 -0
- package/src/meetings/index.ts +8 -3
- package/src/meetings/request.ts +1 -1
- package/src/member/util.ts +2 -1
- package/src/members/request.ts +1 -0
- package/src/reachability/index.ts +2 -1
- package/src/reactions/reactions.type.ts +2 -1
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +315 -0
- package/src/recording-controller/util.ts +58 -0
- package/src/roap/index.ts +8 -8
- package/src/roap/turnDiscovery.ts +5 -5
- package/src/statsAnalyzer/mqaUtil.ts +6 -0
- package/test/integration/spec/journey.js +1 -1
- package/test/integration/spec/space-meeting.js +1 -1
- package/test/integration/spec/transcription.js +1 -1
- package/test/unit/spec/meeting/index.js +33 -6
- package/test/unit/spec/meeting/muteState.js +11 -0
- package/test/unit/spec/meeting/utils.js +0 -127
- package/test/unit/spec/recording-controller/index.js +231 -0
- package/test/unit/spec/recording-controller/util.js +102 -0
- package/test/unit/spec/roap/index.ts +10 -5
- package/test/unit/spec/roap/turnDiscovery.ts +13 -8
- package/tsconfig.json +6 -0
|
@@ -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
|
|
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
|
-
|
|
4027
|
-
canUserStopSpy = sinon.spy(
|
|
4028
|
-
canUserPauseSpy = sinon.spy(
|
|
4029
|
-
canUserResumeSpy = sinon.spy(
|
|
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(
|
|
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);
|
|
@@ -161,6 +161,17 @@ describe('plugin-meetings', () => {
|
|
|
161
161
|
assert.isFalse(audio.isSelf());
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
describe('#isLocallyMuted()', () => {
|
|
165
|
+
it('does not consider remote mute status for audio', async () => {
|
|
166
|
+
// simulate being already remote muted
|
|
167
|
+
meeting.remoteMuted = true;
|
|
168
|
+
// create a new MuteState intance
|
|
169
|
+
audio = createMuteState(AUDIO, meeting, {sendAudio: true});
|
|
170
|
+
|
|
171
|
+
assert.isFalse(audio.isLocallyMuted());
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
164
175
|
describe('#handleClientRequest', () => {
|
|
165
176
|
it('disables/enables the local audio track when audio is muted/unmuted', async () => {
|
|
166
177
|
// mute
|
|
@@ -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
|
});
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import RecordingController from '@webex/plugin-meetings/src/recording-controller';
|
|
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('recording-controller tests', () => {
|
|
8
|
+
describe('index', () => {
|
|
9
|
+
let request;
|
|
10
|
+
|
|
11
|
+
describe('class tests', () => {
|
|
12
|
+
it('can set and extract new values later on', () => {
|
|
13
|
+
const controller = new RecordingController({});
|
|
14
|
+
assert.isUndefined(controller.getServiceUrl());
|
|
15
|
+
assert.isUndefined(controller.getSessionId());
|
|
16
|
+
assert.isUndefined(controller.getLocusUrl());
|
|
17
|
+
assert.isUndefined(controller.getLocusId());
|
|
18
|
+
controller.set({
|
|
19
|
+
serviceUrl: 'test',
|
|
20
|
+
sessionId: 'testId',
|
|
21
|
+
locusUrl: 'test/id',
|
|
22
|
+
displayHints: [],
|
|
23
|
+
})
|
|
24
|
+
assert(controller.getServiceUrl(), 'test');
|
|
25
|
+
assert(controller.getSessionId(), 'testId');
|
|
26
|
+
assert(controller.getLocusUrl(), 'test/id');
|
|
27
|
+
assert(controller.getLocusId(), 'id');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
describe('legacy locus style recording', () => {
|
|
33
|
+
const locusUrl = 'locusUrl';
|
|
34
|
+
let controller;
|
|
35
|
+
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
request = {
|
|
38
|
+
request: sinon.stub().returns(Promise.resolve()),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
controller = new RecordingController(request);
|
|
42
|
+
|
|
43
|
+
controller.set({
|
|
44
|
+
locusUrl,
|
|
45
|
+
displayHints: [],
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('startRecording', () => {
|
|
51
|
+
it('rejects when correct display hint is not present', () => {
|
|
52
|
+
const result = controller.startRecording();
|
|
53
|
+
|
|
54
|
+
assert.notCalled(request.request);
|
|
55
|
+
|
|
56
|
+
assert.isRejected(result);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('can start recording when the correct display hint is present', () => {
|
|
60
|
+
controller.setDisplayHints(['RECORDING_CONTROL_START']);
|
|
61
|
+
|
|
62
|
+
const result = controller.startRecording();
|
|
63
|
+
|
|
64
|
+
assert.calledWith(request.request, {uri: `${locusUrl}/controls`, body: {record: {recording: true, paused: false}}, method: HTTP_VERBS.PATCH});
|
|
65
|
+
|
|
66
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('stopRecording', () => {
|
|
71
|
+
it('rejects when correct display hint is not present', () => {
|
|
72
|
+
const result = controller.stopRecording();
|
|
73
|
+
|
|
74
|
+
assert.notCalled(request.request);
|
|
75
|
+
|
|
76
|
+
assert.isRejected(result);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('can stop recording when the correct display hint is present', () => {
|
|
80
|
+
controller.setDisplayHints(['RECORDING_CONTROL_STOP']);
|
|
81
|
+
|
|
82
|
+
const result = controller.stopRecording();
|
|
83
|
+
|
|
84
|
+
assert.calledWith(request.request, {uri: `${locusUrl}/controls`, body: {record: {recording: false, paused: false}}, method: HTTP_VERBS.PATCH});
|
|
85
|
+
|
|
86
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('pauseRecording', () => {
|
|
91
|
+
it('rejects when correct display hint is not present', () => {
|
|
92
|
+
const result = controller.pauseRecording();
|
|
93
|
+
|
|
94
|
+
assert.notCalled(request.request);
|
|
95
|
+
|
|
96
|
+
assert.isRejected(result);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('can pause recording when the correct display hint is present', () => {
|
|
100
|
+
controller.setDisplayHints(['RECORDING_CONTROL_PAUSE']);
|
|
101
|
+
|
|
102
|
+
const result = controller.pauseRecording();
|
|
103
|
+
|
|
104
|
+
assert.calledWith(request.request, {uri: `${locusUrl}/controls`, body: {record: {recording: true, paused: true}}, method: HTTP_VERBS.PATCH});
|
|
105
|
+
|
|
106
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('resumeRecording', () => {
|
|
111
|
+
it('rejects when correct display hint is not present', () => {
|
|
112
|
+
const result = controller.pauseRecording();
|
|
113
|
+
|
|
114
|
+
assert.notCalled(request.request);
|
|
115
|
+
|
|
116
|
+
assert.isRejected(result);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('can resume recording when the correct display hint is present', () => {
|
|
120
|
+
controller.setDisplayHints(['RECORDING_CONTROL_RESUME']);
|
|
121
|
+
|
|
122
|
+
const result = controller.resumeRecording();
|
|
123
|
+
|
|
124
|
+
assert.calledWith(request.request, {uri: `${locusUrl}/controls`, body: {record: {recording: true, paused: false}}, method: HTTP_VERBS.PATCH});
|
|
125
|
+
|
|
126
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('recording streaming service style tests', () => {
|
|
132
|
+
let controller;
|
|
133
|
+
|
|
134
|
+
beforeEach(() => {
|
|
135
|
+
request = {
|
|
136
|
+
request: sinon.stub().returns(Promise.resolve()),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
controller = new RecordingController(request);
|
|
140
|
+
|
|
141
|
+
controller.set({
|
|
142
|
+
serviceUrl: 'test',
|
|
143
|
+
sessionId: 'testId',
|
|
144
|
+
locusUrl: 'test/id',
|
|
145
|
+
displayHints: [],
|
|
146
|
+
})
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('startRecording', () => {
|
|
150
|
+
it('rejects when correct display hint is not present', () => {
|
|
151
|
+
const result = controller.startRecording();
|
|
152
|
+
|
|
153
|
+
assert.notCalled(request.request);
|
|
154
|
+
|
|
155
|
+
assert.isRejected(result);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('can start recording when the correct display hint is present', () => {
|
|
159
|
+
controller.setDisplayHints(['RECORDING_CONTROL_START']);
|
|
160
|
+
|
|
161
|
+
const result = controller.startRecording();
|
|
162
|
+
|
|
163
|
+
assert.calledWith(request.request, {uri: `test/loci/id/recording`, body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}}, method: HTTP_VERBS.PUT});
|
|
164
|
+
|
|
165
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('stopRecording', () => {
|
|
170
|
+
it('rejects when correct display hint is not present', () => {
|
|
171
|
+
const result = controller.pauseRecording();
|
|
172
|
+
|
|
173
|
+
assert.notCalled(request.request);
|
|
174
|
+
|
|
175
|
+
assert.isRejected(result);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('can start recording when the correct display hint is present', () => {
|
|
179
|
+
controller.setDisplayHints(['RECORDING_CONTROL_STOP']);
|
|
180
|
+
|
|
181
|
+
const result = controller.stopRecording();
|
|
182
|
+
|
|
183
|
+
assert.calledWith(request.request, {uri: `test/loci/id/recording`, body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}}, method: HTTP_VERBS.PUT});
|
|
184
|
+
|
|
185
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('pauseRecording', () => {
|
|
190
|
+
it('rejects when correct display hint is not present', () => {
|
|
191
|
+
const result = controller.pauseRecording();
|
|
192
|
+
|
|
193
|
+
assert.notCalled(request.request);
|
|
194
|
+
|
|
195
|
+
assert.isRejected(result);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('can pause recording when the correct display hint is present', () => {
|
|
199
|
+
controller.setDisplayHints(['RECORDING_CONTROL_PAUSE']);
|
|
200
|
+
|
|
201
|
+
const result = controller.pauseRecording();
|
|
202
|
+
|
|
203
|
+
assert.calledWith(request.request, {uri: `test/loci/id/recording`, body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}}, method: HTTP_VERBS.PUT});
|
|
204
|
+
|
|
205
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe('resumeRecording', () => {
|
|
210
|
+
it('rejects when correct display hint is not present', () => {
|
|
211
|
+
const result = controller.resumeRecording();
|
|
212
|
+
|
|
213
|
+
assert.notCalled(request.request);
|
|
214
|
+
|
|
215
|
+
assert.isRejected(result);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('can resume recording when the correct display hint is present', () => {
|
|
219
|
+
controller.setDisplayHints(['RECORDING_CONTROL_RESUME']);
|
|
220
|
+
|
|
221
|
+
const result = controller.resumeRecording();
|
|
222
|
+
|
|
223
|
+
assert.calledWith(request.request, {uri: `test/loci/id/recording`, body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}}, method: HTTP_VERBS.PUT});
|
|
224
|
+
|
|
225
|
+
assert.deepEqual(result, request.request.firstCall.returnValue);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
|
|
2
|
+
import RecordingAction from '@webex/plugin-meetings/src/recording-controller/enums';
|
|
3
|
+
import { assert } from 'chai';
|
|
4
|
+
|
|
5
|
+
describe('plugin-meetings', () => {
|
|
6
|
+
describe('recording-controller tests', () => {
|
|
7
|
+
describe('recording util tests', () => {
|
|
8
|
+
|
|
9
|
+
let locusInfo;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
locusInfo = {
|
|
13
|
+
parsedLocus: {
|
|
14
|
+
info: {
|
|
15
|
+
userDisplayHints: [],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('canUserStart', () => {
|
|
22
|
+
it('can start recording when the correct display hint is present', () => {
|
|
23
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_START');
|
|
24
|
+
|
|
25
|
+
assert.equal(RecordingUtil.canUserStart(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('rejects when correct display hint is not present', () => {
|
|
29
|
+
assert.equal(RecordingUtil.canUserStart(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('canUserPause', () => {
|
|
34
|
+
it('can pause recording when the correct display hint is present', () => {
|
|
35
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_PAUSE');
|
|
36
|
+
|
|
37
|
+
assert.equal(RecordingUtil.canUserPause(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('rejects when correct display hint is not present', () => {
|
|
41
|
+
assert.equal(RecordingUtil.canUserPause(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('canUserStop', () => {
|
|
46
|
+
it('can stop recording when the correct display hint is present', () => {
|
|
47
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_STOP');
|
|
48
|
+
|
|
49
|
+
assert.equal(RecordingUtil.canUserStop(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('rejects when correct display hint is not present', () => {
|
|
53
|
+
assert.equal(RecordingUtil.canUserStop(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('canUserResume', () => {
|
|
58
|
+
it('can start recording when the correct display hint is present', () => {
|
|
59
|
+
locusInfo.parsedLocus.info.userDisplayHints.push('RECORDING_CONTROL_RESUME');
|
|
60
|
+
|
|
61
|
+
assert.equal(RecordingUtil.canUserResume(locusInfo.parsedLocus.info.userDisplayHints), true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('rejects when correct display hint is not present', () => {
|
|
65
|
+
assert.equal(RecordingUtil.canUserResume(locusInfo.parsedLocus.info.userDisplayHints), false);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('deriveRecordingStates', () => {
|
|
70
|
+
it('gets the correct values for a start recording action', () => {
|
|
71
|
+
assert.deepEqual(RecordingUtil.deriveRecordingStates(RecordingAction.Start), {recording: true, paused: false});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('gets the correct values for a stop recording action', () => {
|
|
75
|
+
assert.deepEqual(RecordingUtil.deriveRecordingStates(RecordingAction.Stop), {recording: false, paused: false});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('gets the correct values for a resume recording action', () => {
|
|
79
|
+
assert.deepEqual(RecordingUtil.deriveRecordingStates(RecordingAction.Resume), {recording: true, paused: false});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('gets the correct values for a paused recording action', () => {
|
|
83
|
+
assert.deepEqual(RecordingUtil.deriveRecordingStates(RecordingAction.Pause), {recording: true, paused: true});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('extractLocusId', () => {
|
|
88
|
+
it('gets the correct id from the url param', () => {
|
|
89
|
+
assert.equal(RecordingUtil.extractLocusId('test/id'), 'id');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('works with empty string parameters passed', () => {
|
|
93
|
+
assert.equal(RecordingUtil.extractLocusId(''), '');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('works with no parameters passed', () => {
|
|
97
|
+
assert.isUndefined(RecordingUtil.extractLocusId(undefined));
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -6,12 +6,13 @@ import {ROAP} from '@webex/plugin-meetings/src/constants';
|
|
|
6
6
|
import RoapRequest from '@webex/plugin-meetings/src/roap/request';
|
|
7
7
|
import RoapHandler from '@webex/plugin-meetings/src/roap/handler';
|
|
8
8
|
import Roap from '@webex/plugin-meetings/src/roap/';
|
|
9
|
+
import Meeting from '@webex/plugin-meetings/src/meeting';
|
|
9
10
|
|
|
10
11
|
describe('Roap', () => {
|
|
11
12
|
describe('doTurnDiscovery', () => {
|
|
12
13
|
it('calls this.turnDiscovery.doTurnDiscovery() and forwards all the arguments', async () => {
|
|
13
14
|
const RESULT = {something: 'some value'};
|
|
14
|
-
const meeting = {id: 'some meeting id'};
|
|
15
|
+
const meeting = {id: 'some meeting id'} as Meeting;
|
|
15
16
|
|
|
16
17
|
const doTurnDiscoveryStub = sinon
|
|
17
18
|
.stub(TurnDiscovery.prototype, 'doTurnDiscovery')
|
|
@@ -46,8 +47,12 @@ describe('Roap', () => {
|
|
|
46
47
|
correlationId: 'correlation id',
|
|
47
48
|
selfUrl: 'self url',
|
|
48
49
|
mediaId: 'media id',
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
audio:{
|
|
51
|
+
isLocallyMuted: () => true,
|
|
52
|
+
},
|
|
53
|
+
video:{
|
|
54
|
+
isLocallyMuted: () => false,
|
|
55
|
+
},
|
|
51
56
|
setRoapSeq: sinon.stub(),
|
|
52
57
|
config: {experimental: {enableTurnDiscovery: false}},
|
|
53
58
|
};
|
|
@@ -98,8 +103,8 @@ describe('Roap', () => {
|
|
|
98
103
|
correlationId: meeting.correlationId,
|
|
99
104
|
locusSelfUrl: meeting.selfUrl,
|
|
100
105
|
mediaId: expectEmptyMediaId ? '' : meeting.mediaId,
|
|
101
|
-
audioMuted: meeting.
|
|
102
|
-
videoMuted: meeting.
|
|
106
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
107
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
103
108
|
meetingId: meeting.id,
|
|
104
109
|
});
|
|
105
110
|
|