@webex/plugin-meetings 3.6.0-next.9 → 3.7.0-ipv6-multi-turn-urls.1
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/README.md +2 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
- package/dist/common/errors/join-webinar-error.js.map +1 -0
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +50 -7
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +1 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +10 -3
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +12 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.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 -4
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js +2 -1
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/index.js +61 -3
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/index.js +29 -1
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +29 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +692 -472
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +2 -6
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/request.js +21 -29
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +95 -59
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +29 -17
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +8 -3
- package/dist/meetings/index.js.map +1 -1
- package/dist/members/index.js +3 -2
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +13 -7
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +3 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMedia.js +30 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/reachability/clusterReachability.js +12 -15
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +433 -136
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +7 -0
- package/dist/reachability/reachability.types.js.map +1 -0
- package/dist/reachability/request.js +23 -9
- package/dist/reachability/request.js.map +1 -1
- package/dist/recording-controller/enums.js +8 -4
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +18 -9
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +13 -9
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +5 -7
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +45 -79
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +3 -6
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
- package/dist/types/config.d.ts +2 -0
- package/dist/types/constants.d.ts +38 -1
- package/dist/types/controls-options-manager/enums.d.ts +2 -1
- package/dist/types/controls-options-manager/index.d.ts +2 -1
- package/dist/types/controls-options-manager/types.d.ts +2 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/locus-info/index.d.ts +9 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +28 -0
- package/dist/types/meeting/index.d.ts +34 -3
- package/dist/types/meeting/locusMediaRequest.d.ts +2 -3
- package/dist/types/meeting/request.d.ts +2 -2
- package/dist/types/meeting/util.d.ts +2 -2
- package/dist/types/meeting-info/meeting-info-v2.d.ts +4 -4
- package/dist/types/meetings/index.d.ts +4 -1
- package/dist/types/members/index.d.ts +2 -1
- package/dist/types/members/util.d.ts +5 -1
- package/dist/types/metrics/constants.d.ts +3 -1
- package/dist/types/reachability/clusterReachability.d.ts +1 -10
- package/dist/types/reachability/index.d.ts +74 -35
- package/dist/types/reachability/reachability.types.d.ts +64 -0
- package/dist/types/reachability/request.d.ts +5 -1
- package/dist/types/recording-controller/enums.d.ts +5 -2
- package/dist/types/recording-controller/index.d.ts +1 -0
- package/dist/types/recording-controller/util.d.ts +2 -1
- package/dist/types/roap/request.d.ts +1 -13
- package/dist/webinar/index.js +382 -19
- package/dist/webinar/index.js.map +1 -1
- package/package.json +22 -22
- package/src/common/errors/join-webinar-error.ts +24 -0
- package/src/config.ts +2 -0
- package/src/constants.ts +49 -3
- package/src/controls-options-manager/enums.ts +1 -0
- package/src/controls-options-manager/index.ts +19 -2
- package/src/controls-options-manager/types.ts +2 -0
- package/src/controls-options-manager/util.ts +12 -0
- package/src/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +46 -2
- package/src/locus-info/fullState.ts +1 -0
- package/src/locus-info/index.ts +60 -0
- package/src/media/index.ts +15 -0
- package/src/meeting/in-meeting-actions.ts +58 -0
- package/src/meeting/index.ts +232 -25
- package/src/meeting/locusMediaRequest.ts +4 -8
- package/src/meeting/request.ts +4 -11
- package/src/meeting/util.ts +25 -4
- package/src/meeting-info/meeting-info-v2.ts +23 -11
- package/src/meetings/index.ts +54 -41
- package/src/members/index.ts +4 -2
- package/src/members/util.ts +4 -1
- package/src/metrics/constants.ts +3 -1
- package/src/multistream/remoteMedia.ts +28 -15
- package/src/reachability/clusterReachability.ts +5 -15
- package/src/reachability/index.ts +285 -77
- package/src/reachability/reachability.types.ts +85 -0
- package/src/reachability/request.ts +55 -30
- package/src/recording-controller/enums.ts +5 -2
- package/src/recording-controller/index.ts +17 -4
- package/src/recording-controller/util.ts +20 -5
- package/src/roap/index.ts +4 -5
- package/src/roap/request.ts +30 -44
- package/src/roap/turnDiscovery.ts +2 -4
- package/src/webinar/index.ts +223 -17
- package/test/unit/spec/controls-options-manager/index.js +56 -32
- package/test/unit/spec/controls-options-manager/util.js +44 -0
- package/test/unit/spec/locus-info/controlsUtils.js +80 -4
- package/test/unit/spec/locus-info/index.js +59 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +31 -1
- package/test/unit/spec/meeting/index.js +369 -103
- package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
- package/test/unit/spec/meeting/request.js +3 -26
- package/test/unit/spec/meeting/utils.js +55 -13
- package/test/unit/spec/meeting-info/meetinginfov2.js +9 -4
- package/test/unit/spec/meetings/index.js +25 -6
- package/test/unit/spec/members/index.js +25 -2
- package/test/unit/spec/members/request.js +37 -3
- package/test/unit/spec/members/utils.js +110 -1
- package/test/unit/spec/multistream/remoteMedia.ts +11 -7
- package/test/unit/spec/reachability/clusterReachability.ts +7 -0
- package/test/unit/spec/reachability/index.ts +265 -1
- package/test/unit/spec/reachability/request.js +56 -15
- package/test/unit/spec/recording-controller/index.js +61 -5
- package/test/unit/spec/recording-controller/util.js +39 -3
- package/test/unit/spec/roap/index.ts +1 -1
- package/test/unit/spec/roap/request.ts +51 -109
- package/test/unit/spec/roap/turnDiscovery.ts +202 -147
- package/test/unit/spec/webinar/index.ts +443 -14
- package/dist/common/errors/webinar-registration-error.js.map +0 -1
- package/src/common/errors/webinar-registration-error.ts +0 -27
|
@@ -34,12 +34,19 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
34
34
|
'wjfkm.wjfkm.*': {udp:{reachable: true}, tcp:{reachable:false}},
|
|
35
35
|
'1eb65fdf-9643-417f-9974-ad72cae0e10f.59268c12-7a04-4b23-a1a1-4c74be03019a.*': {udp:{reachable: false}, tcp:{reachable:true}},
|
|
36
36
|
},
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
clientMediaPreferences: {
|
|
38
|
+
preferTranscoding: false,
|
|
39
|
+
joinCookie: {
|
|
40
|
+
anycastEntryPoint: 'aws-eu-west-1',
|
|
41
|
+
clientIpAddress: 'some ip',
|
|
42
|
+
timeShot: '2023-05-23T08:03:49Z',
|
|
43
|
+
},
|
|
44
|
+
ipver: IP_VERSION.only_ipv4,
|
|
45
|
+
reachability: {
|
|
46
|
+
version: '1',
|
|
47
|
+
result: 'some fake reachability result',
|
|
48
|
+
}
|
|
49
|
+
}
|
|
43
50
|
};
|
|
44
51
|
|
|
45
52
|
const createExpectedRoapBody = (expectedMessageType, expectedMute:{audioMuted: boolean, videoMuted: boolean}) => {
|
|
@@ -53,12 +60,16 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
53
60
|
}
|
|
54
61
|
],
|
|
55
62
|
clientMediaPreferences: {
|
|
56
|
-
preferTranscoding:
|
|
63
|
+
preferTranscoding: false,
|
|
57
64
|
ipver: 4,
|
|
58
65
|
joinCookie: {
|
|
59
66
|
anycastEntryPoint: 'aws-eu-west-1',
|
|
60
67
|
clientIpAddress: 'some ip',
|
|
61
68
|
timeShot: '2023-05-23T08:03:49Z'
|
|
69
|
+
},
|
|
70
|
+
reachability: {
|
|
71
|
+
version: '1',
|
|
72
|
+
result: 'some fake reachability result',
|
|
62
73
|
}
|
|
63
74
|
}
|
|
64
75
|
};
|
|
@@ -87,10 +98,6 @@ describe('LocusMediaRequest.send()', () => {
|
|
|
87
98
|
localSdp: `{"audioMuted":${expectedMute.audioMuted},"videoMuted":${expectedMute.videoMuted}}`,
|
|
88
99
|
},
|
|
89
100
|
],
|
|
90
|
-
clientMediaPreferences: {
|
|
91
|
-
preferTranscoding: true,
|
|
92
|
-
ipver: undefined,
|
|
93
|
-
},
|
|
94
101
|
};
|
|
95
102
|
|
|
96
103
|
if (sequence) {
|
|
@@ -196,6 +196,7 @@ describe('plugin-meetings', () => {
|
|
|
196
196
|
const permissionToken = 'permission-token';
|
|
197
197
|
const installationId = 'installationId';
|
|
198
198
|
const reachability = 'reachability';
|
|
199
|
+
const clientMediaPreferences = 'clientMediaPreferences';
|
|
199
200
|
|
|
200
201
|
await meetingsRequest.joinMeeting({
|
|
201
202
|
locusUrl,
|
|
@@ -204,6 +205,7 @@ describe('plugin-meetings', () => {
|
|
|
204
205
|
roapMessage,
|
|
205
206
|
reachability,
|
|
206
207
|
permissionToken,
|
|
208
|
+
clientMediaPreferences
|
|
207
209
|
});
|
|
208
210
|
const requestParams = meetingsRequest.request.getCall(0).args[0];
|
|
209
211
|
|
|
@@ -214,6 +216,7 @@ describe('plugin-meetings', () => {
|
|
|
214
216
|
assert.equal(requestParams.body.device.countryCode, 'US');
|
|
215
217
|
assert.equal(requestParams.body.permissionToken, 'permission-token');
|
|
216
218
|
assert.equal(requestParams.body.device.regionCode, 'WEST-COAST');
|
|
219
|
+
assert.equal(requestParams.body.clientMediaPreferences, 'clientMediaPreferences');
|
|
217
220
|
assert.include(requestParams.body.device.localIp, '127.0.0');
|
|
218
221
|
assert.deepEqual(requestParams.body.localMedias, [
|
|
219
222
|
{localSdp: '{"roapMessage":"roap-message","reachability":"reachability"}'},
|
|
@@ -386,32 +389,6 @@ describe('plugin-meetings', () => {
|
|
|
386
389
|
|
|
387
390
|
assert.deepEqual(requestParams.body.alias, undefined);
|
|
388
391
|
});
|
|
389
|
-
|
|
390
|
-
it('includes joinCookie and ipver correctly', async () => {
|
|
391
|
-
const locusUrl = 'locusURL';
|
|
392
|
-
const deviceUrl = 'deviceUrl';
|
|
393
|
-
const correlationId = 'random-uuid';
|
|
394
|
-
const roapMessage = 'roap-message';
|
|
395
|
-
const permissionToken = 'permission-token';
|
|
396
|
-
|
|
397
|
-
await meetingsRequest.joinMeeting({
|
|
398
|
-
locusUrl,
|
|
399
|
-
deviceUrl,
|
|
400
|
-
correlationId,
|
|
401
|
-
roapMessage,
|
|
402
|
-
permissionToken,
|
|
403
|
-
ipVersion: IP_VERSION.ipv4_and_ipv6,
|
|
404
|
-
});
|
|
405
|
-
const requestParams = meetingsRequest.request.getCall(0).args[0];
|
|
406
|
-
|
|
407
|
-
assert.equal(requestParams.method, 'POST');
|
|
408
|
-
assert.equal(requestParams.uri, `${locusUrl}/participant?alternateRedirect=true`);
|
|
409
|
-
assert.deepEqual(requestParams.body.clientMediaPreferences, {
|
|
410
|
-
joinCookie: {anycastEntryPoint: 'aws-eu-west-1'},
|
|
411
|
-
preferTranscoding: true,
|
|
412
|
-
ipver: 1,
|
|
413
|
-
});
|
|
414
|
-
});
|
|
415
392
|
});
|
|
416
393
|
|
|
417
394
|
describe('#pstn', () => {
|
|
@@ -22,6 +22,12 @@ describe('plugin-meetings', () => {
|
|
|
22
22
|
meetings: Meetings,
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
|
+
|
|
26
|
+
webex.meetings.reachability = {
|
|
27
|
+
getReachabilityReportToAttachToRoap: sinon.stub().resolves({}),
|
|
28
|
+
getClientMediaPreferences: sinon.stub().resolves({}),
|
|
29
|
+
};
|
|
30
|
+
|
|
25
31
|
const logger = {
|
|
26
32
|
info: sandbox.stub(),
|
|
27
33
|
log: sandbox.stub(),
|
|
@@ -39,6 +45,7 @@ describe('plugin-meetings', () => {
|
|
|
39
45
|
meeting.cleanupLocalStreams = sinon.stub().returns(Promise.resolve());
|
|
40
46
|
meeting.closeRemoteStreams = sinon.stub().returns(Promise.resolve());
|
|
41
47
|
meeting.closePeerConnections = sinon.stub().returns(Promise.resolve());
|
|
48
|
+
meeting.stopPeriodicLogUpload = sinon.stub();
|
|
42
49
|
|
|
43
50
|
meeting.unsetRemoteStreams = sinon.stub();
|
|
44
51
|
meeting.unsetPeerConnections = sinon.stub();
|
|
@@ -64,6 +71,7 @@ describe('plugin-meetings', () => {
|
|
|
64
71
|
assert.calledOnce(meeting.cleanupLocalStreams);
|
|
65
72
|
assert.calledOnce(meeting.closeRemoteStreams);
|
|
66
73
|
assert.calledOnce(meeting.closePeerConnections);
|
|
74
|
+
assert.calledOnce(meeting.stopPeriodicLogUpload);
|
|
67
75
|
|
|
68
76
|
assert.calledOnce(meeting.unsetRemoteStreams);
|
|
69
77
|
assert.calledOnce(meeting.unsetPeerConnections);
|
|
@@ -408,17 +416,39 @@ describe('plugin-meetings', () => {
|
|
|
408
416
|
});
|
|
409
417
|
|
|
410
418
|
it('#Should call `meetingRequest.joinMeeting', async () => {
|
|
419
|
+
meeting.isMultistream = true;
|
|
420
|
+
|
|
421
|
+
const FAKE_REACHABILITY_REPORT = {
|
|
422
|
+
id: 'fake reachability report',
|
|
423
|
+
};
|
|
424
|
+
const FAKE_CLIENT_MEDIA_PREFERENCES = {
|
|
425
|
+
id: 'fake client media preferences',
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
webex.meetings.reachability.getReachabilityReportToAttachToRoap.resolves(FAKE_REACHABILITY_REPORT);
|
|
429
|
+
webex.meetings.reachability.getClientMediaPreferences.resolves(FAKE_CLIENT_MEDIA_PREFERENCES);
|
|
430
|
+
|
|
431
|
+
sinon
|
|
432
|
+
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4')
|
|
433
|
+
.get(() => true);
|
|
434
|
+
sinon
|
|
435
|
+
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6')
|
|
436
|
+
.get(() => true);
|
|
437
|
+
|
|
411
438
|
await MeetingUtil.joinMeeting(meeting, {
|
|
412
439
|
reachability: 'reachability',
|
|
413
440
|
roapMessage: 'roapMessage',
|
|
414
441
|
});
|
|
415
442
|
|
|
443
|
+
assert.calledOnceWithExactly(webex.meetings.reachability.getReachabilityReportToAttachToRoap);
|
|
444
|
+
assert.calledOnceWithExactly(webex.meetings.reachability.getClientMediaPreferences, meeting.isMultistream, IP_VERSION.ipv4_and_ipv6);
|
|
445
|
+
|
|
416
446
|
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
417
447
|
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
418
448
|
|
|
419
449
|
assert.equal(parameter.inviteeAddress, 'meetingJoinUrl');
|
|
420
|
-
assert.equal(parameter.
|
|
421
|
-
assert.equal(parameter.
|
|
450
|
+
assert.equal(parameter.reachability, FAKE_REACHABILITY_REPORT);
|
|
451
|
+
assert.equal(parameter.clientMediaPreferences, FAKE_CLIENT_MEDIA_PREFERENCES);
|
|
422
452
|
assert.equal(parameter.roapMessage, 'roapMessage');
|
|
423
453
|
|
|
424
454
|
assert.calledOnce(meeting.setLocus)
|
|
@@ -445,6 +475,29 @@ describe('plugin-meetings', () => {
|
|
|
445
475
|
});
|
|
446
476
|
});
|
|
447
477
|
|
|
478
|
+
it('should handle failed reachability report retrieval', async () => {
|
|
479
|
+
webex.meetings.reachability.getReachabilityReportToAttachToRoap.rejects(
|
|
480
|
+
new Error('fake error')
|
|
481
|
+
);
|
|
482
|
+
await MeetingUtil.joinMeeting(meeting, {});
|
|
483
|
+
// Verify meeting join still proceeds
|
|
484
|
+
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('should handle failed clientMediaPreferences retrieval', async () => {
|
|
488
|
+
webex.meetings.reachability.getClientMediaPreferences.rejects(new Error('fake error'));
|
|
489
|
+
meeting.isMultistream = true;
|
|
490
|
+
await MeetingUtil.joinMeeting(meeting, {});
|
|
491
|
+
// Verify meeting join still proceeds
|
|
492
|
+
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
493
|
+
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
494
|
+
assert.deepEqual(parameter.clientMediaPreferences, {
|
|
495
|
+
preferTranscoding: false,
|
|
496
|
+
ipver: 0,
|
|
497
|
+
joinCookie: undefined,
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
|
|
448
501
|
it('#Should call meetingRequest.joinMeeting with breakoutsSupported=true when passed in as true', async () => {
|
|
449
502
|
await MeetingUtil.joinMeeting(meeting, {
|
|
450
503
|
breakoutsSupported: true,
|
|
@@ -480,17 +533,6 @@ describe('plugin-meetings', () => {
|
|
|
480
533
|
assert.deepEqual(parameter.deviceCapabilities, ['TEST']);
|
|
481
534
|
});
|
|
482
535
|
|
|
483
|
-
it('#Should call meetingRequest.joinMeeting with preferTranscoding=false when multistream is enabled', async () => {
|
|
484
|
-
meeting.isMultistream = true;
|
|
485
|
-
await MeetingUtil.joinMeeting(meeting, {});
|
|
486
|
-
|
|
487
|
-
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
488
|
-
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
489
|
-
|
|
490
|
-
assert.equal(parameter.inviteeAddress, 'meetingJoinUrl');
|
|
491
|
-
assert.equal(parameter.preferTranscoding, false);
|
|
492
|
-
});
|
|
493
|
-
|
|
494
536
|
it('#Should fallback sipUrl if meetingJoinUrl does not exists', async () => {
|
|
495
537
|
meeting.meetingJoinUrl = undefined;
|
|
496
538
|
meeting.sipUri = 'sipUri';
|
|
@@ -18,7 +18,7 @@ import MeetingInfo, {
|
|
|
18
18
|
MeetingInfoV2CaptchaError,
|
|
19
19
|
MeetingInfoV2AdhocMeetingError,
|
|
20
20
|
MeetingInfoV2PolicyError,
|
|
21
|
-
|
|
21
|
+
MeetingInfoV2JoinWebinarError,
|
|
22
22
|
} from '@webex/plugin-meetings/src/meeting-info/meeting-info-v2';
|
|
23
23
|
import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
|
|
24
24
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
@@ -895,9 +895,14 @@ describe('plugin-meetings', () => {
|
|
|
895
895
|
{errorCode: 403021},
|
|
896
896
|
{errorCode: 403022},
|
|
897
897
|
{errorCode: 403024},
|
|
898
|
+
{errorCode: 403137},
|
|
899
|
+
{errorCode: 423007},
|
|
900
|
+
{errorCode: 403026},
|
|
901
|
+
{errorCode: 403037},
|
|
902
|
+
{errorCode: 403137},
|
|
898
903
|
],
|
|
899
904
|
({errorCode}) => {
|
|
900
|
-
it(`should throw a
|
|
905
|
+
it(`should throw a MeetingInfoV2JoinWebinarError for error code ${errorCode}`, async () => {
|
|
901
906
|
const message = 'a message';
|
|
902
907
|
const meetingInfoData = {meetingInfo: {registrationUrl: 'registrationUrl'}};
|
|
903
908
|
|
|
@@ -909,7 +914,7 @@ describe('plugin-meetings', () => {
|
|
|
909
914
|
await meetingInfo.createAdhocSpaceMeeting(conversationUrl, installedOrgID);
|
|
910
915
|
assert.fail('createAdhocSpaceMeeting should have thrown, but has not done that');
|
|
911
916
|
} catch (err) {
|
|
912
|
-
assert.instanceOf(err,
|
|
917
|
+
assert.instanceOf(err, MeetingInfoV2JoinWebinarError);
|
|
913
918
|
assert.deepEqual(err.message, `${message}, code=${errorCode}`);
|
|
914
919
|
assert.equal(err.wbxAppApiCode, errorCode);
|
|
915
920
|
assert.deepEqual(err.meetingInfo, meetingInfoData);
|
|
@@ -917,7 +922,7 @@ describe('plugin-meetings', () => {
|
|
|
917
922
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
918
923
|
assert.calledWith(
|
|
919
924
|
Metrics.sendBehavioralMetric,
|
|
920
|
-
BEHAVIORAL_METRICS.
|
|
925
|
+
BEHAVIORAL_METRICS.JOIN_WEBINAR_ERROR,
|
|
921
926
|
{code: errorCode}
|
|
922
927
|
);
|
|
923
928
|
|
|
@@ -131,9 +131,9 @@ describe('plugin-meetings', () => {
|
|
|
131
131
|
logger,
|
|
132
132
|
people: {
|
|
133
133
|
_getMe: sinon.stub().resolves({
|
|
134
|
-
type: 'validuser',
|
|
134
|
+
type: 'validuser',
|
|
135
135
|
}),
|
|
136
|
-
}
|
|
136
|
+
},
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
startReachabilityStub = sinon.stub(webex.meetings, 'startReachability').resolves();
|
|
@@ -1985,6 +1985,8 @@ describe('plugin-meetings', () => {
|
|
|
1985
1985
|
const meetingIds = {
|
|
1986
1986
|
meetingId: meeting.id,
|
|
1987
1987
|
correlationId: meeting.correlationId,
|
|
1988
|
+
roles: meeting.roles,
|
|
1989
|
+
callStateForMetrics: meeting.callStateForMetrics,
|
|
1988
1990
|
};
|
|
1989
1991
|
|
|
1990
1992
|
webex.meetings.destroy(meeting, test1);
|
|
@@ -2021,6 +2023,8 @@ describe('plugin-meetings', () => {
|
|
|
2021
2023
|
|
|
2022
2024
|
assert.equal(deletedMeetingInfo.id, meetingIds.meetingId);
|
|
2023
2025
|
assert.equal(deletedMeetingInfo.correlationId, meetingIds.correlationId);
|
|
2026
|
+
assert.equal(deletedMeetingInfo.roles, meetingIds.roles);
|
|
2027
|
+
assert.equal(deletedMeetingInfo.callStateForMetrics, meetingIds.callStateForMetrics);
|
|
2024
2028
|
});
|
|
2025
2029
|
});
|
|
2026
2030
|
|
|
@@ -2077,7 +2081,22 @@ describe('plugin-meetings', () => {
|
|
|
2077
2081
|
]);
|
|
2078
2082
|
});
|
|
2079
2083
|
|
|
2080
|
-
|
|
2084
|
+
it('should handle failure to get user information if scopes are insufficient', async () => {
|
|
2085
|
+
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
2086
|
+
Object.assign(webex.people, {
|
|
2087
|
+
_getMe: sinon.stub().returns(Promise.reject()),
|
|
2088
|
+
});
|
|
2089
|
+
|
|
2090
|
+
await webex.meetings.fetchUserPreferredWebexSite();
|
|
2091
|
+
|
|
2092
|
+
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
2093
|
+
assert.calledOnceWithExactly(
|
|
2094
|
+
loggerProxySpy,
|
|
2095
|
+
'Failed to retrieve user information. No preferredWebexSite will be set'
|
|
2096
|
+
);
|
|
2097
|
+
});
|
|
2098
|
+
|
|
2099
|
+
const setup = ({me = {type: 'validuser'}, user} = {}) => {
|
|
2081
2100
|
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
2082
2101
|
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
2083
2102
|
|
|
@@ -2093,14 +2112,14 @@ describe('plugin-meetings', () => {
|
|
|
2093
2112
|
|
|
2094
2113
|
Object.assign(webex.people, {
|
|
2095
2114
|
_getMe: sinon.stub().returns(Promise.resolve(me)),
|
|
2096
|
-
|
|
2115
|
+
});
|
|
2097
2116
|
};
|
|
2098
2117
|
|
|
2099
2118
|
it('should not call request.getMeetingPreferences if user is a guest', async () => {
|
|
2100
2119
|
setup({me: {type: 'appuser'}});
|
|
2101
|
-
|
|
2120
|
+
|
|
2102
2121
|
await webex.meetings.fetchUserPreferredWebexSite();
|
|
2103
|
-
|
|
2122
|
+
|
|
2104
2123
|
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
2105
2124
|
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
2106
2125
|
assert.notCalled(webex.internal.services.getMeetingPreferences);
|
|
@@ -660,17 +660,20 @@ describe('plugin-meetings', () => {
|
|
|
660
660
|
resultPromise,
|
|
661
661
|
spies,
|
|
662
662
|
expectedRequestingMemberId,
|
|
663
|
-
expectedLocusUrl
|
|
663
|
+
expectedLocusUrl,
|
|
664
|
+
expectedRoles,
|
|
664
665
|
) => {
|
|
665
666
|
await assert.isFulfilled(resultPromise);
|
|
666
667
|
assert.calledOnceWithExactly(
|
|
667
668
|
spies.generateLowerAllHandsMemberOptions,
|
|
668
669
|
expectedRequestingMemberId,
|
|
669
|
-
expectedLocusUrl
|
|
670
|
+
expectedLocusUrl,
|
|
671
|
+
expectedRoles,
|
|
670
672
|
);
|
|
671
673
|
assert.calledOnceWithExactly(spies.lowerAllHandsMember, {
|
|
672
674
|
requestingParticipantId: expectedRequestingMemberId,
|
|
673
675
|
locusUrl: expectedLocusUrl,
|
|
676
|
+
...(expectedRoles !== undefined && { roles: expectedRoles })
|
|
674
677
|
});
|
|
675
678
|
assert.strictEqual(resultPromise, spies.lowerAllHandsMember.getCall(0).returnValue);
|
|
676
679
|
};
|
|
@@ -707,6 +710,26 @@ describe('plugin-meetings', () => {
|
|
|
707
710
|
|
|
708
711
|
await checkValid(resultPromise, spies, requestingMemberId, url1);
|
|
709
712
|
});
|
|
713
|
+
|
|
714
|
+
it('should make the correct request when called with valid requestingMemberId and roles', async () => {
|
|
715
|
+
const requestingMemberId = 'test-member-id';
|
|
716
|
+
const roles = ['panelist', 'attendee'];
|
|
717
|
+
const { members, spies } = setup('test-locus-url');
|
|
718
|
+
|
|
719
|
+
const resultPromise = members.lowerAllHands(requestingMemberId, roles);
|
|
720
|
+
|
|
721
|
+
await checkValid(resultPromise, spies, requestingMemberId, 'test-locus-url', roles);
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('should handle an empty roles array correctly', async () => {
|
|
725
|
+
const requestingMemberId = 'test-member-id';
|
|
726
|
+
const roles = [];
|
|
727
|
+
const { members, spies } = setup('test-locus-url');
|
|
728
|
+
|
|
729
|
+
const resultPromise = members.lowerAllHands(requestingMemberId, roles);
|
|
730
|
+
|
|
731
|
+
await checkValid(resultPromise, spies, requestingMemberId, 'test-locus-url', roles);
|
|
732
|
+
});
|
|
710
733
|
});
|
|
711
734
|
|
|
712
735
|
describe('#editDisplayName', () => {
|
|
@@ -225,7 +225,7 @@ describe('plugin-meetings', () => {
|
|
|
225
225
|
});
|
|
226
226
|
|
|
227
227
|
describe('#assignRolesMember', () => {
|
|
228
|
-
it('sends a PATCH to the locus endpoint', async () => {
|
|
228
|
+
it('sends a assignRolesMember PATCH to the locus endpoint', async () => {
|
|
229
229
|
const locusUrl = url1;
|
|
230
230
|
const memberId = 'test1';
|
|
231
231
|
const roles = [
|
|
@@ -255,7 +255,7 @@ describe('plugin-meetings', () => {
|
|
|
255
255
|
});
|
|
256
256
|
|
|
257
257
|
describe('#raiseHand', () => {
|
|
258
|
-
it('sends a PATCH to the locus endpoint', async () => {
|
|
258
|
+
it('sends a raiseOrLowerHandMember PATCH to the locus endpoint', async () => {
|
|
259
259
|
const locusUrl = url1;
|
|
260
260
|
const memberId = 'test1';
|
|
261
261
|
|
|
@@ -319,7 +319,7 @@ describe('plugin-meetings', () => {
|
|
|
319
319
|
assert.strictEqual(result, requestResponse);
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
it('sends a PATCH to the locus endpoint', async () => {
|
|
322
|
+
it('sends a lowerAllHandsMember PATCH to the locus endpoint', async () => {
|
|
323
323
|
const locusUrl = url1;
|
|
324
324
|
const memberId = 'test1';
|
|
325
325
|
|
|
@@ -348,6 +348,40 @@ describe('plugin-meetings', () => {
|
|
|
348
348
|
},
|
|
349
349
|
});
|
|
350
350
|
});
|
|
351
|
+
|
|
352
|
+
it('sends a lowerAllHandsMember PATCH to the locus endpoint with roles', async () => {
|
|
353
|
+
const locusUrl = url1;
|
|
354
|
+
const memberId = 'test1';
|
|
355
|
+
const roles = ['attendee'];
|
|
356
|
+
|
|
357
|
+
const options = {
|
|
358
|
+
requestingParticipantId: memberId,
|
|
359
|
+
locusUrl,
|
|
360
|
+
roles,
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const getRequestParamsSpy = sandbox.spy(membersUtil, 'getLowerAllHandsMemberRequestParams');
|
|
364
|
+
|
|
365
|
+
await membersRequest.lowerAllHandsMember(options);
|
|
366
|
+
|
|
367
|
+
assert.calledOnceWithExactly(getRequestParamsSpy, {
|
|
368
|
+
requestingParticipantId: memberId,
|
|
369
|
+
locusUrl: url1,
|
|
370
|
+
roles: ['attendee'],
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
checkRequest({
|
|
374
|
+
method: 'PATCH',
|
|
375
|
+
uri: `${locusUrl}/controls`,
|
|
376
|
+
body: {
|
|
377
|
+
hand: {
|
|
378
|
+
raised: false,
|
|
379
|
+
roles: ['attendee'],
|
|
380
|
+
},
|
|
381
|
+
requestingParticipantId: memberId,
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
});
|
|
351
385
|
});
|
|
352
386
|
|
|
353
387
|
describe('#editDisplayName', () => {
|
|
@@ -101,7 +101,7 @@ describe('plugin-meetings', () => {
|
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
describe('#generateLowerAllHandsMemberOptions', () => {
|
|
104
|
-
it('returns the correct options', () => {
|
|
104
|
+
it('returns the correct options without roles', () => {
|
|
105
105
|
const requestingParticipantId = 'test';
|
|
106
106
|
const locusUrl = 'urlTest1';
|
|
107
107
|
|
|
@@ -113,6 +113,20 @@ describe('plugin-meetings', () => {
|
|
|
113
113
|
}
|
|
114
114
|
);
|
|
115
115
|
});
|
|
116
|
+
it('returns the correct options with roles', () => {
|
|
117
|
+
const requestingParticipantId = 'test';
|
|
118
|
+
const locusUrl = 'urlTest1';
|
|
119
|
+
const roles = ['panelist'];
|
|
120
|
+
|
|
121
|
+
assert.deepEqual(
|
|
122
|
+
MembersUtil.generateLowerAllHandsMemberOptions(requestingParticipantId, locusUrl, roles),
|
|
123
|
+
{
|
|
124
|
+
requestingParticipantId,
|
|
125
|
+
locusUrl,
|
|
126
|
+
roles,
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
});
|
|
116
130
|
});
|
|
117
131
|
describe('#generateEditDisplayNameMemberOptions', () => {
|
|
118
132
|
it('returns the correct options', () => {
|
|
@@ -248,5 +262,100 @@ describe('plugin-meetings', () => {
|
|
|
248
262
|
testParams(false);
|
|
249
263
|
});
|
|
250
264
|
});
|
|
265
|
+
|
|
266
|
+
describe('#getAddMemberBody', () => {
|
|
267
|
+
it('returns the correct body with email address and roles', () => {
|
|
268
|
+
const options = {
|
|
269
|
+
invitee: {
|
|
270
|
+
emailAddress: 'test@example.com',
|
|
271
|
+
roles: ['role1', 'role2'],
|
|
272
|
+
},
|
|
273
|
+
alertIfActive: true,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
277
|
+
invitees: [
|
|
278
|
+
{
|
|
279
|
+
address: 'test@example.com',
|
|
280
|
+
roles: ['role1', 'role2'],
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
alertIfActive: true,
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('returns the correct body with phone number and no roles', () => {
|
|
288
|
+
const options = {
|
|
289
|
+
invitee: {
|
|
290
|
+
phoneNumber: '1234567890',
|
|
291
|
+
},
|
|
292
|
+
alertIfActive: false,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
296
|
+
invitees: [
|
|
297
|
+
{
|
|
298
|
+
address: '1234567890',
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
alertIfActive: false,
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('returns the correct body with fallback to email', () => {
|
|
306
|
+
const options = {
|
|
307
|
+
invitee: {
|
|
308
|
+
email: 'fallback@example.com',
|
|
309
|
+
},
|
|
310
|
+
alertIfActive: true,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
314
|
+
invitees: [
|
|
315
|
+
{
|
|
316
|
+
address: 'fallback@example.com',
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
alertIfActive: true,
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('handles missing `alertIfActive` gracefully', () => {
|
|
324
|
+
const options = {
|
|
325
|
+
invitee: {
|
|
326
|
+
emailAddress: 'test@example.com',
|
|
327
|
+
roles: ['role1'],
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
332
|
+
invitees: [
|
|
333
|
+
{
|
|
334
|
+
address: 'test@example.com',
|
|
335
|
+
roles: ['role1'],
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
alertIfActive: undefined,
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('ignores roles if not provided', () => {
|
|
343
|
+
const options = {
|
|
344
|
+
invitee: {
|
|
345
|
+
emailAddress: 'test@example.com',
|
|
346
|
+
},
|
|
347
|
+
alertIfActive: false,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
351
|
+
invitees: [
|
|
352
|
+
{
|
|
353
|
+
address: 'test@example.com',
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
alertIfActive: false,
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
});
|
|
251
360
|
});
|
|
252
361
|
});
|
|
@@ -249,14 +249,18 @@ describe('RemoteMedia', () => {
|
|
|
249
249
|
|
|
250
250
|
forEach(
|
|
251
251
|
[
|
|
252
|
-
{height:
|
|
253
|
-
{height:
|
|
254
|
-
{height:
|
|
255
|
-
{height:
|
|
256
|
-
{height:
|
|
257
|
-
{height:
|
|
252
|
+
{height: 90, fs: 60}, // 90p
|
|
253
|
+
{height: 98, fs: 60},
|
|
254
|
+
{height: 99, fs: 240}, // 180p
|
|
255
|
+
{height: 180, fs: 240},
|
|
256
|
+
{height: 197, fs: 240},
|
|
257
|
+
{height: 198, fs: 920}, // 360p
|
|
258
|
+
{height: 360, fs: 920},
|
|
259
|
+
{height: 395, fs: 920},
|
|
260
|
+
{height: 396, fs: 3600}, // 720p
|
|
258
261
|
{height: 720, fs: 3600},
|
|
259
|
-
{height: 721, fs: 8192},
|
|
262
|
+
{height: 721, fs: 8192}, // 1080p
|
|
263
|
+
{height: 1080, fs: 8192},
|
|
260
264
|
],
|
|
261
265
|
({height, fs}) => {
|
|
262
266
|
it(`sets the max fs to ${fs} correctly when height is ${height}`, () => {
|
|
@@ -15,6 +15,7 @@ describe('ClusterReachability', () => {
|
|
|
15
15
|
let previousRTCPeerConnection;
|
|
16
16
|
let clusterReachability;
|
|
17
17
|
let fakePeerConnection;
|
|
18
|
+
let gatherIceCandidatesSpy;
|
|
18
19
|
|
|
19
20
|
const emittedEvents: Record<Events, (ResultEventData | ClientMediaIpsUpdatedEventData)[]> = {
|
|
20
21
|
[Events.resultReady]: [],
|
|
@@ -44,6 +45,8 @@ describe('ClusterReachability', () => {
|
|
|
44
45
|
xtls: ['stun:xtls1.webex.com', 'stun:xtls2.webex.com:443'],
|
|
45
46
|
});
|
|
46
47
|
|
|
48
|
+
gatherIceCandidatesSpy = sinon.spy(clusterReachability, 'gatherIceCandidates');
|
|
49
|
+
|
|
47
50
|
resetEmittedEvents();
|
|
48
51
|
|
|
49
52
|
clusterReachability.on(Events.resultReady, (data: ResultEventData) => {
|
|
@@ -151,6 +154,10 @@ describe('ClusterReachability', () => {
|
|
|
151
154
|
assert.calledOnceWithExactly(fakePeerConnection.createOffer, {offerToReceiveAudio: true});
|
|
152
155
|
assert.calledOnce(fakePeerConnection.setLocalDescription);
|
|
153
156
|
|
|
157
|
+
// Make sure that gatherIceCandidates is called before setLocalDescription
|
|
158
|
+
// as setLocalDescription triggers the ICE gathering process
|
|
159
|
+
assert.isTrue(gatherIceCandidatesSpy.calledBefore(fakePeerConnection.setLocalDescription));
|
|
160
|
+
|
|
154
161
|
clusterReachability.abort();
|
|
155
162
|
await promise;
|
|
156
163
|
|