@webex/plugin-meetings 3.11.0-next.2 → 3.11.0-next.21
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/hashTree/hashTree.js +18 -0
- package/dist/hashTree/hashTree.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +307 -139
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/types.js +2 -1
- package/dist/hashTree/types.js.map +1 -1
- package/dist/hashTree/utils.js +10 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +55 -42
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +57 -1
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +4 -2
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +33 -22
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +108 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +76 -26
- package/dist/meetings/index.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/types/hashTree/hashTree.d.ts +7 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +47 -12
- package/dist/types/hashTree/types.d.ts +1 -0
- package/dist/types/hashTree/utils.d.ts +6 -0
- package/dist/types/locus-info/index.d.ts +9 -2
- package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
- package/dist/types/media/properties.d.ts +2 -1
- package/dist/types/meeting/index.d.ts +8 -5
- package/dist/types/meeting/util.d.ts +28 -0
- package/dist/types/meetings/index.d.ts +3 -1
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/reactions/reactions.type.d.ts +1 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/hashTree/hashTree.ts +17 -0
- package/src/hashTree/hashTreeParser.ts +294 -96
- package/src/hashTree/types.ts +1 -0
- package/src/hashTree/utils.ts +9 -0
- package/src/locus-info/index.ts +83 -35
- package/src/media/MediaConnectionAwaiter.ts +41 -1
- package/src/media/properties.ts +3 -1
- package/src/meeting/index.ts +24 -11
- package/src/meeting/util.ts +132 -1
- package/src/meetings/index.ts +93 -8
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +1 -1
- package/src/reactions/reactions.type.ts +1 -0
- package/test/unit/spec/hashTree/hashTree.ts +66 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +942 -110
- package/test/unit/spec/locus-info/index.js +88 -17
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
- package/test/unit/spec/media/properties.ts +12 -3
- package/test/unit/spec/meeting/index.js +160 -2
- package/test/unit/spec/meeting/utils.js +294 -22
- package/test/unit/spec/meetings/index.js +594 -17
|
@@ -29,7 +29,8 @@ import {
|
|
|
29
29
|
} from '../../../../src/constants';
|
|
30
30
|
|
|
31
31
|
import {self, selfWithInactivity} from './selfConstant';
|
|
32
|
-
import {
|
|
32
|
+
import {MEETING_REMOVED_REASON} from '@webex/plugin-meetings/src/constants';
|
|
33
|
+
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
33
34
|
|
|
34
35
|
describe('plugin-meetings', () => {
|
|
35
36
|
describe('LocusInfo index', () => {
|
|
@@ -106,7 +107,7 @@ describe('plugin-meetings', () => {
|
|
|
106
107
|
const createHashTreeMessage = (visibleDataSets) => ({
|
|
107
108
|
locusStateElements: [
|
|
108
109
|
{
|
|
109
|
-
htMeta: {elementId: {type: '
|
|
110
|
+
htMeta: {elementId: {type: 'metadata'}},
|
|
110
111
|
data: {visibleDataSets},
|
|
111
112
|
},
|
|
112
113
|
],
|
|
@@ -136,9 +137,13 @@ describe('plugin-meetings', () => {
|
|
|
136
137
|
HashTreeParserStub,
|
|
137
138
|
sinon.match({
|
|
138
139
|
initialLocus: {
|
|
139
|
-
locus:
|
|
140
|
+
locus: null,
|
|
140
141
|
dataSets: [],
|
|
141
142
|
},
|
|
143
|
+
metadata: {
|
|
144
|
+
htMeta: hashTreeMessage.locusStateElements[0].htMeta,
|
|
145
|
+
visibleDataSets,
|
|
146
|
+
},
|
|
142
147
|
webexRequest: sinon.match.func,
|
|
143
148
|
locusInfoUpdateCallback: sinon.match.func,
|
|
144
149
|
debugId: sinon.match.string,
|
|
@@ -169,11 +174,16 @@ describe('plugin-meetings', () => {
|
|
|
169
174
|
const visibleDataSets = ['dataset1', 'dataset2'];
|
|
170
175
|
const locus = createLocusWithVisibleDataSets(visibleDataSets);
|
|
171
176
|
const dataSets = [{name: 'dataset1', url: 'http://dataset-url.com'}];
|
|
177
|
+
const metadata = {
|
|
178
|
+
htMeta: {elementId: {type: 'metadata'}},
|
|
179
|
+
visibleDataSets,
|
|
180
|
+
};
|
|
172
181
|
|
|
173
182
|
await locusInfo.initialSetup({
|
|
174
183
|
trigger: 'join-response',
|
|
175
184
|
locus,
|
|
176
185
|
dataSets,
|
|
186
|
+
metadata,
|
|
177
187
|
});
|
|
178
188
|
|
|
179
189
|
assert.calledOnceWithExactly(
|
|
@@ -183,6 +193,7 @@ describe('plugin-meetings', () => {
|
|
|
183
193
|
locus,
|
|
184
194
|
dataSets,
|
|
185
195
|
},
|
|
196
|
+
metadata,
|
|
186
197
|
webexRequest: sinon.match.func,
|
|
187
198
|
locusInfoUpdateCallback: sinon.match.func,
|
|
188
199
|
debugId: sinon.match.string,
|
|
@@ -220,12 +231,13 @@ describe('plugin-meetings', () => {
|
|
|
220
231
|
HashTreeParserStub,
|
|
221
232
|
sinon.match({
|
|
222
233
|
initialLocus: {
|
|
223
|
-
locus:
|
|
234
|
+
locus: null,
|
|
224
235
|
dataSets: [],
|
|
225
236
|
},
|
|
226
237
|
webexRequest: sinon.match.func,
|
|
227
238
|
locusInfoUpdateCallback: sinon.match.func,
|
|
228
239
|
debugId: sinon.match.string,
|
|
240
|
+
metadata: null,
|
|
229
241
|
})
|
|
230
242
|
);
|
|
231
243
|
assert.calledOnceWithExactly(mockHashTreeParser.initializeFromGetLociResponse, locus);
|
|
@@ -249,6 +261,30 @@ describe('plugin-meetings', () => {
|
|
|
249
261
|
assert.isTrue(locusInfo.emitChange);
|
|
250
262
|
});
|
|
251
263
|
|
|
264
|
+
it('throws if called with "locus-message" and Metadata object without visibleDataSets', async () => {
|
|
265
|
+
const hashTreeMessage = {
|
|
266
|
+
locusStateElements: [
|
|
267
|
+
{
|
|
268
|
+
htMeta: {elementId: {type: 'Metadata'}},
|
|
269
|
+
data: {},
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
dataSets: [{name: 'dataset1', url: 'test-url'}],
|
|
273
|
+
};
|
|
274
|
+
try {
|
|
275
|
+
await locusInfo.initialSetup({
|
|
276
|
+
trigger: 'locus-message',
|
|
277
|
+
hashTreeMessage,
|
|
278
|
+
});
|
|
279
|
+
assert.fail('should have thrown an error');
|
|
280
|
+
} catch (error) {
|
|
281
|
+
assert.equal(
|
|
282
|
+
error.message,
|
|
283
|
+
'Metadata object with visibleDataSets is missing in the message'
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
252
288
|
describe('should setup correct locusInfoUpdateCallback when creating HashTreeParser', () => {
|
|
253
289
|
const OBJECTS_UPDATED = HashTreeParserModule.LocusInfoUpdateType.OBJECTS_UPDATED;
|
|
254
290
|
const MEETING_ENDED = HashTreeParserModule.LocusInfoUpdateType.MEETING_ENDED;
|
|
@@ -265,8 +301,8 @@ describe('plugin-meetings', () => {
|
|
|
265
301
|
hashTreeMessage: {
|
|
266
302
|
locusStateElements: [
|
|
267
303
|
{
|
|
268
|
-
htMeta: {elementId: {type: '
|
|
269
|
-
data: {visibleDataSets: ['dataset1']},
|
|
304
|
+
htMeta: {elementId: {type: 'Metadata'}},
|
|
305
|
+
data: {visibleDataSets: [{name: 'dataset1', url: 'test-url'}]},
|
|
270
306
|
},
|
|
271
307
|
],
|
|
272
308
|
dataSets: [{name: 'dataset1', url: 'test-url'}],
|
|
@@ -1076,7 +1112,7 @@ describe('plugin-meetings', () => {
|
|
|
1076
1112
|
it('should trigger the CONTROLS_POLLING_QA_CHANGED event when necessary', () => {
|
|
1077
1113
|
locusInfo.controls = {};
|
|
1078
1114
|
locusInfo.emitScoped = sinon.stub();
|
|
1079
|
-
newControls.pollingQAControl = {
|
|
1115
|
+
newControls.pollingQAControl = {enabled: true};
|
|
1080
1116
|
locusInfo.updateControls(newControls);
|
|
1081
1117
|
|
|
1082
1118
|
assert.calledWith(
|
|
@@ -1631,7 +1667,6 @@ describe('plugin-meetings', () => {
|
|
|
1631
1667
|
);
|
|
1632
1668
|
});
|
|
1633
1669
|
|
|
1634
|
-
|
|
1635
1670
|
it('should call with participant display name', () => {
|
|
1636
1671
|
const failureParticipant = [
|
|
1637
1672
|
{
|
|
@@ -1656,7 +1691,7 @@ describe('plugin-meetings', () => {
|
|
|
1656
1691
|
displayName: 'Test User',
|
|
1657
1692
|
}
|
|
1658
1693
|
);
|
|
1659
|
-
})
|
|
1694
|
+
});
|
|
1660
1695
|
});
|
|
1661
1696
|
|
|
1662
1697
|
describe('#updateSelf', () => {
|
|
@@ -2457,8 +2492,8 @@ describe('plugin-meetings', () => {
|
|
|
2457
2492
|
{
|
|
2458
2493
|
isInitializing: !self,
|
|
2459
2494
|
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2495
|
+
);
|
|
2496
|
+
});
|
|
2462
2497
|
|
|
2463
2498
|
const checkMeetingInfoUpdatedCalled = (expected, payload) => {
|
|
2464
2499
|
const expectedArgs = [
|
|
@@ -3039,7 +3074,7 @@ describe('plugin-meetings', () => {
|
|
|
3039
3074
|
sandbox.stub(locusInfo, 'handleOneOnOneEvent');
|
|
3040
3075
|
sandbox.stub(locusParser, 'isNewFullLocus').returns(true);
|
|
3041
3076
|
|
|
3042
|
-
locusInfo.onFullLocus(fakeLocus, eventType);
|
|
3077
|
+
locusInfo.onFullLocus('test', fakeLocus, eventType);
|
|
3043
3078
|
|
|
3044
3079
|
assert.equal(fakeLocus, locusParser.workingCopy);
|
|
3045
3080
|
});
|
|
@@ -3060,7 +3095,7 @@ describe('plugin-meetings', () => {
|
|
|
3060
3095
|
|
|
3061
3096
|
sandbox.stub(locusParser, 'isNewFullLocus').returns(false);
|
|
3062
3097
|
|
|
3063
|
-
locusInfo.onFullLocus(fakeLocus, eventType);
|
|
3098
|
+
locusInfo.onFullLocus('test', fakeLocus, eventType);
|
|
3064
3099
|
|
|
3065
3100
|
spies.forEach((spy) => {
|
|
3066
3101
|
assert.notCalled(spy);
|
|
@@ -3210,7 +3245,11 @@ describe('plugin-meetings', () => {
|
|
|
3210
3245
|
}).then(() => {
|
|
3211
3246
|
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'oldLocusUrl'});
|
|
3212
3247
|
|
|
3213
|
-
assert.calledOnceWithExactly(
|
|
3248
|
+
assert.calledOnceWithExactly(
|
|
3249
|
+
meeting.locusInfo.onFullLocus,
|
|
3250
|
+
'classic Locus sync',
|
|
3251
|
+
fakeFullLocusDto
|
|
3252
|
+
);
|
|
3214
3253
|
assert.calledOnce(locusInfo.locusParser.resume);
|
|
3215
3254
|
});
|
|
3216
3255
|
});
|
|
@@ -3308,7 +3347,11 @@ describe('plugin-meetings', () => {
|
|
|
3308
3347
|
});
|
|
3309
3348
|
|
|
3310
3349
|
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
|
3311
|
-
assert.calledOnceWithExactly(
|
|
3350
|
+
assert.calledOnceWithExactly(
|
|
3351
|
+
meeting.locusInfo.onFullLocus,
|
|
3352
|
+
'classic Locus sync',
|
|
3353
|
+
fakeFullLocusDto
|
|
3354
|
+
);
|
|
3312
3355
|
assert.calledOnce(locusInfo.locusParser.resume);
|
|
3313
3356
|
});
|
|
3314
3357
|
});
|
|
@@ -3484,7 +3527,11 @@ describe('plugin-meetings', () => {
|
|
|
3484
3527
|
url: 'fake locus DELTA url',
|
|
3485
3528
|
});
|
|
3486
3529
|
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
|
3487
|
-
assert.calledOnceWithExactly(
|
|
3530
|
+
assert.calledOnceWithExactly(
|
|
3531
|
+
meeting.locusInfo.onFullLocus,
|
|
3532
|
+
'classic Locus sync',
|
|
3533
|
+
fakeFullLocusDto
|
|
3534
|
+
);
|
|
3488
3535
|
assert.calledOnce(locusInfo.locusParser.resume);
|
|
3489
3536
|
});
|
|
3490
3537
|
});
|
|
@@ -3950,7 +3997,7 @@ describe('plugin-meetings', () => {
|
|
|
3950
3997
|
getLocusDTO: syncRequestStub,
|
|
3951
3998
|
};
|
|
3952
3999
|
|
|
3953
|
-
locusInfo.onFullLocus({
|
|
4000
|
+
locusInfo.onFullLocus('test', {
|
|
3954
4001
|
sequence: {
|
|
3955
4002
|
rangeStart: 0,
|
|
3956
4003
|
rangeEnd: 0,
|
|
@@ -4213,6 +4260,30 @@ describe('plugin-meetings', () => {
|
|
|
4213
4260
|
|
|
4214
4261
|
assert.calledOnceWithExactly(mockHashTreeParser.handleMessage, fakeHashTreeMessage);
|
|
4215
4262
|
});
|
|
4263
|
+
|
|
4264
|
+
it('ignores hash tree event when hashTreeParser is not created yet', () => {
|
|
4265
|
+
const data = {
|
|
4266
|
+
eventType: LOCUSEVENT.HASH_TREE_DATA_UPDATED,
|
|
4267
|
+
stateElementsMessage: {
|
|
4268
|
+
locusStateElements: [],
|
|
4269
|
+
dataSets: [],
|
|
4270
|
+
},
|
|
4271
|
+
};
|
|
4272
|
+
|
|
4273
|
+
const loggerSpy = sinon.spy(LoggerProxy.logger, 'info');
|
|
4274
|
+
const getTheLocusToUpdateStub = sinon.stub(locusInfo, 'getTheLocusToUpdate');
|
|
4275
|
+
|
|
4276
|
+
// Ensure we're not using hash trees
|
|
4277
|
+
assert.isUndefined(locusInfo.hashTreeParser);
|
|
4278
|
+
|
|
4279
|
+
locusInfo.parse(mockMeeting, data);
|
|
4280
|
+
|
|
4281
|
+
assert.calledWith(
|
|
4282
|
+
loggerSpy,
|
|
4283
|
+
'Locus-info:index#parse --> received locus hash tree event before hashTreeParser is created'
|
|
4284
|
+
);
|
|
4285
|
+
assert.notCalled(getTheLocusToUpdateStub);
|
|
4286
|
+
});
|
|
4216
4287
|
});
|
|
4217
4288
|
});
|
|
4218
4289
|
});
|
|
@@ -5,6 +5,8 @@ import {ConnectionState, MediaConnectionEventNames} from '@webex/internal-media-
|
|
|
5
5
|
import testUtils from '../../../utils/testUtils';
|
|
6
6
|
import {ICE_AND_DTLS_CONNECTION_TIMEOUT} from '@webex/plugin-meetings/src/constants';
|
|
7
7
|
import MediaConnectionAwaiter from '../../../../src/media/MediaConnectionAwaiter';
|
|
8
|
+
import Metrics from '../../../../src/metrics';
|
|
9
|
+
import BEHAVIORAL_METRICS from '../../../../src/metrics/constants';
|
|
8
10
|
|
|
9
11
|
describe('MediaConnectionAwaiter', () => {
|
|
10
12
|
let mediaConnectionAwaiter;
|
|
@@ -14,18 +16,34 @@ describe('MediaConnectionAwaiter', () => {
|
|
|
14
16
|
beforeEach(() => {
|
|
15
17
|
clock = sinon.useFakeTimers();
|
|
16
18
|
|
|
19
|
+
const mockTransportReport = {
|
|
20
|
+
type: 'transport',
|
|
21
|
+
dtlsState: 'connecting',
|
|
22
|
+
iceState: 'checking',
|
|
23
|
+
packetsSent: 10,
|
|
24
|
+
packetsReceived: 5,
|
|
25
|
+
};
|
|
26
|
+
|
|
17
27
|
mockMC = {
|
|
18
|
-
getStats: sinon.stub().resolves(
|
|
28
|
+
getStats: sinon.stub().resolves({
|
|
29
|
+
values: () => [mockTransportReport],
|
|
30
|
+
}),
|
|
19
31
|
on: sinon.stub(),
|
|
20
32
|
off: sinon.stub(),
|
|
21
33
|
getConnectionState: sinon.stub().returns(ConnectionState.New),
|
|
22
34
|
getIceGatheringState: sinon.stub().returns('new'),
|
|
23
35
|
getIceConnectionState: sinon.stub().returns('new'),
|
|
24
36
|
getPeerConnectionState: sinon.stub().returns('new'),
|
|
37
|
+
multistreamConnection: {
|
|
38
|
+
dataChannel: {
|
|
39
|
+
readyState: 'open',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
25
42
|
};
|
|
26
43
|
|
|
27
44
|
mediaConnectionAwaiter = new MediaConnectionAwaiter({
|
|
28
45
|
webrtcMediaConnection: mockMC,
|
|
46
|
+
correlationId: 'test-correlation-id',
|
|
29
47
|
});
|
|
30
48
|
});
|
|
31
49
|
|
|
@@ -44,6 +62,8 @@ describe('MediaConnectionAwaiter', () => {
|
|
|
44
62
|
});
|
|
45
63
|
|
|
46
64
|
it('rejects after timeout if ice state is not connected', async () => {
|
|
65
|
+
const sendMetricSpy = sinon.spy(Metrics, 'sendBehavioralMetric');
|
|
66
|
+
|
|
47
67
|
mockMC.getConnectionState.returns(ConnectionState.Connecting);
|
|
48
68
|
mockMC.getIceGatheringState.returns('gathering');
|
|
49
69
|
|
|
@@ -83,6 +103,18 @@ describe('MediaConnectionAwaiter', () => {
|
|
|
83
103
|
assert.equal(promiseRejected, true);
|
|
84
104
|
|
|
85
105
|
assert.calledThrice(mockMC.off);
|
|
106
|
+
|
|
107
|
+
assert.calledOnceWithExactly(sendMetricSpy, BEHAVIORAL_METRICS.MEDIA_STILL_NOT_CONNECTED, {
|
|
108
|
+
correlation_id: 'test-correlation-id',
|
|
109
|
+
numTransports: 1,
|
|
110
|
+
dtlsState: 'connecting',
|
|
111
|
+
iceState: 'checking',
|
|
112
|
+
packetsSent: 10,
|
|
113
|
+
packetsReceived: 5,
|
|
114
|
+
dataChannelState: 'open',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
sendMetricSpy.restore();
|
|
86
118
|
});
|
|
87
119
|
|
|
88
120
|
it('rejects immediately if ice state is FAILED', async () => {
|
|
@@ -351,6 +383,8 @@ describe('MediaConnectionAwaiter', () => {
|
|
|
351
383
|
});
|
|
352
384
|
|
|
353
385
|
it(`reject with restart timer once if gathering state is not complete`, async () => {
|
|
386
|
+
const sendMetricSpy = sinon.spy(Metrics, 'sendBehavioralMetric');
|
|
387
|
+
|
|
354
388
|
mockMC.getConnectionState.returns(ConnectionState.Connecting);
|
|
355
389
|
mockMC.getIceGatheringState.returns('new');
|
|
356
390
|
|
|
@@ -390,6 +424,12 @@ describe('MediaConnectionAwaiter', () => {
|
|
|
390
424
|
|
|
391
425
|
assert.calledOnce(clearTimeoutSpy);
|
|
392
426
|
assert.calledTwice(setTimeoutSpy);
|
|
427
|
+
|
|
428
|
+
// verify sendMetric was called twice (once for each timeout)
|
|
429
|
+
assert.calledTwice(sendMetricSpy);
|
|
430
|
+
assert.calledWith(sendMetricSpy, BEHAVIORAL_METRICS.MEDIA_STILL_NOT_CONNECTED);
|
|
431
|
+
|
|
432
|
+
sendMetricSpy.restore();
|
|
393
433
|
});
|
|
394
434
|
|
|
395
435
|
it(`resolves gathering and connection state complete right after`, async () => {
|
|
@@ -41,14 +41,23 @@ describe('MediaProperties', () => {
|
|
|
41
41
|
describe('waitForMediaConnectionConnected', () => {
|
|
42
42
|
it('resolves if media connection is connected', async () => {
|
|
43
43
|
const waitForMediaConnectionConnectedResult = new Defer();
|
|
44
|
+
const correlationId = 'aaaa-bbbb-cccc-dddd';
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
let capturedInstance;
|
|
47
|
+
const stub = sinon
|
|
46
48
|
.stub(MediaConnectionAwaiter.prototype, 'waitForMediaConnectionConnected')
|
|
47
|
-
.
|
|
49
|
+
.callsFake(function () {
|
|
50
|
+
capturedInstance = this;
|
|
51
|
+
return waitForMediaConnectionConnectedResult.promise;
|
|
52
|
+
});
|
|
48
53
|
|
|
49
54
|
waitForMediaConnectionConnectedResult.resolve();
|
|
50
55
|
|
|
51
|
-
await mediaProperties.waitForMediaConnectionConnected();
|
|
56
|
+
await mediaProperties.waitForMediaConnectionConnected(correlationId);
|
|
57
|
+
|
|
58
|
+
assert.calledOnce(stub);
|
|
59
|
+
assert.equal(capturedInstance.correlationId, correlationId);
|
|
60
|
+
assert.equal(capturedInstance.webrtcMediaConnection, mockMC);
|
|
52
61
|
});
|
|
53
62
|
it('rejects if media connection is not connected', async () => {
|
|
54
63
|
const waitForMediaConnectionConnectedResult = new Defer();
|
|
@@ -1249,7 +1249,7 @@ describe('plugin-meetings', () => {
|
|
|
1249
1249
|
});
|
|
1250
1250
|
|
|
1251
1251
|
[
|
|
1252
|
-
{errorName: 'SdpOfferCreationError', description: 'if we fail to create the offer on first attempt'},
|
|
1252
|
+
{errorName: 'SdpOfferCreationError', description: 'if we fail to create the offer on first attempt'},
|
|
1253
1253
|
{errorName: 'WebrtcApiNotAvailableError', description: 'if RTCPeerConnection is not available'},
|
|
1254
1254
|
].forEach(({errorName, description}) => {
|
|
1255
1255
|
it(`should not attempt a retry ${description}`, async () => {
|
|
@@ -1882,6 +1882,53 @@ describe('plugin-meetings', () => {
|
|
|
1882
1882
|
fakeProcessedReaction
|
|
1883
1883
|
);
|
|
1884
1884
|
});
|
|
1885
|
+
|
|
1886
|
+
it('should process if participantId does not exist in membersCollection but has displayName in Webinar', () => {
|
|
1887
|
+
LoggerProxy.logger.warn = sinon.stub();
|
|
1888
|
+
meeting.isReactionsSupported = sinon.stub().returns(true);
|
|
1889
|
+
meeting.config.receiveReactions = true;
|
|
1890
|
+
meeting.locusInfo.info = {isWebinar: true};
|
|
1891
|
+
const fakeSendersName = 'Fake reactors name';
|
|
1892
|
+
const fakeReactionPayload = {
|
|
1893
|
+
type: 'fake_type',
|
|
1894
|
+
codepoints: 'fake_codepoints',
|
|
1895
|
+
shortcodes: 'fake_shortcodes',
|
|
1896
|
+
tone: {
|
|
1897
|
+
type: 'fake_tone_type',
|
|
1898
|
+
codepoints: 'fake_tone_codepoints',
|
|
1899
|
+
shortcodes: 'fake_tone_shortcodes',
|
|
1900
|
+
},
|
|
1901
|
+
};
|
|
1902
|
+
const fakeSenderPayload = {
|
|
1903
|
+
displayName: 'Fake reactors name',
|
|
1904
|
+
participantId: 'fake_participant_id',
|
|
1905
|
+
};
|
|
1906
|
+
const fakeProcessedReaction = {
|
|
1907
|
+
reaction: fakeReactionPayload,
|
|
1908
|
+
sender: {
|
|
1909
|
+
id: fakeSenderPayload.participantId,
|
|
1910
|
+
name: fakeSendersName,
|
|
1911
|
+
},
|
|
1912
|
+
};
|
|
1913
|
+
const fakeRelayEvent = {
|
|
1914
|
+
data: {
|
|
1915
|
+
relayType: REACTION_RELAY_TYPES.REACTION,
|
|
1916
|
+
reaction: fakeReactionPayload,
|
|
1917
|
+
sender: fakeSenderPayload,
|
|
1918
|
+
},
|
|
1919
|
+
};
|
|
1920
|
+
meeting.processRelayEvent(fakeRelayEvent);
|
|
1921
|
+
assert.calledWith(
|
|
1922
|
+
TriggerProxy.trigger,
|
|
1923
|
+
sinon.match.instanceOf(Meeting),
|
|
1924
|
+
{
|
|
1925
|
+
file: 'meeting/index',
|
|
1926
|
+
function: 'join',
|
|
1927
|
+
},
|
|
1928
|
+
EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
|
|
1929
|
+
fakeProcessedReaction
|
|
1930
|
+
);
|
|
1931
|
+
});
|
|
1885
1932
|
});
|
|
1886
1933
|
|
|
1887
1934
|
describe('#handleLLMOnline', () => {
|
|
@@ -3028,6 +3075,111 @@ describe('plugin-meetings', () => {
|
|
|
3028
3075
|
checkWorking({allowMediaInLobby: true});
|
|
3029
3076
|
});
|
|
3030
3077
|
|
|
3078
|
+
const setupLobbyTest = () => {
|
|
3079
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
3080
|
+
.stub()
|
|
3081
|
+
.resolves({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});
|
|
3082
|
+
|
|
3083
|
+
meeting.meetingState = 'ACTIVE';
|
|
3084
|
+
meeting.locusInfo.parsedLocus = {self: {state: 'IDLE'}};
|
|
3085
|
+
meeting.isUserUnadmitted = true;
|
|
3086
|
+
|
|
3087
|
+
// Mock locusMediaRequest
|
|
3088
|
+
meeting.locusMediaRequest = {
|
|
3089
|
+
send: sinon.stub().resolves(),
|
|
3090
|
+
isConfluenceCreated: sinon.stub().returns(false),
|
|
3091
|
+
};
|
|
3092
|
+
|
|
3093
|
+
sinon.stub(RemoteMediaManagerModule, 'RemoteMediaManager').returns({
|
|
3094
|
+
start: sinon.stub().resolves(),
|
|
3095
|
+
on: sinon.stub(),
|
|
3096
|
+
logAllReceiveSlots: sinon.stub(),
|
|
3097
|
+
});
|
|
3098
|
+
|
|
3099
|
+
meeting.isMultistream = true;
|
|
3100
|
+
|
|
3101
|
+
const createFakeStream = (id) => ({
|
|
3102
|
+
on: sinon.stub(),
|
|
3103
|
+
off: sinon.stub(),
|
|
3104
|
+
userMuted: false,
|
|
3105
|
+
systemMuted: false,
|
|
3106
|
+
get muted() {
|
|
3107
|
+
return this.userMuted || this.systemMuted;
|
|
3108
|
+
},
|
|
3109
|
+
setUnmuteAllowed: sinon.stub(),
|
|
3110
|
+
setUserMuted: sinon.stub(),
|
|
3111
|
+
outputStream: {
|
|
3112
|
+
getTracks: () => [{id}],
|
|
3113
|
+
},
|
|
3114
|
+
getSettings: sinon.stub().returns({}),
|
|
3115
|
+
});
|
|
3116
|
+
|
|
3117
|
+
return {
|
|
3118
|
+
fakeMicrophoneStream: createFakeStream('fake mic'),
|
|
3119
|
+
fakeCameraStream: createFakeStream('fake camera'),
|
|
3120
|
+
};
|
|
3121
|
+
};
|
|
3122
|
+
|
|
3123
|
+
it('should not publish any local streams when in the lobby and allowPublishMediaInLobby is false', async () => {
|
|
3124
|
+
const {fakeMicrophoneStream, fakeCameraStream} = setupLobbyTest();
|
|
3125
|
+
|
|
3126
|
+
const publishStreamStub = sinon.stub();
|
|
3127
|
+
fakeMediaConnection.createSendSlot = sinon.stub().returns({
|
|
3128
|
+
publishStream: publishStreamStub,
|
|
3129
|
+
unpublishStream: sinon.stub(),
|
|
3130
|
+
setNamedMediaGroups: sinon.stub(),
|
|
3131
|
+
});
|
|
3132
|
+
|
|
3133
|
+
await meeting.addMedia({
|
|
3134
|
+
allowMediaInLobby: true,
|
|
3135
|
+
allowPublishMediaInLobby: false,
|
|
3136
|
+
audioEnabled: true,
|
|
3137
|
+
videoEnabled: true,
|
|
3138
|
+
localStreams: {
|
|
3139
|
+
microphone: fakeMicrophoneStream,
|
|
3140
|
+
camera: fakeCameraStream,
|
|
3141
|
+
},
|
|
3142
|
+
});
|
|
3143
|
+
|
|
3144
|
+
assert.notCalled(publishStreamStub);
|
|
3145
|
+
});
|
|
3146
|
+
|
|
3147
|
+
it('should publish local streams when in the lobby and allowPublishMediaInLobby is true', async () => {
|
|
3148
|
+
const {fakeMicrophoneStream, fakeCameraStream} = setupLobbyTest();
|
|
3149
|
+
|
|
3150
|
+
const audioSlot = {
|
|
3151
|
+
publishStream: sinon.stub(),
|
|
3152
|
+
unpublishStream: sinon.stub(),
|
|
3153
|
+
setNamedMediaGroups: sinon.stub(),
|
|
3154
|
+
};
|
|
3155
|
+
const videoSlot = {
|
|
3156
|
+
publishStream: sinon.stub(),
|
|
3157
|
+
unpublishStream: sinon.stub(),
|
|
3158
|
+
setNamedMediaGroups: sinon.stub(),
|
|
3159
|
+
};
|
|
3160
|
+
|
|
3161
|
+
fakeMediaConnection.createSendSlot = sinon.stub().callsFake((mediaType) => {
|
|
3162
|
+
if (mediaType === 'AUDIO-MAIN') {
|
|
3163
|
+
return audioSlot;
|
|
3164
|
+
}
|
|
3165
|
+
return videoSlot;
|
|
3166
|
+
});
|
|
3167
|
+
|
|
3168
|
+
await meeting.addMedia({
|
|
3169
|
+
allowMediaInLobby: true,
|
|
3170
|
+
allowPublishMediaInLobby: true,
|
|
3171
|
+
audioEnabled: true,
|
|
3172
|
+
videoEnabled: true,
|
|
3173
|
+
localStreams: {
|
|
3174
|
+
microphone: fakeMicrophoneStream,
|
|
3175
|
+
camera: fakeCameraStream,
|
|
3176
|
+
},
|
|
3177
|
+
});
|
|
3178
|
+
|
|
3179
|
+
assert.calledOnceWithExactly(audioSlot.publishStream, fakeMicrophoneStream);
|
|
3180
|
+
assert.calledOnceWithExactly(videoSlot.publishStream, fakeCameraStream);
|
|
3181
|
+
});
|
|
3182
|
+
|
|
3031
3183
|
it('should create rtcMetrics and pass them to Media.createMediaConnection()', async () => {
|
|
3032
3184
|
const setIntervalOriginal = window.setInterval;
|
|
3033
3185
|
window.setInterval = sinon.stub().returns(1);
|
|
@@ -9149,7 +9301,10 @@ describe('plugin-meetings', () => {
|
|
|
9149
9301
|
|
|
9150
9302
|
// check that the right things were called by the callback
|
|
9151
9303
|
assert.calledOnceWithExactly(meeting.waitForRemoteSDPAnswer);
|
|
9152
|
-
assert.calledOnceWithExactly(
|
|
9304
|
+
assert.calledOnceWithExactly(
|
|
9305
|
+
meeting.mediaProperties.waitForMediaConnectionConnected,
|
|
9306
|
+
meeting.correlationId
|
|
9307
|
+
);
|
|
9153
9308
|
});
|
|
9154
9309
|
});
|
|
9155
9310
|
|
|
@@ -12628,6 +12783,7 @@ describe('plugin-meetings', () => {
|
|
|
12628
12783
|
|
|
12629
12784
|
it('should read the locus object, set on the meeting and return null', () => {
|
|
12630
12785
|
const dataSets = {someFakeStuff: 'dataSet'};
|
|
12786
|
+
const metadata = {some: 'metadata'};
|
|
12631
12787
|
|
|
12632
12788
|
meeting.setLocus({
|
|
12633
12789
|
mediaConnections: [test1],
|
|
@@ -12637,12 +12793,14 @@ describe('plugin-meetings', () => {
|
|
|
12637
12793
|
mediaId: uuid3,
|
|
12638
12794
|
locus: {host: {id: uuid4}},
|
|
12639
12795
|
dataSets,
|
|
12796
|
+
metadata,
|
|
12640
12797
|
});
|
|
12641
12798
|
assert.calledOnce(meeting.locusInfo.initialSetup);
|
|
12642
12799
|
assert.calledWith(meeting.locusInfo.initialSetup, {
|
|
12643
12800
|
trigger: 'join-response',
|
|
12644
12801
|
locus: {host: {id: uuid4}},
|
|
12645
12802
|
dataSets,
|
|
12803
|
+
metadata,
|
|
12646
12804
|
});
|
|
12647
12805
|
assert.equal(meeting.mediaConnections, test1);
|
|
12648
12806
|
assert.equal(meeting.locusUrl, url1);
|