@webex/plugin-meetings 3.0.0-beta.43 → 3.0.0-beta.45
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 +12 -3
- package/dist/breakouts/index.js.map +1 -1
- package/dist/constants.js +15 -3
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +6 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +35 -1
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +28 -0
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +9 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +43 -4
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +45 -20
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/util.js +15 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/members/index.js +15 -3
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +33 -12
- package/dist/members/util.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +112 -55
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/types/constants.d.ts +11 -0
- package/dist/types/locus-info/index.d.ts +7 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +8 -0
- package/dist/types/meeting/index.d.ts +12 -2
- package/dist/types/meeting/muteState.d.ts +16 -0
- package/dist/types/members/index.d.ts +7 -2
- package/dist/types/multistream/remoteMediaManager.d.ts +20 -2
- package/package.json +18 -18
- package/src/breakouts/index.ts +8 -1
- package/src/constants.ts +13 -0
- package/src/locus-info/controlsUtils.ts +8 -0
- package/src/locus-info/index.ts +42 -1
- package/src/locus-info/selfUtils.ts +34 -0
- package/src/meeting/in-meeting-actions.ts +16 -0
- package/src/meeting/index.ts +53 -4
- package/src/meeting/muteState.ts +49 -30
- package/src/meeting/util.ts +15 -0
- package/src/members/index.ts +12 -4
- package/src/members/util.ts +21 -8
- package/src/multistream/remoteMediaManager.ts +57 -26
- package/test/unit/spec/breakouts/index.ts +2 -2
- package/test/unit/spec/locus-info/controlsUtils.js +104 -46
- package/test/unit/spec/locus-info/index.js +131 -16
- package/test/unit/spec/locus-info/selfConstant.js +9 -5
- package/test/unit/spec/locus-info/selfUtils.js +39 -16
- package/test/unit/spec/meeting/in-meeting-actions.ts +9 -1
- package/test/unit/spec/meeting/index.js +208 -79
- package/test/unit/spec/meeting/muteState.js +72 -6
- package/test/unit/spec/meeting/utils.js +35 -0
- package/test/unit/spec/members/index.js +75 -0
- package/test/unit/spec/members/utils.js +112 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +127 -0
|
@@ -24,6 +24,9 @@ describe('plugin-meetings', () => {
|
|
|
24
24
|
},
|
|
25
25
|
remoteMuted: false,
|
|
26
26
|
unmuteAllowed: true,
|
|
27
|
+
remoteVideoMuted: false,
|
|
28
|
+
unmuteVideoAllowed: true,
|
|
29
|
+
|
|
27
30
|
locusInfo: {
|
|
28
31
|
onFullLocus: sinon.stub(),
|
|
29
32
|
},
|
|
@@ -75,15 +78,16 @@ describe('plugin-meetings', () => {
|
|
|
75
78
|
});
|
|
76
79
|
|
|
77
80
|
it('initialises correctly for video', async () => {
|
|
78
|
-
// setup fields related to
|
|
79
|
-
meeting.
|
|
80
|
-
meeting.
|
|
81
|
-
|
|
81
|
+
// setup fields related to video remote state
|
|
82
|
+
meeting.remoteVideoMuted = false;
|
|
83
|
+
meeting.unmuteVideoAllowed = false;
|
|
84
|
+
|
|
85
|
+
// create a new video MuteState instance
|
|
82
86
|
video = createMuteState(VIDEO, meeting, {sendVideo: true});
|
|
83
87
|
|
|
84
88
|
assert.isFalse(video.isMuted());
|
|
85
89
|
assert.isFalse(video.state.server.remoteMute);
|
|
86
|
-
assert.
|
|
90
|
+
assert.isFalse(video.state.server.unmuteAllowed);
|
|
87
91
|
});
|
|
88
92
|
|
|
89
93
|
it('takes remote mute into account when reporting current state', async () => {
|
|
@@ -167,6 +171,30 @@ describe('plugin-meetings', () => {
|
|
|
167
171
|
assert.isFalse(audio.isSelf());
|
|
168
172
|
});
|
|
169
173
|
|
|
174
|
+
it('does local video unmute if localVideoUnmuteRequired is received', async () => {
|
|
175
|
+
// first we need to mute
|
|
176
|
+
await video.handleClientRequest(meeting, true);
|
|
177
|
+
|
|
178
|
+
assert.isTrue(video.isMuted());
|
|
179
|
+
assert.isTrue(video.isSelf());
|
|
180
|
+
|
|
181
|
+
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
182
|
+
|
|
183
|
+
// now simulate server requiring us to locally unmute
|
|
184
|
+
video.handleServerLocalUnmuteRequired(meeting);
|
|
185
|
+
await testUtils.flushPromises();
|
|
186
|
+
|
|
187
|
+
// check that local track was unmuted
|
|
188
|
+
assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
|
|
189
|
+
|
|
190
|
+
// and local unmute was sent to server
|
|
191
|
+
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
192
|
+
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, false, meeting);
|
|
193
|
+
|
|
194
|
+
assert.isFalse(video.isMuted());
|
|
195
|
+
assert.isFalse(video.isSelf());
|
|
196
|
+
});
|
|
197
|
+
|
|
170
198
|
describe('#isLocallyMuted()', () => {
|
|
171
199
|
it('does not consider remote mute status for audio', async () => {
|
|
172
200
|
// simulate being already remote muted
|
|
@@ -176,6 +204,15 @@ describe('plugin-meetings', () => {
|
|
|
176
204
|
|
|
177
205
|
assert.isFalse(audio.isLocallyMuted());
|
|
178
206
|
});
|
|
207
|
+
|
|
208
|
+
it('does not consider remote mute status for video', async () => {
|
|
209
|
+
// simulate being already remote muted
|
|
210
|
+
meeting.remoteVideoMuted = true;
|
|
211
|
+
// create a new MuteState intance
|
|
212
|
+
video = createMuteState(VIDEO, meeting, {sendVideo: true});
|
|
213
|
+
|
|
214
|
+
assert.isFalse(video.isLocallyMuted());
|
|
215
|
+
});
|
|
179
216
|
});
|
|
180
217
|
|
|
181
218
|
describe('#handleClientRequest', () => {
|
|
@@ -238,12 +275,41 @@ describe('plugin-meetings', () => {
|
|
|
238
275
|
|
|
239
276
|
// check that remote unmute was sent to server
|
|
240
277
|
assert.calledOnce(meeting.members.muteMember);
|
|
241
|
-
assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false);
|
|
278
|
+
assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, true);
|
|
242
279
|
|
|
243
280
|
assert.isFalse(audio.isMuted());
|
|
244
281
|
assert.isFalse(audio.isSelf());
|
|
245
282
|
});
|
|
246
283
|
|
|
284
|
+
it('does video remote unmute when unmuting and remote mute is on', async () => {
|
|
285
|
+
// simulate remote mute
|
|
286
|
+
video.handleServerRemoteMuteUpdate(true, true);
|
|
287
|
+
|
|
288
|
+
// unmute
|
|
289
|
+
await video.handleClientRequest(meeting, false);
|
|
290
|
+
|
|
291
|
+
// check that remote unmute was sent to server
|
|
292
|
+
assert.calledOnce(meeting.members.muteMember);
|
|
293
|
+
assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, false);
|
|
294
|
+
|
|
295
|
+
assert.isFalse(video.isMuted());
|
|
296
|
+
assert.isFalse(video.isSelf());
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('does not video remote unmute when unmuting and remote mute is off', async () => {
|
|
300
|
+
// simulate remote mute
|
|
301
|
+
video.handleServerRemoteMuteUpdate(false, true);
|
|
302
|
+
|
|
303
|
+
// unmute
|
|
304
|
+
await video.handleClientRequest(meeting, false);
|
|
305
|
+
|
|
306
|
+
// check that remote unmute was sent to server
|
|
307
|
+
assert.notCalled(meeting.members.muteMember);
|
|
308
|
+
|
|
309
|
+
assert.isFalse(video.isMuted());
|
|
310
|
+
assert.isFalse(video.isSelf());
|
|
311
|
+
});
|
|
312
|
+
|
|
247
313
|
it('resolves client request promise once the server is updated', async () => {
|
|
248
314
|
let clientPromiseResolved = false;
|
|
249
315
|
|
|
@@ -419,5 +419,40 @@ describe('plugin-meetings', () => {
|
|
|
419
419
|
});
|
|
420
420
|
});
|
|
421
421
|
});
|
|
422
|
+
|
|
423
|
+
describe('canManageBreakout', () => {
|
|
424
|
+
it('works as expected', () => {
|
|
425
|
+
assert.deepEqual(MeetingUtil.canManageBreakout(['BREAKOUT_MANAGEMENT']), true);
|
|
426
|
+
assert.deepEqual(MeetingUtil.canManageBreakout([]), false);
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe('isSuppressBreakoutSupport', () => {
|
|
431
|
+
it('works as expected', () => {
|
|
432
|
+
assert.deepEqual(MeetingUtil.isSuppressBreakoutSupport(['UCF_SUPPRESS_BREAKOUTS_SUPPORT']), true);
|
|
433
|
+
assert.deepEqual(MeetingUtil.isSuppressBreakoutSupport([]), false);
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
describe('canAdmitLobbyToBreakout', () => {
|
|
438
|
+
it('works as expected', () => {
|
|
439
|
+
assert.deepEqual(MeetingUtil.canAdmitLobbyToBreakout(['DISABLE_LOBBY_TO_BREAKOUT']), false);
|
|
440
|
+
assert.deepEqual(MeetingUtil.canAdmitLobbyToBreakout([]), true);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
describe('canUserAskForHelp', () => {
|
|
445
|
+
it('works as expected', () => {
|
|
446
|
+
assert.deepEqual(MeetingUtil.canUserAskForHelp(['DISABLE_ASK_FOR_HELP']), false);
|
|
447
|
+
assert.deepEqual(MeetingUtil.canUserAskForHelp([]), true);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
describe('isBreakoutPreassignmentsEnabled', () => {
|
|
452
|
+
it('works as expected', () => {
|
|
453
|
+
assert.deepEqual(MeetingUtil.isBreakoutPreassignmentsEnabled(['DISABLE_BREAKOUT_PREASSIGNMENTS']), false);
|
|
454
|
+
assert.deepEqual(MeetingUtil.isBreakoutPreassignmentsEnabled([]), true);
|
|
455
|
+
});
|
|
456
|
+
});
|
|
422
457
|
})
|
|
423
458
|
});
|
|
@@ -130,6 +130,81 @@ describe('plugin-meetings', () => {
|
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
describe('#admitMembers', () => {
|
|
134
|
+
let members;
|
|
135
|
+
beforeEach(() => {
|
|
136
|
+
members = createMembers({url: url1});
|
|
137
|
+
members.membersRequest.admitMember = sinon.stub().returns(Promise.resolve(true));
|
|
138
|
+
});
|
|
139
|
+
it('should return error if param memberIds is not provided', async () => {
|
|
140
|
+
let error;
|
|
141
|
+
await members.admitMembers().catch((e) => {
|
|
142
|
+
error = e;
|
|
143
|
+
});
|
|
144
|
+
assert.deepEqual(error, new ParameterError('No member ids provided to admit.'));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should call membersRequest.admitMember as expected', async () => {
|
|
148
|
+
await members.admitMembers(['uuid']);
|
|
149
|
+
const arg1 = members.membersRequest.admitMember.getCall(0).args[0];
|
|
150
|
+
assert.equal(arg1.sessionLocusUrls, undefined);
|
|
151
|
+
assert.equal(arg1.locusUrl.includes('https://example.com/'), true);
|
|
152
|
+
assert.deepEqual(arg1.memberIds, ['uuid']);
|
|
153
|
+
|
|
154
|
+
const sessionLocusUrls = {
|
|
155
|
+
authorizingLocusUrl: 'authorizingLocusUrl',
|
|
156
|
+
mainLocusUrl: 'mainLocusUrl',
|
|
157
|
+
};
|
|
158
|
+
await members.admitMembers(['uuid'], sessionLocusUrls);
|
|
159
|
+
const arg2 = members.membersRequest.admitMember.getCall(1).args[0];
|
|
160
|
+
assert.equal(arg2.sessionLocusUrls, sessionLocusUrls);
|
|
161
|
+
assert.equal(arg1.locusUrl.includes('https://example.com/'), true);
|
|
162
|
+
assert.deepEqual(arg1.memberIds, ['uuid']);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe('#muteMember', () => {
|
|
167
|
+
const testMuteMember = async (mute, isAudio) => {
|
|
168
|
+
sandbox.spy(MembersUtil, 'generateMuteMemberOptions');
|
|
169
|
+
|
|
170
|
+
const locusUrl = 'locus-url';
|
|
171
|
+
const members = createMembers({url: locusUrl});
|
|
172
|
+
const {membersRequest} = members;
|
|
173
|
+
sandbox.spy(membersRequest, 'muteMember');
|
|
174
|
+
|
|
175
|
+
const memberId = 'bob';
|
|
176
|
+
|
|
177
|
+
await members.muteMember(memberId, mute, isAudio);
|
|
178
|
+
assert.calledOnce(MembersUtil.generateMuteMemberOptions);
|
|
179
|
+
assert.calledWith(
|
|
180
|
+
MembersUtil.generateMuteMemberOptions,
|
|
181
|
+
memberId,
|
|
182
|
+
mute,
|
|
183
|
+
members.locusUrl,
|
|
184
|
+
isAudio
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
assert.calledOnce(membersRequest.muteMember);
|
|
188
|
+
assert.calledWith(membersRequest.muteMember, {memberId, muted: mute, locusUrl, isAudio});
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
it('invokes expected functions when muteMember is called for mute=true, isAudio=true', async () => {
|
|
192
|
+
testMuteMember(true, true);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('invokes expected functions when muteMember is called for mute=true, isAudio=false', async () => {
|
|
196
|
+
testMuteMember(true, false);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('invokes expected functions when muteMember is called for mute=false, isAudio=true', async () => {
|
|
200
|
+
testMuteMember(false, true);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('invokes expected functions when muteMember is called for mute=false, isAudio=false', async () => {
|
|
204
|
+
testMuteMember(false, false);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
133
208
|
describe('#sendDialPadKey', () => {
|
|
134
209
|
it('should throw a rejection when calling sendDialPadKey with no tones', async () => {
|
|
135
210
|
const members = createMembers({url: url1});
|
|
@@ -3,6 +3,7 @@ import chai from 'chai';
|
|
|
3
3
|
import chaiAsPromised from 'chai-as-promised';
|
|
4
4
|
|
|
5
5
|
import MembersUtil from '@webex/plugin-meetings/src/members/util';
|
|
6
|
+
import {HTTP_VERBS, CONTROLS, PARTICIPANT} from '@webex/plugin-meetings/src/constants';
|
|
6
7
|
|
|
7
8
|
const {assert} = chai;
|
|
8
9
|
|
|
@@ -38,5 +39,116 @@ describe('plugin-meetings', () => {
|
|
|
38
39
|
);
|
|
39
40
|
});
|
|
40
41
|
});
|
|
42
|
+
describe('#getAdmitMemberRequestBody', () => {
|
|
43
|
+
it('returns the correct request body', () => {
|
|
44
|
+
const option1 = {memberIds: ['uuid']};
|
|
45
|
+
|
|
46
|
+
assert.deepEqual(MembersUtil.getAdmitMemberRequestBody(option1), {
|
|
47
|
+
admit: {participantIds: ['uuid']},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const option2 = {
|
|
51
|
+
memberIds: ['uuid'],
|
|
52
|
+
sessionLocusUrls: {authorizingLocusUrl: 'authorizingLocusUrl'},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
assert.deepEqual(MembersUtil.getAdmitMemberRequestBody(option2), {
|
|
56
|
+
admit: {participantIds: ['uuid']},
|
|
57
|
+
authorizingLocusUrl: 'authorizingLocusUrl',
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('#getAdmitMemberRequestParams', () => {
|
|
62
|
+
it('returns the correct request params', () => {
|
|
63
|
+
const format1 = {memberIds: ['uuid'], locusUrl: 'locusUrl'};
|
|
64
|
+
|
|
65
|
+
assert.deepEqual(MembersUtil.getAdmitMemberRequestParams(format1), {
|
|
66
|
+
method: 'PUT',
|
|
67
|
+
uri: 'locusUrl/controls',
|
|
68
|
+
body: {admit: {participantIds: ['uuid']}},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const format2 = {
|
|
72
|
+
memberIds: ['uuid'],
|
|
73
|
+
sessionLocusUrls: {
|
|
74
|
+
authorizingLocusUrl: 'authorizingLocusUrl',
|
|
75
|
+
mainLocusUrl: 'mainLocusUrl',
|
|
76
|
+
},
|
|
77
|
+
locusUrl: 'locusUrl',
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
assert.deepEqual(MembersUtil.getAdmitMemberRequestParams(format2), {
|
|
81
|
+
method: 'PUT',
|
|
82
|
+
uri: 'mainLocusUrl/controls',
|
|
83
|
+
body: {
|
|
84
|
+
admit: {participantIds: ['uuid']},
|
|
85
|
+
authorizingLocusUrl: 'authorizingLocusUrl',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('#generateMuteMemberOptions', () => {
|
|
92
|
+
const testOptions = (isAudio) => {
|
|
93
|
+
const memberId = 'bob';
|
|
94
|
+
const muteStatus = true;
|
|
95
|
+
const locusUrl = 'urlTest1';
|
|
96
|
+
|
|
97
|
+
assert.deepEqual(
|
|
98
|
+
MembersUtil.generateMuteMemberOptions(memberId, muteStatus, locusUrl, isAudio),
|
|
99
|
+
{
|
|
100
|
+
memberId,
|
|
101
|
+
muted: muteStatus,
|
|
102
|
+
locusUrl,
|
|
103
|
+
isAudio,
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
it('returns the correct options for audio', () => {
|
|
109
|
+
testOptions(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('returns the correct options for video', () => {
|
|
113
|
+
testOptions(false);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('#getMuteMemberRequestParams', () => {
|
|
118
|
+
const testParams = (isAudio) => {
|
|
119
|
+
const memberId = 'bob';
|
|
120
|
+
const muteStatus = true;
|
|
121
|
+
const locusUrl = 'urlTest1';
|
|
122
|
+
|
|
123
|
+
const options = {
|
|
124
|
+
memberId,
|
|
125
|
+
muted: muteStatus,
|
|
126
|
+
locusUrl,
|
|
127
|
+
isAudio,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const uri = `${options.locusUrl}/${PARTICIPANT}/${options.memberId}/${CONTROLS}`;
|
|
131
|
+
const property = isAudio ? 'audio' : 'video';
|
|
132
|
+
const body = {
|
|
133
|
+
[property]: {
|
|
134
|
+
muted: options.muted,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
assert.deepEqual(MembersUtil.getMuteMemberRequestParams(options), {
|
|
139
|
+
method: HTTP_VERBS.PATCH,
|
|
140
|
+
uri,
|
|
141
|
+
body,
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
it('returns the correct params for audio', () => {
|
|
146
|
+
testParams(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('returns the correct params for video', () => {
|
|
150
|
+
testParams(false);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
41
153
|
});
|
|
42
154
|
});
|
|
@@ -699,6 +699,133 @@ describe('RemoteMediaManager', () => {
|
|
|
699
699
|
});
|
|
700
700
|
});
|
|
701
701
|
|
|
702
|
+
it('releases slots and reallocates slots when switching to layouts in correct order', async () => {
|
|
703
|
+
|
|
704
|
+
const config = cloneDeep(DefaultTestConfiguration);
|
|
705
|
+
let count = 0;
|
|
706
|
+
|
|
707
|
+
fakeReceiveSlotManager.allocateSlot = sinon.stub().callsFake((mediaType) => {
|
|
708
|
+
switch (mediaType) {
|
|
709
|
+
case MediaType.AudioMain:
|
|
710
|
+
return Promise.resolve(fakeAudioSlot);
|
|
711
|
+
case MediaType.VideoMain:
|
|
712
|
+
return Promise.resolve(new FakeSlot(MediaType.VideoMain, `fake video ${count++}`));
|
|
713
|
+
case MediaType.AudioSlides:
|
|
714
|
+
return Promise.resolve(fakeScreenShareAudioSlot);
|
|
715
|
+
case MediaType.VideoSlides:
|
|
716
|
+
return Promise.resolve(fakeScreenShareVideoSlot);
|
|
717
|
+
}
|
|
718
|
+
throw new Error(`invalid mediaType: ${mediaType}`);
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
remoteMediaManager = new RemoteMediaManager(
|
|
722
|
+
fakeReceiveSlotManager,
|
|
723
|
+
fakeMediaRequestManagers,
|
|
724
|
+
config
|
|
725
|
+
);
|
|
726
|
+
|
|
727
|
+
await remoteMediaManager.start();
|
|
728
|
+
|
|
729
|
+
resetHistory();
|
|
730
|
+
|
|
731
|
+
assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
|
|
732
|
+
"fake video 0",
|
|
733
|
+
"fake video 1",
|
|
734
|
+
"fake video 2",
|
|
735
|
+
"fake video 3",
|
|
736
|
+
"fake video 4",
|
|
737
|
+
"fake video 5",
|
|
738
|
+
"fake video 6",
|
|
739
|
+
"fake video 7",
|
|
740
|
+
"fake video 8",
|
|
741
|
+
]);
|
|
742
|
+
|
|
743
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
|
|
744
|
+
"fake video 0",
|
|
745
|
+
"fake video 1",
|
|
746
|
+
"fake video 2",
|
|
747
|
+
"fake video 3",
|
|
748
|
+
"fake video 4",
|
|
749
|
+
"fake video 5",
|
|
750
|
+
"fake video 6",
|
|
751
|
+
"fake video 7",
|
|
752
|
+
"fake video 8",
|
|
753
|
+
])
|
|
754
|
+
|
|
755
|
+
// switch to "OnePlusFive" layout that requires 3 less video slots (6)
|
|
756
|
+
await remoteMediaManager.setLayout('OnePlusFive');
|
|
757
|
+
|
|
758
|
+
assert.deepEqual(remoteMediaManager.slots.video.unused, []);
|
|
759
|
+
|
|
760
|
+
assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
|
|
761
|
+
"fake video 0",
|
|
762
|
+
"fake video 1",
|
|
763
|
+
"fake video 2",
|
|
764
|
+
"fake video 3",
|
|
765
|
+
"fake video 4",
|
|
766
|
+
"fake video 5"
|
|
767
|
+
]);
|
|
768
|
+
|
|
769
|
+
// we're checking that the slots are in the same order as in the previous layout
|
|
770
|
+
// first one goes into main
|
|
771
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["mainBigOne"].slots.map((slot: any) => slot.id), [
|
|
772
|
+
"fake video 0",
|
|
773
|
+
])
|
|
774
|
+
// and rest go in the pips
|
|
775
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["secondarySetOfSmallPanes"].slots.map((slot: any) => slot.id), [
|
|
776
|
+
"fake video 1",
|
|
777
|
+
"fake video 2",
|
|
778
|
+
"fake video 3",
|
|
779
|
+
"fake video 4",
|
|
780
|
+
"fake video 5"
|
|
781
|
+
])
|
|
782
|
+
|
|
783
|
+
// verify that 3 main video slots were released
|
|
784
|
+
assert.callCount(fakeReceiveSlotManager.releaseSlot, 3);
|
|
785
|
+
fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
|
|
786
|
+
const slot = call.args[0];
|
|
787
|
+
|
|
788
|
+
assert.strictEqual(slot.mediaType, MediaType.VideoMain);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
await remoteMediaManager.setLayout('AllEqual');
|
|
792
|
+
|
|
793
|
+
assert.deepEqual(remoteMediaManager.slots.video.unused, []);
|
|
794
|
+
|
|
795
|
+
// checking that slots are in the same order as in previous layout + 3 new ones
|
|
796
|
+
assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
|
|
797
|
+
"fake video 0",
|
|
798
|
+
"fake video 1",
|
|
799
|
+
"fake video 2",
|
|
800
|
+
"fake video 3",
|
|
801
|
+
"fake video 4",
|
|
802
|
+
"fake video 5",
|
|
803
|
+
"fake video 10",
|
|
804
|
+
"fake video 11",
|
|
805
|
+
"fake video 12",
|
|
806
|
+
]);
|
|
807
|
+
|
|
808
|
+
assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
|
|
809
|
+
"fake video 0",
|
|
810
|
+
"fake video 1",
|
|
811
|
+
"fake video 2",
|
|
812
|
+
"fake video 3",
|
|
813
|
+
"fake video 4",
|
|
814
|
+
"fake video 5",
|
|
815
|
+
"fake video 10",
|
|
816
|
+
"fake video 11",
|
|
817
|
+
"fake video 12"
|
|
818
|
+
])
|
|
819
|
+
|
|
820
|
+
// verify that 3 main video slots were allocated
|
|
821
|
+
assert.callCount(fakeReceiveSlotManager.allocateSlot, 3);
|
|
822
|
+
fakeReceiveSlotManager.allocateSlot.getCalls().forEach((call) => {
|
|
823
|
+
const mediaType = call.args[0];
|
|
824
|
+
|
|
825
|
+
assert.strictEqual(mediaType, MediaType.VideoMain);
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
|
|
702
829
|
it('stops all current video remoteMedia instances when switching to new layout', async () => {
|
|
703
830
|
const audioStopStubs = [];
|
|
704
831
|
const videoStopStubs = [];
|