@webex/plugin-meetings 3.8.0-next.4 → 3.8.0-next.40
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 +443 -256
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +21 -22
- 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 +10 -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 +60 -1
- package/dist/meetings/index.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 +52 -8
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +70 -45
- 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 +47 -1
- 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 +2 -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 +13 -1
- package/dist/types/reachability/index.d.ts +2 -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 +263 -69
- package/src/meeting/locusMediaRequest.ts +27 -22
- 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 +9 -2
- package/src/meeting-info/meeting-info-v2.ts +247 -6
- package/src/meetings/index.ts +72 -1
- 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 +47 -1
- package/src/reachability/index.ts +15 -0
- 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 +490 -130
- package/test/unit/spec/meeting/locusMediaRequest.ts +95 -87
- 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 +115 -18
- package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
- package/test/unit/spec/meetings/index.js +78 -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 +47 -1
- package/test/unit/spec/reachability/index.ts +12 -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,9 +178,9 @@ 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 () => {
|
@@ -210,9 +207,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
210
207
|
method: 'PUT',
|
211
208
|
uri: 'fakeMeetingSelfUrl/media',
|
212
209
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: false}),
|
210
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
211
|
+
download: sinon.match.instanceOf(EventEmitter),
|
213
212
|
});
|
214
|
-
|
215
|
-
checkMetrics(false);
|
216
213
|
});
|
217
214
|
|
218
215
|
it('sends a local mute request with sequence', async () => {
|
@@ -228,6 +225,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
228
225
|
method: 'PUT',
|
229
226
|
uri: 'fakeMeetingSelfUrl/media',
|
230
227
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: false}, sequence),
|
228
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
229
|
+
download: sinon.match.instanceOf(EventEmitter),
|
231
230
|
});
|
232
231
|
});
|
233
232
|
|
@@ -237,15 +236,13 @@ describe('LocusMediaRequest.send()', () => {
|
|
237
236
|
let result1;
|
238
237
|
let result2;
|
239
238
|
|
240
|
-
const promise1 = sendLocalMute({audioMuted: true, videoMuted: false})
|
241
|
-
|
242
|
-
|
243
|
-
});
|
239
|
+
const promise1 = sendLocalMute({audioMuted: true, videoMuted: false}).then((result) => {
|
240
|
+
result1 = result;
|
241
|
+
});
|
244
242
|
|
245
|
-
const promise2 = sendLocalMute({audioMuted: false, videoMuted: true})
|
246
|
-
|
247
|
-
|
248
|
-
});
|
243
|
+
const promise2 = sendLocalMute({audioMuted: false, videoMuted: true}).then((result) => {
|
244
|
+
result2 = result;
|
245
|
+
});
|
249
246
|
|
250
247
|
await testUtils.flushPromises();
|
251
248
|
|
@@ -258,9 +255,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
258
255
|
method: 'PUT',
|
259
256
|
uri: 'fakeMeetingSelfUrl/media',
|
260
257
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
258
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
259
|
+
download: sinon.match.instanceOf(EventEmitter),
|
261
260
|
});
|
262
|
-
|
263
|
-
checkMetrics(false);
|
264
261
|
});
|
265
262
|
|
266
263
|
it('sends a local mute request with the last audio/video mute values', async () => {
|
@@ -277,9 +274,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
277
274
|
method: 'PUT',
|
278
275
|
uri: 'fakeMeetingSelfUrl/media',
|
279
276
|
body: createExpectedLocalMuteBody({audioMuted: true, videoMuted: false}),
|
277
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
278
|
+
download: sinon.match.instanceOf(EventEmitter),
|
280
279
|
});
|
281
|
-
|
282
|
-
checkMetrics(false);
|
283
280
|
});
|
284
281
|
|
285
282
|
it('sends only roap when roap and local mute are requested', async () => {
|
@@ -296,9 +293,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
296
293
|
method: 'PUT',
|
297
294
|
uri: 'fakeMeetingSelfUrl/media',
|
298
295
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: false}),
|
296
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
297
|
+
download: sinon.match.instanceOf(EventEmitter),
|
299
298
|
});
|
300
|
-
|
301
|
-
checkMetrics();
|
302
299
|
});
|
303
300
|
|
304
301
|
describe('queueing', () => {
|
@@ -328,10 +325,10 @@ describe('LocusMediaRequest.send()', () => {
|
|
328
325
|
* after the processing cycle from which it was called is finished.
|
329
326
|
* This helper function waits for this to happen - it's needed, because we're using
|
330
327
|
* fake timers in these tests
|
331
|
-
|
328
|
+
*/
|
332
329
|
const ensureQueueProcessingIsStarted = () => {
|
333
330
|
clock.tick(1);
|
334
|
-
}
|
331
|
+
};
|
335
332
|
it('queues requests if there is one already in progress', async () => {
|
336
333
|
results.push(sendRoapMessage('OFFER'));
|
337
334
|
|
@@ -342,6 +339,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
342
339
|
method: 'PUT',
|
343
340
|
uri: 'fakeMeetingSelfUrl/media',
|
344
341
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: true}),
|
342
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
343
|
+
download: sinon.match.instanceOf(EventEmitter),
|
345
344
|
});
|
346
345
|
|
347
346
|
webexRequestStub.resetHistory();
|
@@ -364,6 +363,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
364
363
|
method: 'PUT',
|
365
364
|
uri: 'fakeMeetingSelfUrl/media',
|
366
365
|
body: createExpectedRoapBody('OK', {audioMuted: true, videoMuted: true}),
|
366
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
367
|
+
download: sinon.match.instanceOf(EventEmitter),
|
367
368
|
});
|
368
369
|
|
369
370
|
// promise returned by the first call to send OFFER should be resolved by now
|
@@ -386,6 +387,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
386
387
|
method: 'PUT',
|
387
388
|
uri: 'fakeMeetingSelfUrl/media',
|
388
389
|
body: createExpectedRoapBody('OFFER', {audioMuted: false, videoMuted: false}),
|
390
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
391
|
+
download: sinon.match.instanceOf(EventEmitter),
|
389
392
|
});
|
390
393
|
|
391
394
|
webexRequestStub.resetHistory();
|
@@ -410,6 +413,8 @@ describe('LocusMediaRequest.send()', () => {
|
|
410
413
|
method: 'PUT',
|
411
414
|
uri: 'fakeMeetingSelfUrl/media',
|
412
415
|
body: createExpectedRoapBody('OK', {audioMuted: false, videoMuted: true}),
|
416
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
417
|
+
download: sinon.match.instanceOf(EventEmitter),
|
413
418
|
});
|
414
419
|
|
415
420
|
// promise returned by the first call to send OFFER should be resolved by now
|
@@ -438,16 +443,17 @@ describe('LocusMediaRequest.send()', () => {
|
|
438
443
|
|
439
444
|
ensureQueueProcessingIsStarted();
|
440
445
|
|
441
|
-
sendLocalMute({audioMuted: false, videoMuted: true})
|
442
|
-
|
443
|
-
|
444
|
-
});
|
446
|
+
sendLocalMute({audioMuted: false, videoMuted: true}).then((response) => {
|
447
|
+
result = response;
|
448
|
+
});
|
445
449
|
|
446
450
|
// only roap offer should have been sent so far
|
447
451
|
assert.calledOnceWithExactly(webexRequestStub, {
|
448
452
|
method: 'PUT',
|
449
453
|
uri: 'fakeMeetingSelfUrl/media',
|
450
454
|
body: createExpectedRoapBody('OFFER', {audioMuted: true, videoMuted: true}),
|
455
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
456
|
+
download: sinon.match.instanceOf(EventEmitter),
|
451
457
|
});
|
452
458
|
assert.equal(result, undefined); // sendLocalMute shouldn't resolve yet, as the request should be queued
|
453
459
|
assert.equal(locusMediaRequest.isConfluenceCreated(), false);
|
@@ -464,10 +470,12 @@ describe('LocusMediaRequest.send()', () => {
|
|
464
470
|
method: 'PUT',
|
465
471
|
uri: 'fakeMeetingSelfUrl/media',
|
466
472
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
473
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
474
|
+
download: sinon.match.instanceOf(EventEmitter),
|
467
475
|
});
|
468
476
|
|
469
477
|
// check also the result once Locus replies to local mute
|
470
|
-
const fakeLocusResponse = {
|
478
|
+
const fakeLocusResponse = {response: 'ok'};
|
471
479
|
requestsToLocus[1].resolve(fakeLocusResponse);
|
472
480
|
await testUtils.flushPromises();
|
473
481
|
assert.deepEqual(result, fakeLocusResponse);
|
@@ -487,10 +495,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
487
495
|
assert.equal(locusMediaRequest.isConfluenceCreated(), true);
|
488
496
|
|
489
497
|
// now send local mute
|
490
|
-
sendLocalMute({audioMuted: false, videoMuted: true})
|
491
|
-
|
492
|
-
|
493
|
-
});
|
498
|
+
sendLocalMute({audioMuted: false, videoMuted: true}).then((response) => {
|
499
|
+
result = response;
|
500
|
+
});
|
494
501
|
|
495
502
|
ensureQueueProcessingIsStarted();
|
496
503
|
|
@@ -499,8 +506,9 @@ describe('LocusMediaRequest.send()', () => {
|
|
499
506
|
method: 'PUT',
|
500
507
|
uri: 'fakeMeetingSelfUrl/media',
|
501
508
|
body: createExpectedLocalMuteBody({audioMuted: false, videoMuted: true}),
|
509
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
510
|
+
download: sinon.match.instanceOf(EventEmitter),
|
502
511
|
});
|
503
512
|
});
|
504
|
-
|
505
513
|
});
|
506
|
-
})
|
514
|
+
});
|
@@ -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
|
|