@webex/plugin-meetings 3.8.0-next.5 → 3.8.0-next.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +14 -1
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +2 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +52 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +28 -10
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +20 -1
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/index.js +3 -15
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +11 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +544 -324
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +26 -23
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +0 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +30 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +27 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +359 -60
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +69 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +14 -0
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +3 -0
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +9 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/clusterReachability.js +63 -27
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +112 -47
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +14 -0
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/request.js +19 -3
- package/dist/reachability/request.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/util.js +5 -5
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +45 -27
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js +17 -0
- package/dist/roap/types.js.map +1 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/constants.d.ts +10 -0
- package/dist/types/controls-options-manager/enums.d.ts +3 -1
- package/dist/types/controls-options-manager/types.d.ts +7 -1
- package/dist/types/locus-info/index.d.ts +1 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +10 -0
- package/dist/types/meeting/index.d.ts +50 -3
- package/dist/types/meeting/muteState.d.ts +0 -1
- package/dist/types/meeting/request.d.ts +12 -1
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +8 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +80 -0
- package/dist/types/meetings/index.d.ts +29 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/metrics/constants.d.ts +9 -0
- package/dist/types/reachability/clusterReachability.d.ts +15 -7
- package/dist/types/reachability/index.d.ts +10 -1
- package/dist/types/reachability/reachability.types.d.ts +5 -0
- package/dist/types/roap/index.d.ts +3 -2
- package/dist/types/roap/turnDiscovery.d.ts +5 -17
- package/dist/types/roap/types.d.ts +16 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/config.ts +1 -0
- package/src/constants.ts +17 -0
- package/src/controls-options-manager/enums.ts +2 -0
- package/src/controls-options-manager/types.ts +11 -1
- package/src/controls-options-manager/util.ts +62 -0
- package/src/locus-info/controlsUtils.ts +44 -14
- package/src/locus-info/index.ts +23 -1
- package/src/media/index.ts +5 -21
- package/src/meeting/in-meeting-actions.ts +20 -0
- package/src/meeting/index.ts +351 -99
- package/src/meeting/locusMediaRequest.ts +33 -23
- package/src/meeting/muteState.ts +0 -2
- package/src/meeting/request.ts +36 -1
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +27 -2
- package/src/meeting-info/meeting-info-v2.ts +247 -6
- package/src/meetings/index.ts +87 -1
- package/src/meetings/util.ts +18 -0
- package/src/member/index.ts +11 -0
- package/src/member/util.ts +3 -0
- package/src/metrics/constants.ts +9 -0
- package/src/reachability/clusterReachability.ts +73 -26
- package/src/reachability/index.ts +70 -1
- package/src/reachability/reachability.types.ts +6 -0
- package/src/reachability/request.ts +7 -0
- package/src/reconnection-manager/index.ts +2 -2
- package/src/recording-controller/util.ts +17 -13
- package/src/roap/index.ts +3 -7
- package/src/roap/turnDiscovery.ts +34 -39
- package/src/roap/types.ts +23 -0
- package/test/unit/spec/controls-options-manager/util.js +120 -0
- package/test/unit/spec/locus-info/controlsUtils.js +103 -9
- package/test/unit/spec/locus-info/index.js +28 -0
- package/test/unit/spec/media/index.ts +6 -16
- package/test/unit/spec/meeting/in-meeting-actions.ts +13 -4
- package/test/unit/spec/meeting/index.js +558 -145
- package/test/unit/spec/meeting/locusMediaRequest.ts +101 -88
- package/test/unit/spec/meeting/muteState.js +0 -2
- package/test/unit/spec/meeting/request.js +32 -1
- package/test/unit/spec/meeting/utils.js +123 -18
- package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
- package/test/unit/spec/meetings/index.js +96 -1
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/reachability/clusterReachability.ts +88 -56
- package/test/unit/spec/reachability/index.ts +101 -0
- package/test/unit/spec/reachability/request.js +47 -2
- package/test/unit/spec/reconnection-manager/index.js +4 -4
- package/test/unit/spec/roap/turnDiscovery.ts +110 -28
@@ -1,14 +1,18 @@
|
|
1
1
|
import 'jsdom-global/register';
|
2
2
|
import sinon from 'sinon';
|
3
3
|
import {assert} from '@webex/test-helper-chai';
|
4
|
-
import {
|
5
|
-
|
4
|
+
import {cloneDeep} from 'lodash';
|
5
|
+
import {EventEmitter} from 'events';
|
6
6
|
import MockWebex from '@webex/test-helper-mock-webex';
|
7
7
|
import Meetings from '@webex/plugin-meetings';
|
8
|
-
import {
|
8
|
+
import {
|
9
|
+
LocalMuteRequest,
|
10
|
+
LocusMediaRequest,
|
11
|
+
RoapRequest,
|
12
|
+
} from '@webex/plugin-meetings/src/meeting/locusMediaRequest';
|
9
13
|
import testUtils from '../../../utils/testUtils';
|
10
|
-
import {
|
11
|
-
import {
|
14
|
+
import {Defer} from '@webex/common';
|
15
|
+
import {IP_VERSION} from '../../../../src/constants';
|
12
16
|
|
13
17
|
describe('LocusMediaRequest.send()', () => {
|
14
18
|
let locusMediaRequest: LocusMediaRequest;
|
@@ -16,10 +20,10 @@ describe('LocusMediaRequest.send()', () => {
|
|
16
20
|
let mockWebex;
|
17
21
|
|
18
22
|
const fakeLocusResponse = {
|
19
|
-
locus: {
|
23
|
+
locus: {something: 'whatever'},
|
20
24
|
};
|
21
25
|
|
22
|
-
const exampleRoapRequestBody:RoapRequest = {
|
26
|
+
const exampleRoapRequestBody: RoapRequest = {
|
23
27
|
type: 'RoapMessage',
|
24
28
|
mediaId: 'mediaId',
|
25
29
|
selfUrl: 'fakeMeetingSelfUrl',
|
@@ -31,8 +35,11 @@ describe('LocusMediaRequest.send()', () => {
|
|
31
35
|
tieBreaker: 0xfffffffe,
|
32
36
|
},
|
33
37
|
reachability: {
|
34
|
-
'wjfkm.wjfkm.*': {udp:{reachable: true}, tcp:{reachable:false}},
|
35
|
-
'1eb65fdf-9643-417f-9974-ad72cae0e10f.59268c12-7a04-4b23-a1a1-4c74be03019a.*': {
|
38
|
+
'wjfkm.wjfkm.*': {udp: {reachable: true}, tcp: {reachable: false}},
|
39
|
+
'1eb65fdf-9643-417f-9974-ad72cae0e10f.59268c12-7a04-4b23-a1a1-4c74be03019a.*': {
|
40
|
+
udp: {reachable: false},
|
41
|
+
tcp: {reachable: true},
|
42
|
+
},
|
36
43
|
},
|
37
44
|
clientMediaPreferences: {
|
38
45
|
preferTranscoding: false,
|
@@ -45,19 +52,22 @@ describe('LocusMediaRequest.send()', () => {
|
|
45
52
|
reachability: {
|
46
53
|
version: '1',
|
47
54
|
result: 'some fake reachability result',
|
48
|
-
}
|
49
|
-
}
|
55
|
+
},
|
56
|
+
},
|
50
57
|
};
|
51
58
|
|
52
|
-
const createExpectedRoapBody = (
|
59
|
+
const createExpectedRoapBody = (
|
60
|
+
expectedMessageType,
|
61
|
+
expectedMute: {audioMuted: boolean; videoMuted: boolean}
|
62
|
+
) => {
|
53
63
|
return {
|
54
|
-
device: {
|
64
|
+
device: {url: 'deviceUrl', deviceType: 'deviceType', regionCode: 'regionCode'},
|
55
65
|
correlationId: 'correlationId',
|
56
66
|
localMedias: [
|
57
67
|
{
|
58
68
|
localSdp: `{"audioMuted":${expectedMute.audioMuted},"videoMuted":${expectedMute.videoMuted},"roapMessage":{"messageType":"${expectedMessageType}","sdps":["sdp"],"version":"2","seq":1,"tieBreaker":4294967294},"reachability":{"wjfkm.wjfkm.*":{"udp":{"reachable":true},"tcp":{"reachable":false}},"1eb65fdf-9643-417f-9974-ad72cae0e10f.59268c12-7a04-4b23-a1a1-4c74be03019a.*":{"udp":{"reachable":false},"tcp":{"reachable":true}}}}`,
|
59
|
-
mediaId: 'mediaId'
|
60
|
-
}
|
69
|
+
mediaId: 'mediaId',
|
70
|
+
},
|
61
71
|
],
|
62
72
|
clientMediaPreferences: {
|
63
73
|
preferTranscoding: false,
|
@@ -65,24 +75,27 @@ describe('LocusMediaRequest.send()', () => {
|
|
65
75
|
joinCookie: {
|
66
76
|
anycastEntryPoint: 'aws-eu-west-1',
|
67
77
|
clientIpAddress: 'some ip',
|
68
|
-
timeShot: '2023-05-23T08:03:49Z'
|
78
|
+
timeShot: '2023-05-23T08:03:49Z',
|
69
79
|
},
|
70
80
|
reachability: {
|
71
81
|
version: '1',
|
72
82
|
result: 'some fake reachability result',
|
73
|
-
}
|
74
|
-
}
|
83
|
+
},
|
84
|
+
},
|
75
85
|
};
|
76
86
|
};
|
77
87
|
|
78
|
-
const exampleLocalMuteRequestBody:LocalMuteRequest = {
|
88
|
+
const exampleLocalMuteRequestBody: LocalMuteRequest = {
|
79
89
|
type: 'LocalMute',
|
80
90
|
mediaId: 'mediaId',
|
81
91
|
selfUrl: 'fakeMeetingSelfUrl',
|
82
92
|
muteOptions: {},
|
83
93
|
};
|
84
94
|
|
85
|
-
const createExpectedLocalMuteBody = (
|
95
|
+
const createExpectedLocalMuteBody = (
|
96
|
+
expectedMute: {audioMuted: boolean; videoMuted: boolean},
|
97
|
+
sequence = undefined
|
98
|
+
) => {
|
86
99
|
const body: any = {
|
87
100
|
device: {
|
88
101
|
url: 'deviceUrl',
|
@@ -116,33 +129,37 @@ describe('LocusMediaRequest.send()', () => {
|
|
116
129
|
|
117
130
|
mockWebex.internal = {
|
118
131
|
newMetrics: {
|
119
|
-
submitClientEvent: sinon.stub()
|
132
|
+
submitClientEvent: sinon.stub(),
|
120
133
|
},
|
121
134
|
};
|
122
135
|
|
123
|
-
locusMediaRequest = new LocusMediaRequest(
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
136
|
+
locusMediaRequest = new LocusMediaRequest(
|
137
|
+
{
|
138
|
+
device: {
|
139
|
+
url: 'deviceUrl',
|
140
|
+
deviceType: 'deviceType',
|
141
|
+
regionCode: 'regionCode',
|
142
|
+
},
|
143
|
+
correlationId: 'correlationId',
|
144
|
+
meetingId: 'meetingId',
|
145
|
+
preferTranscoding: true,
|
128
146
|
},
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
parent: mockWebex,
|
134
|
-
});
|
147
|
+
{
|
148
|
+
parent: mockWebex,
|
149
|
+
}
|
150
|
+
);
|
135
151
|
webexRequestStub = sinon.stub(locusMediaRequest, 'request').resolves(fakeLocusResponse);
|
136
|
-
})
|
152
|
+
});
|
137
153
|
|
138
|
-
const sendLocalMute = (muteOptions, overrides={}) =>
|
154
|
+
const sendLocalMute = (muteOptions, overrides = {}) =>
|
155
|
+
locusMediaRequest.send({...exampleLocalMuteRequestBody, ...overrides, muteOptions});
|
139
156
|
|
140
157
|
const sendRoapMessage = (messageType) => {
|
141
158
|
const request = cloneDeep(exampleRoapRequestBody);
|
142
159
|
|
143
160
|
request.roapMessage.messageType = messageType;
|
144
161
|
return locusMediaRequest.send(request);
|
145
|
-
}
|
162
|
+
};
|
146
163
|
|
147
164
|
/** Helper function that makes sure the LocusMediaRequest.confluenceState is 'created' */
|
148
165
|
const ensureConfluenceCreated = async () => {
|
@@ -150,27 +167,7 @@ describe('LocusMediaRequest.send()', () => {
|
|
150
167
|
|
151
168
|
webexRequestStub.resetHistory();
|
152
169
|
mockWebex.internal.newMetrics.submitClientEvent.resetHistory();
|
153
|
-
}
|
154
|
-
|
155
|
-
const checkMetrics = (expectedMetrics: boolean = true) => {
|
156
|
-
if (expectedMetrics) {
|
157
|
-
assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
|
158
|
-
name: 'client.locus.media.request',
|
159
|
-
options: {
|
160
|
-
meetingId: 'meetingId',
|
161
|
-
},
|
162
|
-
});
|
163
|
-
|
164
|
-
assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
|
165
|
-
name: 'client.locus.media.response',
|
166
|
-
options: {
|
167
|
-
meetingId: 'meetingId',
|
168
|
-
},
|
169
|
-
});
|
170
|
-
} else {
|
171
|
-
assert.notCalled(mockWebex.internal.newMetrics.submitClientEvent);
|
172
|
-
}
|
173
|
-
}
|
170
|
+
};
|
174
171
|
|
175
172
|
it('sends a roap message', async () => {
|
176
173
|
const result = await sendRoapMessage('OFFER');
|
@@ -181,14 +178,19 @@ describe('LocusMediaRequest.send()', () => {
|
|
181
178
|
method: 'PUT',
|
182
179
|
uri: 'fakeMeetingSelfUrl/media',
|
183
180
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: true}),
|
181
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
182
|
+
download: sinon.match.instanceOf(EventEmitter),
|
184
183
|
});
|
185
|
-
|
186
|
-
checkMetrics();
|
187
184
|
});
|
188
185
|
|
189
186
|
it('sends correct metric event when roap message fails', async () => {
|
190
187
|
webexRequestStub.rejects({code: 300, message: 'fake error'});
|
191
|
-
|
188
|
+
|
189
|
+
const promise = sendRoapMessage('OFFER');
|
190
|
+
await assert.isRejected(promise);
|
191
|
+
|
192
|
+
const error = await promise.catch((err) => err);
|
193
|
+
assert.isTrue(error.handledBySdk);
|
192
194
|
|
193
195
|
assert.calledWith(mockWebex.internal.newMetrics.submitClientEvent, {
|
194
196
|
name: 'client.locus.media.response',
|
@@ -210,9 +212,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
210
212
|
method: 'PUT',
|
211
213
|
uri: 'fakeMeetingSelfUrl/media',
|
212
214
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: false}),
|
215
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
216
|
+
download: sinon.match.instanceOf(EventEmitter),
|
213
217
|
});
|
214
|
-
|
215
|
-
checkMetrics(false);
|
216
218
|
});
|
217
219
|
|
218
220
|
it('sends a local mute request with sequence', async () => {
|
@@ -228,6 +230,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
228
230
|
method: 'PUT',
|
229
231
|
uri: 'fakeMeetingSelfUrl/media',
|
230
232
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: false}, sequence),
|
233
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
234
|
+
download: sinon.match.instanceOf(EventEmitter),
|
231
235
|
});
|
232
236
|
});
|
233
237
|
|
@@ -237,15 +241,13 @@ describe('LocusMediaRequest.send()', () => {
|
|
237
241
|
let result1;
|
238
242
|
let result2;
|
239
243
|
|
240
|
-
const promise1 = sendLocalMute({audioMuted: true, videoMuted: false})
|
241
|
-
|
242
|
-
|
243
|
-
});
|
244
|
+
const promise1 = sendLocalMute({audioMuted: true, videoMuted: false}).then((result) => {
|
245
|
+
result1 = result;
|
246
|
+
});
|
244
247
|
|
245
|
-
const promise2 = sendLocalMute({audioMuted: false, videoMuted: true})
|
246
|
-
|
247
|
-
|
248
|
-
});
|
248
|
+
const promise2 = sendLocalMute({audioMuted: false, videoMuted: true}).then((result) => {
|
249
|
+
result2 = result;
|
250
|
+
});
|
249
251
|
|
250
252
|
await testUtils.flushPromises();
|
251
253
|
|
@@ -258,9 +260,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
258
260
|
method: 'PUT',
|
259
261
|
uri: 'fakeMeetingSelfUrl/media',
|
260
262
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
263
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
264
|
+
download: sinon.match.instanceOf(EventEmitter),
|
261
265
|
});
|
262
|
-
|
263
|
-
checkMetrics(false);
|
264
266
|
});
|
265
267
|
|
266
268
|
it('sends a local mute request with the last audio/video mute values', async () => {
|
@@ -277,9 +279,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
277
279
|
method: 'PUT',
|
278
280
|
uri: 'fakeMeetingSelfUrl/media',
|
279
281
|
body: createExpectedLocalMuteBody({audioMuted: true, videoMuted: false}),
|
282
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
283
|
+
download: sinon.match.instanceOf(EventEmitter),
|
280
284
|
});
|
281
|
-
|
282
|
-
checkMetrics(false);
|
283
285
|
});
|
284
286
|
|
285
287
|
it('sends only roap when roap and local mute are requested', async () => {
|
@@ -296,9 +298,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
296
298
|
method: 'PUT',
|
297
299
|
uri: 'fakeMeetingSelfUrl/media',
|
298
300
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: false}),
|
301
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
302
|
+
download: sinon.match.instanceOf(EventEmitter),
|
299
303
|
});
|
300
|
-
|
301
|
-
checkMetrics();
|
302
304
|
});
|
303
305
|
|
304
306
|
describe('queueing', () => {
|
@@ -328,10 +330,10 @@ describe('LocusMediaRequest.send()', () => {
|
|
328
330
|
* after the processing cycle from which it was called is finished.
|
329
331
|
* This helper function waits for this to happen - it's needed, because we're using
|
330
332
|
* fake timers in these tests
|
331
|
-
|
333
|
+
*/
|
332
334
|
const ensureQueueProcessingIsStarted = () => {
|
333
335
|
clock.tick(1);
|
334
|
-
}
|
336
|
+
};
|
335
337
|
it('queues requests if there is one already in progress', async () => {
|
336
338
|
results.push(sendRoapMessage('OFFER'));
|
337
339
|
|
@@ -342,6 +344,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
342
344
|
method: 'PUT',
|
343
345
|
uri: 'fakeMeetingSelfUrl/media',
|
344
346
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: true}),
|
347
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
348
|
+
download: sinon.match.instanceOf(EventEmitter),
|
345
349
|
});
|
346
350
|
|
347
351
|
webexRequestStub.resetHistory();
|
@@ -364,6 +368,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
364
368
|
method: 'PUT',
|
365
369
|
uri: 'fakeMeetingSelfUrl/media',
|
366
370
|
body: createExpectedRoapBody('OK', {audioMuted: true, videoMuted: true}),
|
371
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
372
|
+
download: sinon.match.instanceOf(EventEmitter),
|
367
373
|
});
|
368
374
|
|
369
375
|
// promise returned by the first call to send OFFER should be resolved by now
|
@@ -386,6 +392,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
386
392
|
method: 'PUT',
|
387
393
|
uri: 'fakeMeetingSelfUrl/media',
|
388
394
|
body: createExpectedRoapBody('OFFER', {audioMuted: false, videoMuted: false}),
|
395
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
396
|
+
download: sinon.match.instanceOf(EventEmitter),
|
389
397
|
});
|
390
398
|
|
391
399
|
webexRequestStub.resetHistory();
|
@@ -410,6 +418,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
410
418
|
method: 'PUT',
|
411
419
|
uri: 'fakeMeetingSelfUrl/media',
|
412
420
|
body: createExpectedRoapBody('OK', {audioMuted: false, videoMuted: true}),
|
421
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
422
|
+
download: sinon.match.instanceOf(EventEmitter),
|
413
423
|
});
|
414
424
|
|
415
425
|
// promise returned by the first call to send OFFER should be resolved by now
|
@@ -438,16 +448,17 @@ describe('LocusMediaRequest.send()', () => {
|
|
438
448
|
|
439
449
|
ensureQueueProcessingIsStarted();
|
440
450
|
|
441
|
-
sendLocalMute({audioMuted: false, videoMuted: true})
|
442
|
-
|
443
|
-
|
444
|
-
});
|
451
|
+
sendLocalMute({audioMuted: false, videoMuted: true}).then((response) => {
|
452
|
+
result = response;
|
453
|
+
});
|
445
454
|
|
446
455
|
// only roap offer should have been sent so far
|
447
456
|
assert.calledOnceWithExactly(webexRequestStub, {
|
448
457
|
method: 'PUT',
|
449
458
|
uri: 'fakeMeetingSelfUrl/media',
|
450
459
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: true}),
|
460
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
461
|
+
download: sinon.match.instanceOf(EventEmitter),
|
451
462
|
});
|
452
463
|
assert.equal(result, undefined); // sendLocalMute shouldn't resolve yet, as the request should be queued
|
453
464
|
assert.equal(locusMediaRequest.isConfluenceCreated(), false);
|
@@ -464,10 +475,12 @@ describe('LocusMediaRequest.send()', () => {
|
|
464
475
|
method: 'PUT',
|
465
476
|
uri: 'fakeMeetingSelfUrl/media',
|
466
477
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
478
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
479
|
+
download: sinon.match.instanceOf(EventEmitter),
|
467
480
|
});
|
468
481
|
|
469
482
|
// check also the result once Locus replies to local mute
|
470
|
-
const fakeLocusResponse = {
|
483
|
+
const fakeLocusResponse = {response: 'ok'};
|
471
484
|
requestsToLocus[1].resolve(fakeLocusResponse);
|
472
485
|
await testUtils.flushPromises();
|
473
486
|
assert.deepEqual(result, fakeLocusResponse);
|
@@ -487,10 +500,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
487
500
|
assert.equal(locusMediaRequest.isConfluenceCreated(), true);
|
488
501
|
|
489
502
|
// now send local mute
|
490
|
-
sendLocalMute({audioMuted: false, videoMuted: true})
|
491
|
-
|
492
|
-
|
493
|
-
});
|
503
|
+
sendLocalMute({audioMuted: false, videoMuted: true}).then((response) => {
|
504
|
+
result = response;
|
505
|
+
});
|
494
506
|
|
495
507
|
ensureQueueProcessingIsStarted();
|
496
508
|
|
@@ -499,8 +511,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
499
511
|
method: 'PUT',
|
500
512
|
uri: 'fakeMeetingSelfUrl/media',
|
501
513
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
514
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
515
|
+
download: sinon.match.instanceOf(EventEmitter),
|
502
516
|
});
|
503
517
|
});
|
504
|
-
|
505
518
|
});
|
506
|
-
})
|
519
|
+
});
|
@@ -2,7 +2,6 @@ import sinon from 'sinon';
|
|
2
2
|
import {assert} from '@webex/test-helper-chai';
|
3
3
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
4
4
|
import {createMuteState, MuteState} from '@webex/plugin-meetings/src/meeting/muteState';
|
5
|
-
import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
|
6
5
|
import {AUDIO, VIDEO} from '@webex/plugin-meetings/src/constants';
|
7
6
|
|
8
7
|
import testUtils from '../../../utils/testUtils';
|
@@ -39,7 +38,6 @@ describe('plugin-meetings', () => {
|
|
39
38
|
unmuteAllowed: true,
|
40
39
|
remoteVideoMuted: false,
|
41
40
|
unmuteVideoAllowed: true,
|
42
|
-
|
43
41
|
locusInfo: {
|
44
42
|
handleLocusDelta: sinon.stub(),
|
45
43
|
},
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import 'jsdom-global/register';
|
2
|
+
import {v4 as uuidv4} from 'uuid';
|
2
3
|
import sinon from 'sinon';
|
3
4
|
import {assert} from '@webex/test-helper-chai';
|
4
5
|
import MockWebex from '@webex/test-helper-mock-webex';
|
@@ -205,7 +206,7 @@ describe('plugin-meetings', () => {
|
|
205
206
|
roapMessage,
|
206
207
|
reachability,
|
207
208
|
permissionToken,
|
208
|
-
clientMediaPreferences
|
209
|
+
clientMediaPreferences,
|
209
210
|
});
|
210
211
|
const requestParams = meetingsRequest.request.getCall(0).args[0];
|
211
212
|
|
@@ -630,6 +631,36 @@ describe('plugin-meetings', () => {
|
|
630
631
|
});
|
631
632
|
});
|
632
633
|
|
634
|
+
describe('#setPostMeetingDataConsent', () => {
|
635
|
+
[true, false].forEach((consent) => {
|
636
|
+
it(`sends request to set post meeting data consent with ${consent}`, async () => {
|
637
|
+
const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${consent}`;
|
638
|
+
const selfId = uuidv4();
|
639
|
+
const deviceUrl = `https://wdm-test.wbx2.com/wdm/api/v1/devices/${consent}`;
|
640
|
+
|
641
|
+
const consentPromise = meetingsRequest.setPostMeetingDataConsent({
|
642
|
+
postMeetingDataConsent: consent,
|
643
|
+
locusUrl,
|
644
|
+
selfId,
|
645
|
+
deviceUrl,
|
646
|
+
});
|
647
|
+
assert.exists(consentPromise.then);
|
648
|
+
await consentPromise;
|
649
|
+
|
650
|
+
checkRequest({
|
651
|
+
method: 'PATCH',
|
652
|
+
uri: `${locusUrl}/participant/${selfId}/controls`,
|
653
|
+
body: {
|
654
|
+
consent: {
|
655
|
+
postMeetingDataConsent: consent,
|
656
|
+
deviceUrl,
|
657
|
+
},
|
658
|
+
},
|
659
|
+
});
|
660
|
+
});
|
661
|
+
});
|
662
|
+
});
|
663
|
+
|
633
664
|
describe('#prepareLeaveMeetingRequestOptions', () => {
|
634
665
|
it('returns expected result', async () => {
|
635
666
|
const result = meetingsRequest.prepareLeaveMeetingRequestOptions({
|
@@ -66,7 +66,7 @@ describe('plugin-meetings', () => {
|
|
66
66
|
|
67
67
|
describe('#cleanup', () => {
|
68
68
|
it('do clean up on meeting object with LLM enabled', async () => {
|
69
|
-
meeting.config = {enableAutomaticLLM
|
69
|
+
meeting.config = {enableAutomaticLLM: true};
|
70
70
|
await MeetingUtil.cleanUp(meeting);
|
71
71
|
assert.calledOnce(meeting.cleanupLocalStreams);
|
72
72
|
assert.calledOnce(meeting.closeRemoteStreams);
|
@@ -84,7 +84,7 @@ describe('plugin-meetings', () => {
|
|
84
84
|
});
|
85
85
|
|
86
86
|
it('do clean up on meeting object with LLM disabled', async () => {
|
87
|
-
meeting.config = {enableAutomaticLLM
|
87
|
+
meeting.config = {enableAutomaticLLM: false};
|
88
88
|
await MeetingUtil.cleanUp(meeting);
|
89
89
|
assert.calledOnce(meeting.cleanupLocalStreams);
|
90
90
|
assert.calledOnce(meeting.closeRemoteStreams);
|
@@ -392,8 +392,7 @@ describe('plugin-meetings', () => {
|
|
392
392
|
meetingJoinUrl: 'meetingJoinUrl',
|
393
393
|
locusUrl: 'locusUrl',
|
394
394
|
meetingRequest: {
|
395
|
-
joinMeeting: sinon.stub().returns(
|
396
|
-
Promise.resolve(joinMeetingResponse)),
|
395
|
+
joinMeeting: sinon.stub().returns(Promise.resolve(joinMeetingResponse)),
|
397
396
|
},
|
398
397
|
getWebexObject: sinon.stub().returns(webex),
|
399
398
|
setLocus: sinon.stub(),
|
@@ -410,23 +409,29 @@ describe('plugin-meetings', () => {
|
|
410
409
|
id: 'fake client media preferences',
|
411
410
|
};
|
412
411
|
|
413
|
-
webex.meetings.reachability.getReachabilityReportToAttachToRoap.resolves(
|
414
|
-
|
412
|
+
webex.meetings.reachability.getReachabilityReportToAttachToRoap.resolves(
|
413
|
+
FAKE_REACHABILITY_REPORT
|
414
|
+
);
|
415
|
+
webex.meetings.reachability.getClientMediaPreferences.resolves(
|
416
|
+
FAKE_CLIENT_MEDIA_PREFERENCES
|
417
|
+
);
|
415
418
|
|
416
|
-
sinon
|
417
|
-
|
418
|
-
.get(() => true);
|
419
|
-
sinon
|
420
|
-
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6')
|
421
|
-
.get(() => true);
|
419
|
+
sinon.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4').get(() => true);
|
420
|
+
sinon.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6').get(() => true);
|
422
421
|
|
423
422
|
await MeetingUtil.joinMeeting(meeting, {
|
424
423
|
reachability: 'reachability',
|
425
424
|
roapMessage: 'roapMessage',
|
426
425
|
});
|
427
426
|
|
428
|
-
assert.calledOnceWithExactly(
|
429
|
-
|
427
|
+
assert.calledOnceWithExactly(
|
428
|
+
webex.meetings.reachability.getReachabilityReportToAttachToRoap
|
429
|
+
);
|
430
|
+
assert.calledOnceWithExactly(
|
431
|
+
webex.meetings.reachability.getClientMediaPreferences,
|
432
|
+
meeting.isMultistream,
|
433
|
+
IP_VERSION.ipv4_and_ipv6
|
434
|
+
);
|
430
435
|
|
431
436
|
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
432
437
|
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
@@ -436,9 +441,9 @@ describe('plugin-meetings', () => {
|
|
436
441
|
assert.equal(parameter.clientMediaPreferences, FAKE_CLIENT_MEDIA_PREFERENCES);
|
437
442
|
assert.equal(parameter.roapMessage, 'roapMessage');
|
438
443
|
|
439
|
-
assert.calledOnce(meeting.setLocus)
|
444
|
+
assert.calledOnce(meeting.setLocus);
|
440
445
|
const setLocusParameter = meeting.setLocus.getCall(0).args[0];
|
441
|
-
assert.deepEqual(setLocusParameter, MeetingUtil.parseLocusJoin(joinMeetingResponse))
|
446
|
+
assert.deepEqual(setLocusParameter, MeetingUtil.parseLocusJoin(joinMeetingResponse));
|
442
447
|
|
443
448
|
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
444
449
|
name: 'client.locus.join.request',
|
@@ -460,6 +465,49 @@ describe('plugin-meetings', () => {
|
|
460
465
|
});
|
461
466
|
});
|
462
467
|
|
468
|
+
it('#Should call `meetingRequest.joinMeeting and handle a date header in the response : isoLocalClientMeetingJoinedTime', async () => {
|
469
|
+
meeting.isMultistream = true;
|
470
|
+
|
471
|
+
const FAKE_REACHABILITY_REPORT = {
|
472
|
+
id: 'fake reachability report',
|
473
|
+
};
|
474
|
+
const FAKE_CLIENT_MEDIA_PREFERENCES = {
|
475
|
+
id: 'fake client media preferences',
|
476
|
+
};
|
477
|
+
|
478
|
+
webex.meetings.reachability.getReachabilityReportToAttachToRoap.resolves(
|
479
|
+
FAKE_REACHABILITY_REPORT
|
480
|
+
);
|
481
|
+
webex.meetings.reachability.getClientMediaPreferences.resolves(
|
482
|
+
FAKE_CLIENT_MEDIA_PREFERENCES
|
483
|
+
);
|
484
|
+
|
485
|
+
sinon.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4').get(() => true);
|
486
|
+
sinon.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6').get(() => true);
|
487
|
+
|
488
|
+
meeting.meetingRequest.joinMeeting.resolves({
|
489
|
+
headers: {
|
490
|
+
date: 'test',
|
491
|
+
},
|
492
|
+
body: {
|
493
|
+
mediaConnections: [{mediaId: 'test'}],
|
494
|
+
locus: {
|
495
|
+
url: 'test',
|
496
|
+
self: {
|
497
|
+
id: 'test',
|
498
|
+
},
|
499
|
+
},
|
500
|
+
},
|
501
|
+
});
|
502
|
+
|
503
|
+
await MeetingUtil.joinMeeting(meeting, {
|
504
|
+
reachability: 'reachability',
|
505
|
+
roapMessage: 'roapMessage',
|
506
|
+
});
|
507
|
+
|
508
|
+
assert.equal(meeting.isoLocalClientMeetingJoinTime, 'test');
|
509
|
+
});
|
510
|
+
|
463
511
|
it('should handle failed reachability report retrieval', async () => {
|
464
512
|
webex.meetings.reachability.getReachabilityReportToAttachToRoap.rejects(
|
465
513
|
new Error('fake error')
|
@@ -516,6 +564,17 @@ describe('plugin-meetings', () => {
|
|
516
564
|
assert.equal(parameter.liveAnnotationSupported, true);
|
517
565
|
});
|
518
566
|
|
567
|
+
it('#Should call meetingRequest.joinMeeting with alias passed through', async () => {
|
568
|
+
await MeetingUtil.joinMeeting(meeting, {
|
569
|
+
alias: 'alias name',
|
570
|
+
});
|
571
|
+
|
572
|
+
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
573
|
+
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
574
|
+
|
575
|
+
assert.equal(parameter.alias, 'alias name');
|
576
|
+
});
|
577
|
+
|
519
578
|
it('#Should call meetingRequest.joinMeeting with locale=en_UK, deviceCapabilities=["TEST"] when they are passed in as those values', async () => {
|
520
579
|
await MeetingUtil.joinMeeting(meeting, {
|
521
580
|
locale: 'en_UK',
|
@@ -685,6 +744,18 @@ describe('plugin-meetings', () => {
|
|
685
744
|
});
|
686
745
|
});
|
687
746
|
|
747
|
+
describe('requiresPostMeetingDataConsentPrompt', () => {
|
748
|
+
it('works as expected', () => {
|
749
|
+
assert.deepEqual(
|
750
|
+
MeetingUtil.requiresPostMeetingDataConsentPrompt([
|
751
|
+
'SHOW_POST_MEETING_DATA_CONSENT_PROMPT',
|
752
|
+
]),
|
753
|
+
true
|
754
|
+
);
|
755
|
+
assert.deepEqual(MeetingUtil.requiresPostMeetingDataConsentPrompt([]), false);
|
756
|
+
});
|
757
|
+
});
|
758
|
+
|
688
759
|
describe('canUserRenameOthers', () => {
|
689
760
|
it('works as expected', () => {
|
690
761
|
assert.deepEqual(MeetingUtil.canUserRenameOthers(['CAN_RENAME_OTHERS']), true);
|
@@ -694,8 +765,34 @@ describe('plugin-meetings', () => {
|
|
694
765
|
|
695
766
|
describe('canShareWhiteBoard', () => {
|
696
767
|
it('works as expected', () => {
|
697
|
-
assert.deepEqual(
|
698
|
-
|
768
|
+
assert.deepEqual(
|
769
|
+
MeetingUtil.canShareWhiteBoard(['SHARE_WHITEBOARD'], {
|
770
|
+
[SELF_POLICY.SUPPORT_WHITEBOARD]: true,
|
771
|
+
}),
|
772
|
+
true
|
773
|
+
);
|
774
|
+
assert.deepEqual(
|
775
|
+
MeetingUtil.canShareWhiteBoard([], {
|
776
|
+
[SELF_POLICY.SUPPORT_WHITEBOARD]: true,
|
777
|
+
}),
|
778
|
+
false
|
779
|
+
);
|
780
|
+
assert.deepEqual(
|
781
|
+
MeetingUtil.canShareWhiteBoard(['SHARE_WHITEBOARD'], {
|
782
|
+
[SELF_POLICY.SUPPORT_WHITEBOARD]: false,
|
783
|
+
}),
|
784
|
+
false
|
785
|
+
);
|
786
|
+
assert.deepEqual(
|
787
|
+
MeetingUtil.canShareWhiteBoard([], {
|
788
|
+
[SELF_POLICY.SUPPORT_WHITEBOARD]: false,
|
789
|
+
}),
|
790
|
+
false
|
791
|
+
);
|
792
|
+
assert.deepEqual(
|
793
|
+
MeetingUtil.canShareWhiteBoard(['SHARE_WHITEBOARD'], undefined),
|
794
|
+
false
|
795
|
+
);
|
699
796
|
});
|
700
797
|
});
|
701
798
|
|
@@ -1088,6 +1185,14 @@ describe('plugin-meetings', () => {
|
|
1088
1185
|
});
|
1089
1186
|
});
|
1090
1187
|
|
1188
|
+
describe('markErrorAsHandledBySdk', () => {
|
1189
|
+
it('should set the error as handled', () => {
|
1190
|
+
const error = MeetingUtil.markErrorAsHandledBySdk(new Error('Test error'));
|
1191
|
+
|
1192
|
+
assert.isTrue(error.handledBySdk);
|
1193
|
+
})
|
1194
|
+
});
|
1195
|
+
|
1091
1196
|
describe('getChangeMeetingFloorErrorPayload', () => {
|
1092
1197
|
[
|
1093
1198
|
{
|