@webex/plugin-meetings 3.0.0-beta.145 → 3.0.0-beta.147
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/annotation/annotation.types.js.map +1 -1
- package/dist/annotation/constants.js +6 -5
- package/dist/annotation/constants.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/webex-errors.js +3 -2
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +1 -7
- package/dist/config.js.map +1 -1
- package/dist/constants.js +7 -15
- package/dist/constants.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/media/index.js +5 -56
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +15 -93
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +1106 -1876
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +88 -184
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +2 -2
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +1 -23
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +1 -2
- package/dist/meetings/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +153 -134
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js +8 -7
- package/dist/roap/index.js.map +1 -1
- package/dist/types/annotation/annotation.types.d.ts +9 -1
- package/dist/types/annotation/constants.d.ts +5 -5
- package/dist/types/common/errors/webex-errors.d.ts +1 -1
- package/dist/types/config.d.ts +0 -6
- package/dist/types/constants.d.ts +1 -18
- package/dist/types/index.d.ts +1 -1
- package/dist/types/media/properties.d.ts +16 -38
- package/dist/types/meeting/index.d.ts +92 -352
- package/dist/types/meeting/muteState.d.ts +36 -38
- package/dist/types/meeting/request.d.ts +2 -1
- package/dist/types/meeting/util.d.ts +2 -4
- package/package.json +19 -19
- package/src/annotation/annotation.types.ts +10 -1
- package/src/annotation/constants.ts +5 -5
- package/src/common/errors/webex-errors.ts +6 -2
- package/src/config.ts +0 -6
- package/src/constants.ts +1 -14
- package/src/index.ts +1 -0
- package/src/media/index.ts +10 -53
- package/src/media/properties.ts +32 -92
- package/src/meeting/index.ts +532 -1564
- package/src/meeting/muteState.ts +87 -178
- package/src/meeting/request.ts +4 -3
- package/src/meeting/util.ts +3 -24
- package/src/meetings/index.ts +0 -1
- package/src/reconnection-manager/index.ts +4 -9
- package/src/roap/index.ts +13 -14
- package/test/integration/spec/converged-space-meetings.js +59 -3
- package/test/integration/spec/journey.js +330 -256
- package/test/integration/spec/space-meeting.js +75 -3
- package/test/unit/spec/meeting/index.js +776 -1344
- package/test/unit/spec/meeting/muteState.js +238 -394
- package/test/unit/spec/meeting/request.js +4 -4
- package/test/unit/spec/meeting/utils.js +2 -9
- package/test/unit/spec/multistream/receiveSlot.ts +1 -1
- package/test/unit/spec/roap/index.ts +2 -2
- package/test/utils/integrationTestUtils.js +5 -23
|
@@ -15,20 +15,21 @@ describe('plugin-meetings', () => {
|
|
|
15
15
|
|
|
16
16
|
const fakeLocus = {info: 'this is a fake locus'};
|
|
17
17
|
|
|
18
|
-
const createFakeLocalTrack = (id) => {
|
|
18
|
+
const createFakeLocalTrack = (id, muted) => {
|
|
19
19
|
return {
|
|
20
20
|
id,
|
|
21
21
|
setMuted: sinon.stub(),
|
|
22
22
|
setServerMuted: sinon.stub(),
|
|
23
23
|
setUnmuteAllowed: sinon.stub(),
|
|
24
|
-
|
|
24
|
+
muted,
|
|
25
|
+
};
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
beforeEach(async () => {
|
|
28
29
|
meeting = {
|
|
29
30
|
mediaProperties: {
|
|
30
|
-
audioTrack: createFakeLocalTrack('fake audio track'),
|
|
31
|
-
videoTrack: createFakeLocalTrack('fake video track'),
|
|
31
|
+
audioTrack: createFakeLocalTrack('fake audio track', false),
|
|
32
|
+
videoTrack: createFakeLocalTrack('fake video track', false),
|
|
32
33
|
},
|
|
33
34
|
remoteMuted: false,
|
|
34
35
|
unmuteAllowed: true,
|
|
@@ -48,8 +49,8 @@ describe('plugin-meetings', () => {
|
|
|
48
49
|
|
|
49
50
|
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves(fakeLocus);
|
|
50
51
|
|
|
51
|
-
audio = createMuteState(AUDIO, meeting,
|
|
52
|
-
video = createMuteState(VIDEO, meeting,
|
|
52
|
+
audio = createMuteState(AUDIO, meeting, true);
|
|
53
|
+
video = createMuteState(VIDEO, meeting, true);
|
|
53
54
|
|
|
54
55
|
await testUtils.flushPromises();
|
|
55
56
|
});
|
|
@@ -59,38 +60,28 @@ describe('plugin-meetings', () => {
|
|
|
59
60
|
});
|
|
60
61
|
|
|
61
62
|
describe('mute state library', () => {
|
|
62
|
-
it('does not create an audio instance if we are not sending audio', async () => {
|
|
63
|
-
assert.isNull(createMuteState(AUDIO, meeting, {sendAudio: false}, true));
|
|
64
|
-
assert.isNull(createMuteState(AUDIO, meeting, {}, true));
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('does not create a video instance if we are not sending video', async () => {
|
|
68
|
-
assert.isNull(createMuteState(VIDEO, meeting, {sendVideo: false}));
|
|
69
|
-
assert.isNull(createMuteState(VIDEO, meeting, {}));
|
|
70
|
-
});
|
|
71
|
-
|
|
72
63
|
it('takes into account current remote mute status when instantiated', async () => {
|
|
73
64
|
// simulate being already remote muted
|
|
74
65
|
meeting.remoteMuted = true;
|
|
75
66
|
|
|
76
67
|
// create a new MuteState instance
|
|
77
|
-
audio = createMuteState(AUDIO, meeting,
|
|
68
|
+
audio = createMuteState(AUDIO, meeting, true);
|
|
78
69
|
|
|
79
70
|
await testUtils.flushPromises();
|
|
80
71
|
|
|
81
72
|
assert.isTrue(audio.isMuted());
|
|
82
|
-
assert.
|
|
73
|
+
assert.isTrue(audio.isRemotelyMuted());
|
|
83
74
|
|
|
84
75
|
// now check the opposite case
|
|
85
76
|
meeting.remoteMuted = false;
|
|
86
77
|
|
|
87
78
|
// create a new MuteState instance
|
|
88
|
-
audio = createMuteState(AUDIO, meeting,
|
|
79
|
+
audio = createMuteState(AUDIO, meeting, true);
|
|
89
80
|
|
|
90
81
|
await testUtils.flushPromises();
|
|
91
82
|
|
|
92
|
-
assert.
|
|
93
|
-
assert.isFalse(audio.
|
|
83
|
+
assert.isTrue(audio.isMuted()); // because we start with no track
|
|
84
|
+
assert.isFalse(audio.isRemotelyMuted());
|
|
94
85
|
});
|
|
95
86
|
|
|
96
87
|
it('initialises correctly for video', async () => {
|
|
@@ -99,31 +90,31 @@ describe('plugin-meetings', () => {
|
|
|
99
90
|
meeting.unmuteVideoAllowed = false;
|
|
100
91
|
|
|
101
92
|
// create a new video MuteState instance
|
|
102
|
-
video = createMuteState(VIDEO, meeting,
|
|
93
|
+
video = createMuteState(VIDEO, meeting, true);
|
|
103
94
|
|
|
104
95
|
await testUtils.flushPromises();
|
|
105
96
|
|
|
106
|
-
assert.
|
|
97
|
+
assert.isTrue(video.isMuted()); // because we start with no track
|
|
98
|
+
assert.isFalse(video.isRemotelyMuted());
|
|
107
99
|
assert.isFalse(video.state.server.remoteMute);
|
|
108
100
|
assert.isFalse(video.state.server.unmuteAllowed);
|
|
109
101
|
});
|
|
110
102
|
|
|
111
103
|
it('takes remote mute into account when reporting current state', async () => {
|
|
112
|
-
assert.isFalse(audio.
|
|
104
|
+
assert.isFalse(audio.isRemotelyMuted());
|
|
113
105
|
|
|
114
106
|
// simulate remote mute
|
|
115
107
|
audio.handleServerRemoteMuteUpdate(meeting, true, true);
|
|
116
108
|
|
|
117
|
-
assert.isTrue(audio.
|
|
118
|
-
assert.isFalse(audio.isSelf());
|
|
109
|
+
assert.isTrue(audio.isRemotelyMuted());
|
|
119
110
|
});
|
|
120
111
|
|
|
121
112
|
it('does local unmute if localAudioUnmuteRequired is received', async () => {
|
|
122
|
-
// first we need to mute
|
|
123
|
-
|
|
113
|
+
// first we need to mute have the local track muted
|
|
114
|
+
meeting.mediaProperties.audioTrack.muted = true;
|
|
115
|
+
audio.handleLocalTrackChange(meeting);
|
|
124
116
|
|
|
125
117
|
assert.isTrue(audio.isMuted());
|
|
126
|
-
assert.isTrue(audio.isSelf());
|
|
127
118
|
|
|
128
119
|
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
129
120
|
|
|
@@ -132,69 +123,21 @@ describe('plugin-meetings', () => {
|
|
|
132
123
|
await testUtils.flushPromises();
|
|
133
124
|
|
|
134
125
|
// check that local track was unmuted
|
|
135
|
-
assert.calledWith(meeting.mediaProperties.audioTrack.
|
|
126
|
+
assert.calledWith(meeting.mediaProperties.audioTrack.setServerMuted, false, 'localUnmuteRequired');
|
|
136
127
|
|
|
137
128
|
// and local unmute was sent to server
|
|
138
129
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
139
130
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
|
|
140
131
|
|
|
141
132
|
assert.isFalse(audio.isMuted());
|
|
142
|
-
assert.isFalse(audio.isSelf());
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('rejects client request in progress if localAudioUnmuteRequired is received', async () => {
|
|
146
|
-
let clientPromiseResolved = false;
|
|
147
|
-
let clientPromiseRejected = false;
|
|
148
|
-
|
|
149
|
-
// first we need to mute and make that request last forever
|
|
150
|
-
let serverResponseResolve;
|
|
151
|
-
|
|
152
|
-
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
|
|
153
|
-
new Promise((resolve) => {
|
|
154
|
-
serverResponseResolve = resolve;
|
|
155
|
-
})
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
audio
|
|
159
|
-
.handleClientRequest(meeting, true)
|
|
160
|
-
.then(() => {
|
|
161
|
-
clientPromiseResolved = true;
|
|
162
|
-
})
|
|
163
|
-
.catch(() => {
|
|
164
|
-
clientPromiseRejected = true;
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
168
|
-
|
|
169
|
-
// now simulate server requiring us to locally unmute
|
|
170
|
-
audio.handleServerLocalUnmuteRequired(meeting);
|
|
171
|
-
await testUtils.flushPromises();
|
|
172
|
-
|
|
173
|
-
// the original client request should have been rejected by now
|
|
174
|
-
assert.isTrue(clientPromiseRejected);
|
|
175
|
-
assert.isFalse(clientPromiseResolved);
|
|
176
|
-
|
|
177
|
-
// now make the server respond to the original mute request
|
|
178
|
-
serverResponseResolve();
|
|
179
|
-
await testUtils.flushPromises();
|
|
180
|
-
|
|
181
|
-
// local unmute should be sent to server
|
|
182
|
-
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
183
|
-
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
|
|
184
|
-
|
|
185
|
-
// and local track should be unmuted
|
|
186
|
-
assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
|
|
187
|
-
|
|
188
|
-
assert.isFalse(audio.isMuted());
|
|
189
|
-
assert.isFalse(audio.isSelf());
|
|
190
133
|
});
|
|
191
134
|
|
|
192
135
|
it('does local video unmute if localVideoUnmuteRequired is received', async () => {
|
|
193
136
|
// first we need to mute
|
|
194
|
-
|
|
137
|
+
meeting.mediaProperties.videoTrack.muted = true;
|
|
138
|
+
video.handleLocalTrackChange(meeting);
|
|
195
139
|
|
|
196
140
|
assert.isTrue(video.isMuted());
|
|
197
|
-
assert.isTrue(video.isSelf());
|
|
198
141
|
|
|
199
142
|
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
200
143
|
|
|
@@ -203,22 +146,23 @@ describe('plugin-meetings', () => {
|
|
|
203
146
|
await testUtils.flushPromises();
|
|
204
147
|
|
|
205
148
|
// check that local track was unmuted
|
|
206
|
-
assert.calledWith(meeting.mediaProperties.videoTrack.
|
|
149
|
+
assert.calledWith(meeting.mediaProperties.videoTrack.setServerMuted, false, 'localUnmuteRequired');
|
|
207
150
|
|
|
208
151
|
// and local unmute was sent to server
|
|
209
152
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
210
153
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
|
|
211
154
|
|
|
212
155
|
assert.isFalse(video.isMuted());
|
|
213
|
-
assert.isFalse(video.isSelf());
|
|
214
156
|
});
|
|
215
157
|
|
|
216
158
|
describe('#isLocallyMuted()', () => {
|
|
217
159
|
it('does not consider remote mute status for audio', async () => {
|
|
218
160
|
// simulate being already remote muted
|
|
219
161
|
meeting.remoteMuted = true;
|
|
162
|
+
|
|
220
163
|
// create a new MuteState instance
|
|
221
|
-
audio = createMuteState(AUDIO, meeting,
|
|
164
|
+
audio = createMuteState(AUDIO, meeting, true);
|
|
165
|
+
audio.handleLocalTrackChange(meeting);
|
|
222
166
|
|
|
223
167
|
await testUtils.flushPromises();
|
|
224
168
|
|
|
@@ -228,8 +172,10 @@ describe('plugin-meetings', () => {
|
|
|
228
172
|
it('does not consider remote mute status for video', async () => {
|
|
229
173
|
// simulate being already remote muted
|
|
230
174
|
meeting.remoteVideoMuted = true;
|
|
175
|
+
|
|
231
176
|
// create a new MuteState instance
|
|
232
|
-
video = createMuteState(VIDEO, meeting,
|
|
177
|
+
video = createMuteState(VIDEO, meeting, true);
|
|
178
|
+
video.handleLocalTrackChange(meeting);
|
|
233
179
|
|
|
234
180
|
await testUtils.flushPromises();
|
|
235
181
|
|
|
@@ -237,55 +183,37 @@ describe('plugin-meetings', () => {
|
|
|
237
183
|
});
|
|
238
184
|
});
|
|
239
185
|
|
|
240
|
-
describe('
|
|
241
|
-
it('disables/enables the local audio track when audio is muted/unmuted', async () => {
|
|
242
|
-
// mute
|
|
243
|
-
audio.handleClientRequest(meeting, true);
|
|
244
|
-
assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, true);
|
|
186
|
+
describe('handling local track mute events', () => {
|
|
245
187
|
|
|
246
|
-
|
|
247
|
-
audio.
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// unmute
|
|
251
|
-
audio.handleClientRequest(meeting, false);
|
|
252
|
-
assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
|
|
188
|
+
beforeEach(async () => {
|
|
189
|
+
audio.handleLocalTrackChange(meeting);
|
|
190
|
+
video.handleLocalTrackChange(meeting);
|
|
253
191
|
|
|
254
|
-
|
|
255
|
-
audio.handleClientRequest(meeting, false);
|
|
256
|
-
assert.calledWith(meeting.mediaProperties.audioTrack.setMuted, false);
|
|
192
|
+
await testUtils.flushPromises();
|
|
257
193
|
});
|
|
258
194
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
|
|
195
|
+
const simulateAudioMuteChange = async (muteValue) => {
|
|
196
|
+
meeting.mediaProperties.audioTrack.muted = muteValue;
|
|
197
|
+
audio.handleLocalTrackMuteStateChange(meeting, muteValue);
|
|
263
198
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
|
|
199
|
+
await testUtils.flushPromises();
|
|
200
|
+
}
|
|
267
201
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
202
|
+
const simulateVideoMuteChange = async (muteValue) => {
|
|
203
|
+
meeting.mediaProperties.videoTrack.muted = muteValue;
|
|
204
|
+
video.handleLocalTrackMuteStateChange(meeting, muteValue);
|
|
271
205
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
|
|
275
|
-
});
|
|
206
|
+
await testUtils.flushPromises();
|
|
207
|
+
}
|
|
276
208
|
|
|
277
|
-
it('returns correct value in isMuted()
|
|
209
|
+
it('returns correct value in isMuted() methods after local track is muted/unmuted', async () => {
|
|
278
210
|
// mute
|
|
279
|
-
|
|
280
|
-
|
|
211
|
+
await simulateAudioMuteChange(true);
|
|
281
212
|
assert.isTrue(audio.isMuted());
|
|
282
|
-
assert.isTrue(audio.isSelf());
|
|
283
213
|
|
|
284
214
|
// unmute
|
|
285
|
-
|
|
286
|
-
|
|
215
|
+
await simulateAudioMuteChange(false);
|
|
287
216
|
assert.isFalse(audio.isMuted());
|
|
288
|
-
assert.isFalse(audio.isSelf());
|
|
289
217
|
});
|
|
290
218
|
|
|
291
219
|
it('does remote unmute when unmuting and remote mute is on', async () => {
|
|
@@ -293,14 +221,13 @@ describe('plugin-meetings', () => {
|
|
|
293
221
|
audio.handleServerRemoteMuteUpdate(meeting, true, true);
|
|
294
222
|
|
|
295
223
|
// unmute
|
|
296
|
-
await
|
|
224
|
+
await simulateAudioMuteChange(false);
|
|
297
225
|
|
|
298
226
|
// check that remote unmute was sent to server
|
|
299
227
|
assert.calledOnce(meeting.members.muteMember);
|
|
300
228
|
assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, true);
|
|
301
229
|
|
|
302
230
|
assert.isFalse(audio.isMuted());
|
|
303
|
-
assert.isFalse(audio.isSelf());
|
|
304
231
|
});
|
|
305
232
|
|
|
306
233
|
it('does video remote unmute when unmuting and remote mute is on', async () => {
|
|
@@ -308,14 +235,13 @@ describe('plugin-meetings', () => {
|
|
|
308
235
|
video.handleServerRemoteMuteUpdate(meeting, true, true);
|
|
309
236
|
|
|
310
237
|
// unmute
|
|
311
|
-
await
|
|
238
|
+
await simulateVideoMuteChange(false);
|
|
312
239
|
|
|
313
240
|
// check that remote unmute was sent to server
|
|
314
241
|
assert.calledOnce(meeting.members.muteMember);
|
|
315
242
|
assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, false);
|
|
316
243
|
|
|
317
244
|
assert.isFalse(video.isMuted());
|
|
318
|
-
assert.isFalse(video.isSelf());
|
|
319
245
|
});
|
|
320
246
|
|
|
321
247
|
it('does not video remote unmute when unmuting and remote mute is off', async () => {
|
|
@@ -323,63 +249,35 @@ describe('plugin-meetings', () => {
|
|
|
323
249
|
video.handleServerRemoteMuteUpdate(meeting, false, true);
|
|
324
250
|
|
|
325
251
|
// unmute
|
|
326
|
-
await
|
|
252
|
+
await simulateVideoMuteChange(false);
|
|
327
253
|
|
|
328
|
-
// check that remote unmute was sent to server
|
|
254
|
+
// check that remote unmute was not sent to server
|
|
329
255
|
assert.notCalled(meeting.members.muteMember);
|
|
330
256
|
|
|
331
257
|
assert.isFalse(video.isMuted());
|
|
332
|
-
assert.isFalse(video.isSelf());
|
|
333
258
|
});
|
|
334
259
|
|
|
335
|
-
it('
|
|
336
|
-
|
|
260
|
+
it('calls setServerMuted with "clientRequestFailed" when server request for local mute fails', async () => {
|
|
261
|
+
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().rejects(new Error('fake error'));
|
|
337
262
|
|
|
338
|
-
|
|
263
|
+
await simulateAudioMuteChange(true);
|
|
339
264
|
|
|
340
|
-
|
|
341
|
-
new Promise((resolve) => {
|
|
342
|
-
serverResponseResolve = resolve;
|
|
343
|
-
})
|
|
344
|
-
);
|
|
345
|
-
|
|
346
|
-
audio.handleClientRequest(meeting, true).then(() => {
|
|
347
|
-
clientPromiseResolved = true;
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
// do a small delay to make sure that the client promise doesn't resolve in that time
|
|
351
|
-
await testUtils.waitUntil(200);
|
|
352
|
-
assert.isFalse(clientPromiseResolved);
|
|
353
|
-
|
|
354
|
-
meeting.locusInfo.onDeltaLocus.resetHistory();
|
|
355
|
-
|
|
356
|
-
// now allow the server response to arrive, this should trigger the client promise to get resolved
|
|
357
|
-
serverResponseResolve(fakeLocus);
|
|
358
|
-
await testUtils.flushPromises();
|
|
359
|
-
|
|
360
|
-
assert.isTrue(clientPromiseResolved);
|
|
361
|
-
assert.calledOnceWithExactly(meeting.locusInfo.onDeltaLocus, fakeLocus);
|
|
265
|
+
assert.calledOnceWithExactly(meeting.mediaProperties.audioTrack.setServerMuted , false, 'clientRequestFailed');
|
|
362
266
|
});
|
|
363
267
|
|
|
364
|
-
it('
|
|
365
|
-
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
|
|
366
|
-
new Promise((resolve, reject) => {
|
|
367
|
-
reject();
|
|
368
|
-
})
|
|
369
|
-
);
|
|
370
|
-
|
|
371
|
-
assert.isRejected(audio.handleClientRequest(meeting, true));
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('rejects client request promise if server request for remote mute fails', async () => {
|
|
268
|
+
it('calls setServerMuted with "clientRequestFailed" if server request for remote mute fails', async () => {
|
|
375
269
|
// we only send remote mute requests when we're unmuting, so first we need to do a remote mute
|
|
376
270
|
audio.handleServerRemoteMuteUpdate(meeting, true, true);
|
|
377
271
|
|
|
272
|
+
await testUtils.flushPromises();
|
|
273
|
+
|
|
378
274
|
// setup the stub to simulate server error response
|
|
379
275
|
meeting.members.muteMember = sinon.stub().rejects();
|
|
276
|
+
meeting.mediaProperties.audioTrack.setServerMuted.resetHistory();
|
|
277
|
+
|
|
278
|
+
await simulateAudioMuteChange(false);
|
|
380
279
|
|
|
381
|
-
|
|
382
|
-
await assert.isRejected(audio.handleClientRequest(meeting, false));
|
|
280
|
+
assert.calledOnceWithExactly(meeting.mediaProperties.audioTrack.setServerMuted , true, 'clientRequestFailed');
|
|
383
281
|
|
|
384
282
|
// even though remote mute update in the server failed, isMuted() should still return true,
|
|
385
283
|
// because of local mute
|
|
@@ -395,12 +293,13 @@ describe('plugin-meetings', () => {
|
|
|
395
293
|
})
|
|
396
294
|
);
|
|
397
295
|
|
|
398
|
-
//
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
296
|
+
// the track is initially unmuted
|
|
297
|
+
// simulate many mute changes with the last one matching the first one
|
|
298
|
+
await simulateAudioMuteChange(true);
|
|
299
|
+
await simulateAudioMuteChange(false);
|
|
300
|
+
await simulateAudioMuteChange(true);
|
|
301
|
+
await simulateAudioMuteChange(false);
|
|
302
|
+
await simulateAudioMuteChange(true);
|
|
404
303
|
|
|
405
304
|
// so far there should have been only 1 request to server (because our stub hasn't resolved yet
|
|
406
305
|
// and MuteState sends only 1 server request at a time)
|
|
@@ -415,7 +314,7 @@ describe('plugin-meetings', () => {
|
|
|
415
314
|
assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
|
|
416
315
|
});
|
|
417
316
|
|
|
418
|
-
it('queues up server requests when multiple
|
|
317
|
+
it('queues up server requests when multiple mute changes happen to local track', async () => {
|
|
419
318
|
let serverResponseResolve;
|
|
420
319
|
|
|
421
320
|
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
|
|
@@ -424,18 +323,9 @@ describe('plugin-meetings', () => {
|
|
|
424
323
|
})
|
|
425
324
|
);
|
|
426
325
|
|
|
427
|
-
let firstClientPromiseResolved = false;
|
|
428
|
-
let secondClientPromiseResolved = false;
|
|
429
|
-
|
|
430
326
|
// 2 client requests, one after another without waiting for first one to resolve
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
});
|
|
434
|
-
audio.handleClientRequest(meeting, false).then(() => {
|
|
435
|
-
secondClientPromiseResolved = true;
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
await testUtils.flushPromises();
|
|
327
|
+
await simulateAudioMuteChange(true);
|
|
328
|
+
await simulateAudioMuteChange(false);
|
|
439
329
|
|
|
440
330
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
441
331
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
|
|
@@ -443,55 +333,32 @@ describe('plugin-meetings', () => {
|
|
|
443
333
|
// now allow the first request to complete
|
|
444
334
|
serverResponseResolve();
|
|
445
335
|
await testUtils.flushPromises();
|
|
446
|
-
assert.isTrue(firstClientPromiseResolved);
|
|
447
336
|
|
|
448
337
|
// that should trigger the second server request to be sent
|
|
449
338
|
assert.calledTwice(MeetingUtil.remoteUpdateAudioVideo);
|
|
450
339
|
assert.deepEqual([meeting, false, undefined], MeetingUtil.remoteUpdateAudioVideo.getCall(1).args);
|
|
451
340
|
|
|
452
341
|
serverResponseResolve();
|
|
453
|
-
await testUtils.flushPromises();
|
|
454
|
-
|
|
455
|
-
assert.isTrue(secondClientPromiseResolved);
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('rejects client request to unmute if hard mute is used', (done) => {
|
|
459
|
-
audio.handleServerRemoteMuteUpdate(meeting, true, false);
|
|
460
|
-
|
|
461
|
-
audio
|
|
462
|
-
.handleClientRequest(meeting, false)
|
|
463
|
-
.then(() => {
|
|
464
|
-
done(new Error('expected handleClientRequest to fail, but it did not!'));
|
|
465
|
-
})
|
|
466
|
-
.catch((e) => {
|
|
467
|
-
assert.isTrue(e instanceof PermissionError);
|
|
468
|
-
done();
|
|
469
|
-
});
|
|
470
342
|
});
|
|
471
343
|
|
|
472
344
|
it('does not send remote mute for video', async () => {
|
|
473
345
|
// mute
|
|
474
|
-
await
|
|
346
|
+
await simulateVideoMuteChange(true);
|
|
475
347
|
|
|
476
348
|
assert.isTrue(video.isMuted());
|
|
477
|
-
assert.isTrue(video.isSelf());
|
|
478
349
|
|
|
479
350
|
// check local mute is done, but not remote one
|
|
480
|
-
assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, true);
|
|
481
351
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
|
|
482
352
|
assert.notCalled(meeting.members.muteMember);
|
|
483
353
|
|
|
484
|
-
meeting.mediaProperties.videoTrack.setMuted.resetHistory();
|
|
485
354
|
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
486
355
|
meeting.members.muteMember.resetHistory();
|
|
487
356
|
|
|
488
357
|
// unmute
|
|
489
|
-
await
|
|
358
|
+
await simulateVideoMuteChange(false);
|
|
490
359
|
|
|
491
360
|
assert.isFalse(video.isMuted());
|
|
492
|
-
assert.isFalse(video.isSelf());
|
|
493
361
|
|
|
494
|
-
assert.calledWith(meeting.mediaProperties.videoTrack.setMuted, false);
|
|
495
362
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
|
|
496
363
|
assert.notCalled(meeting.members.muteMember);
|
|
497
364
|
});
|
|
@@ -502,243 +369,220 @@ describe('plugin-meetings', () => {
|
|
|
502
369
|
meeting.video = video;
|
|
503
370
|
|
|
504
371
|
// mute audio -> the call to remoteUpdateAudioVideo should have video undefined
|
|
505
|
-
await
|
|
372
|
+
await simulateAudioMuteChange(true);
|
|
506
373
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
|
|
507
374
|
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
508
375
|
|
|
509
376
|
// now mute video -> the call to remoteUpdateAudioVideo should have mute for video and undefined for audio
|
|
510
|
-
await
|
|
377
|
+
await simulateVideoMuteChange(true);
|
|
511
378
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
|
|
512
379
|
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
513
380
|
|
|
514
381
|
// now unmute the audio -> the call to remoteUpdateAudioVideo should have video undefined
|
|
515
|
-
await
|
|
382
|
+
await simulateAudioMuteChange(false);
|
|
516
383
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
|
|
517
384
|
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
518
385
|
|
|
519
386
|
// unmute video -> the call to remoteUpdateAudioVideo should have both audio undefined
|
|
520
|
-
await
|
|
387
|
+
await simulateVideoMuteChange(false);
|
|
521
388
|
assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
|
|
522
389
|
});
|
|
523
390
|
});
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
describe('#init, #handleLocalTrackChange', () => {
|
|
528
|
-
let meeting;
|
|
529
|
-
let muteState;
|
|
530
|
-
let setServerMutedSpy;
|
|
531
|
-
let setMutedSpy, setUnmuteAllowedSpy;
|
|
532
|
-
const fakeLocus = {info: 'this is a fake locus'};
|
|
533
|
-
|
|
534
|
-
const createFakeLocalTrack = (id, muted) => {
|
|
535
|
-
return {
|
|
536
|
-
id,
|
|
537
|
-
setMuted: sinon.stub(),
|
|
538
|
-
setServerMuted: sinon.stub(),
|
|
539
|
-
setUnmuteAllowed: sinon.stub(),
|
|
540
|
-
muted,
|
|
541
|
-
};
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
const setupMeeting = (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
|
|
545
|
-
const remoteMuteField = mediaType === AUDIO ? 'remoteMuted' : 'remoteVideoMuted';
|
|
546
|
-
|
|
547
|
-
meeting = {
|
|
548
|
-
mediaProperties: {
|
|
549
|
-
audioTrack: defineTracks ? createFakeLocalTrack('fake audio track', muted) : undefined,
|
|
550
|
-
videoTrack: defineTracks ? createFakeLocalTrack('fake video track', muted) : undefined,
|
|
551
|
-
},
|
|
552
|
-
[remoteMuteField]: remoteMuted,
|
|
553
|
-
unmuteAllowed: true,
|
|
554
|
-
unmuteVideoAllowed: true,
|
|
555
|
-
|
|
556
|
-
locusInfo: {
|
|
557
|
-
onFullLocus: sinon.stub(),
|
|
558
|
-
},
|
|
559
|
-
members: {
|
|
560
|
-
selfId: 'fake self id',
|
|
561
|
-
muteMember: sinon.stub().resolves(),
|
|
562
|
-
},
|
|
563
|
-
};
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
const setup = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
|
|
567
|
-
|
|
568
|
-
setupMeeting(mediaType, remoteMuted, muted, defineTracks);
|
|
569
|
-
|
|
570
|
-
const direction = mediaType === AUDIO ? {sendAudio: true} : {sendVideo: true};
|
|
571
391
|
|
|
572
|
-
|
|
392
|
+
describe('#init, #handleLocalTrackChange', () => {
|
|
393
|
+
let meeting;
|
|
394
|
+
let muteState;
|
|
395
|
+
let setServerMutedSpy;
|
|
396
|
+
let setMutedSpy, setUnmuteAllowedSpy;
|
|
397
|
+
|
|
398
|
+
const setupMeeting = (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
|
|
399
|
+
const remoteMuteField = mediaType === AUDIO ? 'remoteMuted' : 'remoteVideoMuted';
|
|
400
|
+
|
|
401
|
+
meeting = {
|
|
402
|
+
mediaProperties: {
|
|
403
|
+
audioTrack: defineTracks ? createFakeLocalTrack('fake audio track', muted) : undefined,
|
|
404
|
+
videoTrack: defineTracks ? createFakeLocalTrack('fake video track', muted) : undefined,
|
|
405
|
+
},
|
|
406
|
+
[remoteMuteField]: remoteMuted,
|
|
407
|
+
unmuteAllowed: true,
|
|
408
|
+
unmuteVideoAllowed: true,
|
|
409
|
+
|
|
410
|
+
locusInfo: {
|
|
411
|
+
onFullLocus: sinon.stub(),
|
|
412
|
+
},
|
|
413
|
+
members: {
|
|
414
|
+
selfId: 'fake self id',
|
|
415
|
+
muteMember: sinon.stub().resolves(),
|
|
416
|
+
},
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const setup = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
|
|
421
|
+
|
|
422
|
+
setupMeeting(mediaType, remoteMuted, muted, defineTracks);
|
|
423
|
+
|
|
424
|
+
muteState = createMuteState(mediaType, meeting, true);
|
|
425
|
+
muteState.handleLocalTrackChange(meeting);
|
|
573
426
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
const setupSpies = (mediaType) => {
|
|
580
|
-
setUnmuteAllowedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setUnmuteAllowed : meeting.mediaProperties.videoTrack?.setUnmuteAllowed;
|
|
581
|
-
setServerMutedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setServerMuted : meeting.mediaProperties.videoTrack?.setServerMuted;
|
|
582
|
-
setMutedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setMuted : meeting.mediaProperties.videoTrack?.setMuted;
|
|
583
|
-
|
|
584
|
-
clearSpies();
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
const clearSpies = () => {
|
|
588
|
-
setUnmuteAllowedSpy?.resetHistory();
|
|
589
|
-
setServerMutedSpy?.resetHistory();
|
|
590
|
-
setMutedSpy?.resetHistory();
|
|
591
|
-
};
|
|
592
|
-
const tests = [
|
|
593
|
-
{mediaType: AUDIO, title: 'audio'},
|
|
594
|
-
{mediaType: VIDEO, title: 'video'}
|
|
595
|
-
];
|
|
596
|
-
|
|
597
|
-
tests.forEach(({mediaType, title}) =>
|
|
598
|
-
describe(title, () => {
|
|
599
|
-
let originalRemoteUpdateAudioVideo;
|
|
600
|
-
|
|
601
|
-
beforeEach(() => {
|
|
602
|
-
originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
|
|
603
|
-
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves({info: 'fake locus'});
|
|
604
|
-
});
|
|
427
|
+
await testUtils.flushPromises();
|
|
605
428
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
429
|
+
MeetingUtil.remoteUpdateAudioVideo.resetHistory();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const setupSpies = (mediaType) => {
|
|
433
|
+
setUnmuteAllowedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setUnmuteAllowed : meeting.mediaProperties.videoTrack?.setUnmuteAllowed;
|
|
434
|
+
setServerMutedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setServerMuted : meeting.mediaProperties.videoTrack?.setServerMuted;
|
|
435
|
+
setMutedSpy = mediaType === AUDIO ? meeting.mediaProperties.audioTrack?.setMuted : meeting.mediaProperties.videoTrack?.setMuted;
|
|
436
|
+
|
|
437
|
+
clearSpies();
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
const clearSpies = () => {
|
|
441
|
+
setUnmuteAllowedSpy?.resetHistory();
|
|
442
|
+
setServerMutedSpy?.resetHistory();
|
|
443
|
+
setMutedSpy?.resetHistory();
|
|
444
|
+
};
|
|
445
|
+
const tests = [
|
|
446
|
+
{mediaType: AUDIO, title: 'audio'},
|
|
447
|
+
{mediaType: VIDEO, title: 'video'}
|
|
448
|
+
];
|
|
449
|
+
|
|
450
|
+
tests.forEach(({mediaType, title}) =>
|
|
451
|
+
describe(title, () => {
|
|
452
|
+
let originalRemoteUpdateAudioVideo;
|
|
453
|
+
|
|
454
|
+
beforeEach(() => {
|
|
455
|
+
originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
|
|
456
|
+
MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves({info: 'fake locus'});
|
|
457
|
+
});
|
|
610
458
|
|
|
611
|
-
|
|
459
|
+
afterEach(() => {
|
|
460
|
+
MeetingUtil.remoteUpdateAudioVideo = originalRemoteUpdateAudioVideo;
|
|
461
|
+
sinon.restore();
|
|
462
|
+
});
|
|
612
463
|
|
|
613
|
-
|
|
614
|
-
await setup(mediaType);
|
|
615
|
-
const spy = sinon.spy(muteState, 'init');
|
|
616
|
-
muteState.handleLocalTrackChange(meeting);
|
|
617
|
-
assert.calledOnceWithExactly(spy, meeting);
|
|
618
|
-
});
|
|
619
|
-
});
|
|
464
|
+
describe('#handleLocalTrackChange',() => {
|
|
620
465
|
|
|
621
|
-
|
|
466
|
+
it('calls init()', async () => {
|
|
467
|
+
await setup(mediaType);
|
|
468
|
+
const spy = sinon.spy(muteState, 'init');
|
|
469
|
+
muteState.handleLocalTrackChange(meeting);
|
|
470
|
+
assert.calledOnceWithExactly(spy, meeting);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
622
473
|
|
|
623
|
-
|
|
624
|
-
const setupWithoutInit = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
|
|
474
|
+
describe('#init', () => {
|
|
625
475
|
|
|
626
|
-
|
|
476
|
+
// does the setup by calling new MuteState() so that MuteState.init() doesn't get called
|
|
477
|
+
const setupWithoutInit = async (mediaType, remoteMuted = false, muted = false, defineTracks = true) => {
|
|
627
478
|
|
|
628
|
-
|
|
629
|
-
}
|
|
479
|
+
setupMeeting(mediaType, remoteMuted, muted, defineTracks);
|
|
630
480
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
setupSpies(mediaType);
|
|
481
|
+
muteState = new MuteState(mediaType, meeting, true);
|
|
482
|
+
}
|
|
634
483
|
|
|
635
|
-
|
|
484
|
+
it('nothing goes bad when track is undefined', async () => {
|
|
485
|
+
await setupWithoutInit(mediaType, false, false, false);
|
|
486
|
+
setupSpies(mediaType);
|
|
636
487
|
|
|
637
|
-
|
|
638
|
-
});
|
|
488
|
+
muteState.init(meeting);
|
|
639
489
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
setupSpies(mediaType);
|
|
490
|
+
assert.isTrue(muteState.state.client.localMute);
|
|
491
|
+
});
|
|
643
492
|
|
|
644
|
-
|
|
493
|
+
it('tests when track muted is true and remoteMuted is false', async () => {
|
|
494
|
+
await setupWithoutInit(mediaType, false, true);
|
|
495
|
+
setupSpies(mediaType);
|
|
645
496
|
|
|
646
|
-
|
|
647
|
-
assert.notCalled(setServerMutedSpy);
|
|
648
|
-
assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
|
|
649
|
-
assert.isTrue(muteState.state.client.localMute);
|
|
650
|
-
});
|
|
497
|
+
muteState.init(meeting);
|
|
651
498
|
|
|
499
|
+
assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
|
|
500
|
+
assert.notCalled(setServerMutedSpy);
|
|
501
|
+
assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
|
|
502
|
+
assert.isTrue(muteState.state.client.localMute);
|
|
503
|
+
});
|
|
652
504
|
|
|
653
|
-
it('tests when track muted is false and remoteMuted is false', async () => {
|
|
654
|
-
await setupWithoutInit(mediaType, false, false);
|
|
655
|
-
setupSpies(mediaType);
|
|
656
|
-
muteState.state.server.localMute = true;
|
|
657
505
|
|
|
658
|
-
|
|
506
|
+
it('tests when track muted is false and remoteMuted is false', async () => {
|
|
507
|
+
await setupWithoutInit(mediaType, false, false);
|
|
508
|
+
setupSpies(mediaType);
|
|
509
|
+
muteState.state.server.localMute = true;
|
|
659
510
|
|
|
660
|
-
|
|
661
|
-
assert.notCalled(setServerMutedSpy);
|
|
662
|
-
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
663
|
-
assert.isFalse(muteState.state.client.localMute);
|
|
664
|
-
});
|
|
511
|
+
muteState.init(meeting);
|
|
665
512
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
513
|
+
assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
|
|
514
|
+
assert.notCalled(setServerMutedSpy);
|
|
515
|
+
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
516
|
+
assert.isFalse(muteState.state.client.localMute);
|
|
517
|
+
});
|
|
670
518
|
|
|
671
|
-
|
|
519
|
+
it('tests when remoteMuted is true', async () => {
|
|
520
|
+
// testing that muteLocalTrack is called
|
|
521
|
+
await setupWithoutInit(mediaType, true);
|
|
522
|
+
setupSpies(mediaType);
|
|
672
523
|
|
|
673
|
-
|
|
674
|
-
assert.calledOnceWithExactly(setServerMutedSpy, true, 'remotelyMuted');
|
|
675
|
-
});
|
|
676
|
-
});
|
|
524
|
+
muteState.init(meeting);
|
|
677
525
|
|
|
678
|
-
|
|
526
|
+
assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
|
|
527
|
+
assert.calledOnceWithExactly(setServerMutedSpy, true, 'remotelyMuted');
|
|
528
|
+
});
|
|
529
|
+
});
|
|
679
530
|
|
|
680
|
-
|
|
681
|
-
await setup(mediaType, false, false);
|
|
682
|
-
muteState.ignoreMuteStateChange = true;
|
|
531
|
+
describe('#handleLocalTrackMuteStateChange', () => {
|
|
683
532
|
|
|
684
|
-
|
|
685
|
-
|
|
533
|
+
it('checks when ignoreMuteStateChange is true nothing changes', async () => {
|
|
534
|
+
await setup(mediaType, false, false);
|
|
535
|
+
muteState.ignoreMuteStateChange = true;
|
|
686
536
|
|
|
687
|
-
|
|
688
|
-
|
|
537
|
+
muteState.handleLocalTrackMuteStateChange(meeting, true);
|
|
538
|
+
assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
|
|
689
539
|
|
|
690
|
-
|
|
691
|
-
|
|
540
|
+
assert.isFalse(muteState.state.client.localMute);
|
|
541
|
+
});
|
|
692
542
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
assert.called(MeetingUtil.remoteUpdateAudioVideo);
|
|
696
|
-
});
|
|
543
|
+
it('tests localMute - true to false', async () => {
|
|
544
|
+
await setup(mediaType, false, true);
|
|
697
545
|
|
|
698
|
-
|
|
699
|
-
|
|
546
|
+
muteState.handleLocalTrackMuteStateChange(meeting, false);
|
|
547
|
+
assert.equal(muteState.state.client.localMute, false);
|
|
548
|
+
assert.called(MeetingUtil.remoteUpdateAudioVideo);
|
|
549
|
+
});
|
|
700
550
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
assert.called(MeetingUtil.remoteUpdateAudioVideo);
|
|
704
|
-
});
|
|
705
|
-
});
|
|
551
|
+
it('tests localMute - false to true', async () => {
|
|
552
|
+
await setup(mediaType, false, false);
|
|
706
553
|
|
|
707
|
-
|
|
554
|
+
muteState.handleLocalTrackMuteStateChange(meeting, true);
|
|
555
|
+
assert.equal(muteState.state.client.localMute, true);
|
|
556
|
+
assert.called(MeetingUtil.remoteUpdateAudioVideo);
|
|
557
|
+
});
|
|
558
|
+
});
|
|
708
559
|
|
|
709
|
-
|
|
710
|
-
sinon.restore();
|
|
711
|
-
});
|
|
560
|
+
describe('#applyClientStateLocally', () => {
|
|
712
561
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
muteState.sdkOwnsLocalTrack= false;
|
|
562
|
+
afterEach(() => {
|
|
563
|
+
sinon.restore();
|
|
564
|
+
});
|
|
717
565
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
});
|
|
566
|
+
it('calls setServerMuted on the track', async () => {
|
|
567
|
+
await setup(mediaType);
|
|
568
|
+
setupSpies(mediaType);
|
|
722
569
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
570
|
+
muteState.applyClientStateLocally(meeting, 'somereason');
|
|
571
|
+
assert.calledOnceWithExactly(setServerMutedSpy, muteState.state.client.localMute, 'somereason');
|
|
572
|
+
assert.notCalled(setMutedSpy);
|
|
573
|
+
});
|
|
727
574
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
});
|
|
575
|
+
it('nothing explodes when tracks are undefined', async () => {
|
|
576
|
+
await setup(mediaType, false, false, false);
|
|
577
|
+
setupSpies(mediaType);
|
|
732
578
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
muteState.sdkOwnsLocalTrack= true;
|
|
579
|
+
muteState.applyClientStateLocally(meeting, 'somereason');
|
|
580
|
+
});
|
|
581
|
+
});
|
|
737
582
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
583
|
+
})
|
|
584
|
+
);
|
|
585
|
+
});
|
|
741
586
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
});
|
|
587
|
+
});
|
|
588
|
+
});
|