@webex/plugin-meetings 3.5.0 → 3.6.0-next.10
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/common/errors/webinar-registration-error.js +50 -0
- package/dist/common/errors/webinar-registration-error.js.map +1 -0
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.js +7 -0
- 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/parser.js +5 -1
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/media/index.js +3 -1
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +3 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +185 -103
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +5 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/util.js +8 -10
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +68 -17
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +102 -27
- 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/remoteMedia.js +4 -0
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/roap/request.js +1 -1
- package/dist/roap/request.js.map +1 -1
- package/dist/types/common/errors/webinar-registration-error.d.ts +14 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/constants.d.ts +8 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +2 -0
- package/dist/types/meeting/index.d.ts +11 -0
- package/dist/types/meeting/muteState.d.ts +2 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +23 -0
- package/dist/types/meetings/index.d.ts +43 -2
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/remoteMedia.d.ts +1 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/common/errors/webinar-registration-error.ts +27 -0
- package/src/config.ts +3 -0
- package/src/constants.ts +7 -0
- package/src/index.ts +2 -0
- package/src/locus-info/parser.ts +8 -1
- package/src/media/index.ts +4 -1
- package/src/meeting/in-meeting-actions.ts +3 -0
- package/src/meeting/index.ts +82 -13
- package/src/meeting/muteState.ts +6 -2
- package/src/meeting/util.ts +27 -31
- package/src/meeting-info/meeting-info-v2.ts +51 -0
- package/src/meetings/index.ts +129 -38
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/remoteMedia.ts +5 -0
- package/src/roap/request.ts +3 -1
- package/test/unit/spec/locus-info/index.js +29 -0
- package/test/unit/spec/media/index.ts +4 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +2 -0
- package/test/unit/spec/meeting/index.js +118 -18
- package/test/unit/spec/meeting/muteState.js +8 -4
- package/test/unit/spec/meeting/utils.js +50 -85
- package/test/unit/spec/meeting-info/meetinginfov2.js +37 -0
- package/test/unit/spec/meetings/index.js +128 -13
- package/test/unit/spec/multistream/remoteMedia.ts +16 -2
- package/dist/networkQualityMonitor/index.js +0 -227
- package/dist/networkQualityMonitor/index.js.map +0 -1
- package/dist/rtcMetrics/constants.js +0 -11
- package/dist/rtcMetrics/constants.js.map +0 -1
- package/dist/rtcMetrics/index.js +0 -197
- package/dist/rtcMetrics/index.js.map +0 -1
- package/dist/types/networkQualityMonitor/index.d.ts +0 -70
- package/dist/types/rtcMetrics/constants.d.ts +0 -4
- package/dist/types/rtcMetrics/index.d.ts +0 -71
- package/src/rtcMetrics/constants.ts +0 -3
- package/src/rtcMetrics/index.ts +0 -186
- package/test/unit/spec/rtcMetrics/index.ts +0 -154
|
@@ -5,7 +5,6 @@ import 'jsdom-global/register';
|
|
|
5
5
|
import {cloneDeep, forEach, isEqual, isUndefined} from 'lodash';
|
|
6
6
|
import sinon from 'sinon';
|
|
7
7
|
import * as InternalMediaCoreModule from '@webex/internal-media-core';
|
|
8
|
-
import * as RtcMetricsModule from '@webex/plugin-meetings/src/rtcMetrics';
|
|
9
8
|
import * as RemoteMediaManagerModule from '@webex/plugin-meetings/src/multistream/remoteMediaManager';
|
|
10
9
|
import StateMachine from 'javascript-state-machine';
|
|
11
10
|
import uuid from 'uuid';
|
|
@@ -91,13 +90,15 @@ import WebExMeetingsErrors from '../../../../src/common/errors/webex-meetings-er
|
|
|
91
90
|
import ParameterError from '../../../../src/common/errors/parameter';
|
|
92
91
|
import PasswordError from '../../../../src/common/errors/password-error';
|
|
93
92
|
import CaptchaError from '../../../../src/common/errors/captcha-error';
|
|
94
|
-
import PermissionError
|
|
93
|
+
import PermissionError from '../../../../src/common/errors/permission';
|
|
94
|
+
import WebinarRegistrationError from '../../../../src/common/errors/webinar-registration-error';
|
|
95
95
|
import IntentToJoinError from '../../../../src/common/errors/intent-to-join';
|
|
96
96
|
import testUtils from '../../../utils/testUtils';
|
|
97
97
|
import {
|
|
98
98
|
MeetingInfoV2CaptchaError,
|
|
99
99
|
MeetingInfoV2PasswordError,
|
|
100
100
|
MeetingInfoV2PolicyError,
|
|
101
|
+
MeetingInfoV2WebinarRegistrationError,
|
|
101
102
|
} from '../../../../src/meeting-info/meeting-info-v2';
|
|
102
103
|
import {
|
|
103
104
|
DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
@@ -307,7 +308,7 @@ describe('plugin-meetings', () => {
|
|
|
307
308
|
assert.equal(meeting.resource, uuid2);
|
|
308
309
|
assert.equal(meeting.deviceUrl, uuid3);
|
|
309
310
|
assert.equal(meeting.correlationId, correlationId);
|
|
310
|
-
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
311
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
311
312
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
312
313
|
assert.instanceOf(meeting.members, Members);
|
|
313
314
|
assert.calledOnceWithExactly(
|
|
@@ -376,7 +377,7 @@ describe('plugin-meetings', () => {
|
|
|
376
377
|
}
|
|
377
378
|
);
|
|
378
379
|
assert.equal(newMeeting.correlationId, newMeeting.id);
|
|
379
|
-
assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id});
|
|
380
|
+
assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id, sessionCorrelationId: ''});
|
|
380
381
|
});
|
|
381
382
|
|
|
382
383
|
it('correlationId can be provided in callStateForMetrics', () => {
|
|
@@ -403,6 +404,37 @@ describe('plugin-meetings', () => {
|
|
|
403
404
|
correlationId: uuid4,
|
|
404
405
|
joinTrigger: 'fake-join-trigger',
|
|
405
406
|
loginType: 'fake-login-type',
|
|
407
|
+
sessionCorrelationId: '',
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('sessionCorrelationId can be provided in callStateForMetrics', () => {
|
|
412
|
+
const newMeeting = new Meeting(
|
|
413
|
+
{
|
|
414
|
+
userId: uuid1,
|
|
415
|
+
resource: uuid2,
|
|
416
|
+
deviceUrl: uuid3,
|
|
417
|
+
locus: {url: url1},
|
|
418
|
+
destination: testDestination,
|
|
419
|
+
destinationType: DESTINATION_TYPE.MEETING_ID,
|
|
420
|
+
callStateForMetrics: {
|
|
421
|
+
correlationId: uuid4,
|
|
422
|
+
sessionCorrelationId: uuid1,
|
|
423
|
+
joinTrigger: 'fake-join-trigger',
|
|
424
|
+
loginType: 'fake-login-type',
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
parent: webex,
|
|
429
|
+
}
|
|
430
|
+
);
|
|
431
|
+
assert.exists(newMeeting.sessionCorrelationId);
|
|
432
|
+
assert.equal(newMeeting.sessionCorrelationId, uuid1);
|
|
433
|
+
assert.deepEqual(newMeeting.callStateForMetrics, {
|
|
434
|
+
correlationId: uuid4,
|
|
435
|
+
sessionCorrelationId: uuid1,
|
|
436
|
+
joinTrigger: 'fake-join-trigger',
|
|
437
|
+
loginType: 'fake-login-type',
|
|
406
438
|
});
|
|
407
439
|
});
|
|
408
440
|
|
|
@@ -1611,7 +1643,6 @@ describe('plugin-meetings', () => {
|
|
|
1611
1643
|
|
|
1612
1644
|
assert.calledOnce(MeetingUtil.joinMeeting);
|
|
1613
1645
|
assert.calledOnce(webex.internal.device.meetingStarted);
|
|
1614
|
-
assert.calledOnce(meeting.setLocus);
|
|
1615
1646
|
assert.equal(result, joinMeetingResult);
|
|
1616
1647
|
assert.calledWith(webex.internal.llm.on, 'online', meeting.handleLLMOnline);
|
|
1617
1648
|
});
|
|
@@ -2456,8 +2487,8 @@ describe('plugin-meetings', () => {
|
|
|
2456
2487
|
});
|
|
2457
2488
|
|
|
2458
2489
|
it('should create rtcMetrics and pass them to Media.createMediaConnection()', async () => {
|
|
2459
|
-
const
|
|
2460
|
-
|
|
2490
|
+
const setIntervalOriginal = window.setInterval;
|
|
2491
|
+
window.setInterval = sinon.stub().returns(1);
|
|
2461
2492
|
|
|
2462
2493
|
// setup the minimum mocks required for multistream connection
|
|
2463
2494
|
fakeMediaConnection.createSendSlot = sinon.stub().returns({
|
|
@@ -2478,8 +2509,6 @@ describe('plugin-meetings', () => {
|
|
|
2478
2509
|
mediaSettings: {},
|
|
2479
2510
|
});
|
|
2480
2511
|
|
|
2481
|
-
assert.calledOnceWithExactly(rtcMetricsCtor, webex, meeting.id, meeting.correlationId);
|
|
2482
|
-
|
|
2483
2512
|
// check that rtcMetrics was passed to Media.createMediaConnection
|
|
2484
2513
|
assert.calledOnce(Media.createMediaConnection);
|
|
2485
2514
|
assert.calledWith(
|
|
@@ -2487,10 +2516,10 @@ describe('plugin-meetings', () => {
|
|
|
2487
2516
|
true,
|
|
2488
2517
|
meeting.getMediaConnectionDebugId(),
|
|
2489
2518
|
meeting.id,
|
|
2490
|
-
sinon.match(
|
|
2491
|
-
rtcMetrics: fakeRtcMetrics,
|
|
2492
|
-
})
|
|
2519
|
+
sinon.match.hasNested('rtcMetrics.webex', webex)
|
|
2493
2520
|
);
|
|
2521
|
+
|
|
2522
|
+
window.setInterval = setIntervalOriginal;
|
|
2494
2523
|
});
|
|
2495
2524
|
|
|
2496
2525
|
it('should pass the turn server info to the peer connection', async () => {
|
|
@@ -3677,6 +3706,7 @@ describe('plugin-meetings', () => {
|
|
|
3677
3706
|
credential: 'turn password',
|
|
3678
3707
|
},
|
|
3679
3708
|
],
|
|
3709
|
+
iceCandidatesTimeout: meeting.config.iceCandidatesGatheringTimeout,
|
|
3680
3710
|
skipInactiveTransceivers: false,
|
|
3681
3711
|
requireH264: true,
|
|
3682
3712
|
sdpMunging: {
|
|
@@ -3761,11 +3791,16 @@ describe('plugin-meetings', () => {
|
|
|
3761
3791
|
// that's being tested in these tests)
|
|
3762
3792
|
meeting.webex.meetings.registered = true;
|
|
3763
3793
|
meeting.webex.internal.device.config = {};
|
|
3764
|
-
sinon.stub(MeetingUtil, '
|
|
3794
|
+
sinon.stub(MeetingUtil, 'parseLocusJoin').returns({
|
|
3765
3795
|
id: 'fake locus from mocked join request',
|
|
3766
3796
|
locusUrl: 'fake locus url',
|
|
3767
3797
|
mediaId: 'fake media id',
|
|
3768
|
-
})
|
|
3798
|
+
})
|
|
3799
|
+
sinon.stub(meeting.meetingRequest, 'joinMeeting').resolves({
|
|
3800
|
+
headers: {
|
|
3801
|
+
trackingid: 'fake tracking id',
|
|
3802
|
+
}
|
|
3803
|
+
})
|
|
3769
3804
|
await meeting.join({enableMultistream: isMultistream});
|
|
3770
3805
|
});
|
|
3771
3806
|
|
|
@@ -3958,6 +3993,7 @@ describe('plugin-meetings', () => {
|
|
|
3958
3993
|
assert.notCalled(
|
|
3959
3994
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream
|
|
3960
3995
|
);
|
|
3996
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish microphone stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
3961
3997
|
} else {
|
|
3962
3998
|
assert.calledOnceWithExactly(
|
|
3963
3999
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream,
|
|
@@ -3970,6 +4006,7 @@ describe('plugin-meetings', () => {
|
|
|
3970
4006
|
assert.notCalled(
|
|
3971
4007
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream
|
|
3972
4008
|
);
|
|
4009
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish camera stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
3973
4010
|
} else {
|
|
3974
4011
|
assert.calledOnceWithExactly(
|
|
3975
4012
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream,
|
|
@@ -3982,6 +4019,7 @@ describe('plugin-meetings', () => {
|
|
|
3982
4019
|
assert.notCalled(
|
|
3983
4020
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream
|
|
3984
4021
|
);
|
|
4022
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish screenShare audio stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
3985
4023
|
} else {
|
|
3986
4024
|
assert.calledOnceWithExactly(
|
|
3987
4025
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
|
|
@@ -3994,6 +4032,7 @@ describe('plugin-meetings', () => {
|
|
|
3994
4032
|
assert.notCalled(
|
|
3995
4033
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream
|
|
3996
4034
|
);
|
|
4035
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish screenShare video stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
3997
4036
|
} else {
|
|
3998
4037
|
assert.calledOnceWithExactly(
|
|
3999
4038
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream,
|
|
@@ -6217,6 +6256,22 @@ describe('plugin-meetings', () => {
|
|
|
6217
6256
|
|
|
6218
6257
|
assert.equal(meeting.fetchMeetingInfoTimeoutId, undefined);
|
|
6219
6258
|
});
|
|
6259
|
+
|
|
6260
|
+
it('handles meetingInfoProvider webinar need registration error', async () => {
|
|
6261
|
+
meeting.destination = FAKE_DESTINATION;
|
|
6262
|
+
meeting.destinationType = FAKE_TYPE;
|
|
6263
|
+
meeting.attrs.meetingInfoProvider = {
|
|
6264
|
+
fetchMeetingInfo: sinon
|
|
6265
|
+
.stub()
|
|
6266
|
+
.throws(new MeetingInfoV2WebinarRegistrationError(403021, FAKE_MEETING_INFO, 'a message')),
|
|
6267
|
+
};
|
|
6268
|
+
|
|
6269
|
+
await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), WebinarRegistrationError);
|
|
6270
|
+
|
|
6271
|
+
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6272
|
+
assert.equal(meeting.meetingInfoFailureCode, 403021);
|
|
6273
|
+
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION);
|
|
6274
|
+
});
|
|
6220
6275
|
});
|
|
6221
6276
|
|
|
6222
6277
|
describe('#refreshPermissionToken', () => {
|
|
@@ -6927,33 +6982,36 @@ describe('plugin-meetings', () => {
|
|
|
6927
6982
|
describe('#setCorrelationId', () => {
|
|
6928
6983
|
it('should set the correlationId and return undefined', () => {
|
|
6929
6984
|
assert.equal(meeting.correlationId, correlationId);
|
|
6930
|
-
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
6985
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
6931
6986
|
meeting.setCorrelationId(uuid1);
|
|
6932
6987
|
assert.equal(meeting.correlationId, uuid1);
|
|
6933
|
-
assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1});
|
|
6988
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, sessionCorrelationId: ''});
|
|
6934
6989
|
});
|
|
6935
6990
|
});
|
|
6936
6991
|
|
|
6937
6992
|
describe('#updateCallStateForMetrics', () => {
|
|
6938
6993
|
it('should update the callState, overriding existing values', () => {
|
|
6939
|
-
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
6994
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
6940
6995
|
meeting.updateCallStateForMetrics({
|
|
6941
6996
|
correlationId: uuid1,
|
|
6997
|
+
sessionCorrelationId: uuid3,
|
|
6942
6998
|
joinTrigger: 'jt',
|
|
6943
6999
|
loginType: 'lt',
|
|
6944
7000
|
});
|
|
6945
7001
|
assert.deepEqual(meeting.callStateForMetrics, {
|
|
6946
7002
|
correlationId: uuid1,
|
|
7003
|
+
sessionCorrelationId: uuid3,
|
|
6947
7004
|
joinTrigger: 'jt',
|
|
6948
7005
|
loginType: 'lt',
|
|
6949
7006
|
});
|
|
6950
7007
|
});
|
|
6951
7008
|
|
|
6952
7009
|
it('should update the callState, keeping non-supplied values', () => {
|
|
6953
|
-
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
7010
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
6954
7011
|
meeting.updateCallStateForMetrics({joinTrigger: 'jt', loginType: 'lt'});
|
|
6955
7012
|
assert.deepEqual(meeting.callStateForMetrics, {
|
|
6956
7013
|
correlationId,
|
|
7014
|
+
sessionCorrelationId: '',
|
|
6957
7015
|
joinTrigger: 'jt',
|
|
6958
7016
|
loginType: 'lt',
|
|
6959
7017
|
});
|
|
@@ -9837,6 +9895,11 @@ describe('plugin-meetings', () => {
|
|
|
9837
9895
|
requiredDisplayHints: [],
|
|
9838
9896
|
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
|
9839
9897
|
},
|
|
9898
|
+
{
|
|
9899
|
+
actionName: 'canPollingAndQA',
|
|
9900
|
+
requiredDisplayHints: [],
|
|
9901
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_POLLING_AND_QA],
|
|
9902
|
+
},
|
|
9840
9903
|
],
|
|
9841
9904
|
({
|
|
9842
9905
|
actionName,
|
|
@@ -12137,6 +12200,43 @@ describe('plugin-meetings', () => {
|
|
|
12137
12200
|
await testEmit(false);
|
|
12138
12201
|
});
|
|
12139
12202
|
});
|
|
12203
|
+
|
|
12204
|
+
describe('LOCAL_UNMUTE_REQUIRED locus event', () => {
|
|
12205
|
+
const testEmit = async (unmuteAllowed) => {
|
|
12206
|
+
meeting.audio = {
|
|
12207
|
+
handleServerLocalUnmuteRequired: sinon.stub(),
|
|
12208
|
+
}
|
|
12209
|
+
await meeting.locusInfo.emitScoped(
|
|
12210
|
+
{},
|
|
12211
|
+
LOCUSINFO.EVENTS.LOCAL_UNMUTE_REQUIRED,
|
|
12212
|
+
{
|
|
12213
|
+
unmuteAllowed,
|
|
12214
|
+
}
|
|
12215
|
+
);
|
|
12216
|
+
|
|
12217
|
+
assert.calledWith(
|
|
12218
|
+
TriggerProxy.trigger,
|
|
12219
|
+
sinon.match.instanceOf(Meeting),
|
|
12220
|
+
{
|
|
12221
|
+
file: 'meeting/index',
|
|
12222
|
+
function: 'setUpLocusInfoSelfListener',
|
|
12223
|
+
},
|
|
12224
|
+
EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
|
|
12225
|
+
{
|
|
12226
|
+
payload: {
|
|
12227
|
+
unmuteAllowed,
|
|
12228
|
+
},
|
|
12229
|
+
}
|
|
12230
|
+
);
|
|
12231
|
+
assert.calledOnceWithExactly(meeting.audio.handleServerLocalUnmuteRequired, meeting, unmuteAllowed)
|
|
12232
|
+
};
|
|
12233
|
+
|
|
12234
|
+
[true, false].forEach((unmuteAllowed) => {
|
|
12235
|
+
it(`emits the expected event and calls handleServerLocalUnmuteRequired() when unmuteAllowed=${unmuteAllowed}`, async () => {
|
|
12236
|
+
await testEmit(unmuteAllowed);
|
|
12237
|
+
});
|
|
12238
|
+
});
|
|
12239
|
+
});
|
|
12140
12240
|
});
|
|
12141
12241
|
});
|
|
12142
12242
|
|
|
@@ -151,7 +151,7 @@ describe('plugin-meetings', () => {
|
|
|
151
151
|
meeting.mediaProperties.audioStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
152
152
|
meeting.mediaProperties.audioStream.userMuted = muted;
|
|
153
153
|
});
|
|
154
|
-
audio.handleServerLocalUnmuteRequired(meeting);
|
|
154
|
+
audio.handleServerLocalUnmuteRequired(meeting, true);
|
|
155
155
|
|
|
156
156
|
await testUtils.flushPromises();
|
|
157
157
|
|
|
@@ -161,6 +161,8 @@ describe('plugin-meetings', () => {
|
|
|
161
161
|
false,
|
|
162
162
|
'localUnmuteRequired'
|
|
163
163
|
);
|
|
164
|
+
// and unmuteAllowed was updated
|
|
165
|
+
assert.calledWith(meeting.mediaProperties.audioStream.setUnmuteAllowed, true);
|
|
164
166
|
|
|
165
167
|
// and local unmute was sent to server
|
|
166
168
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
@@ -184,7 +186,7 @@ describe('plugin-meetings', () => {
|
|
|
184
186
|
meeting.mediaProperties.audioStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
185
187
|
meeting.mediaProperties.audioStream.userMuted = muted;
|
|
186
188
|
});
|
|
187
|
-
audio.handleServerLocalUnmuteRequired(meeting);
|
|
189
|
+
audio.handleServerLocalUnmuteRequired(meeting, true);
|
|
188
190
|
|
|
189
191
|
await testUtils.flushPromises();
|
|
190
192
|
|
|
@@ -215,7 +217,7 @@ describe('plugin-meetings', () => {
|
|
|
215
217
|
meeting.mediaProperties.videoStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
216
218
|
meeting.mediaProperties.videoStream.userMuted = muted;
|
|
217
219
|
});
|
|
218
|
-
video.handleServerLocalUnmuteRequired(meeting);
|
|
220
|
+
video.handleServerLocalUnmuteRequired(meeting, true);
|
|
219
221
|
|
|
220
222
|
await testUtils.flushPromises();
|
|
221
223
|
|
|
@@ -225,6 +227,8 @@ describe('plugin-meetings', () => {
|
|
|
225
227
|
false,
|
|
226
228
|
'localUnmuteRequired'
|
|
227
229
|
);
|
|
230
|
+
// and unmuteAllowed was updated
|
|
231
|
+
assert.calledWith(meeting.mediaProperties.videoStream.setUnmuteAllowed, true);
|
|
228
232
|
|
|
229
233
|
// and local unmute was sent to server
|
|
230
234
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
@@ -248,7 +252,7 @@ describe('plugin-meetings', () => {
|
|
|
248
252
|
meeting.mediaProperties.videoStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
249
253
|
meeting.mediaProperties.videoStream.userMuted = muted;
|
|
250
254
|
});
|
|
251
|
-
video.handleServerLocalUnmuteRequired(meeting);
|
|
255
|
+
video.handleServerLocalUnmuteRequired(meeting, true);
|
|
252
256
|
|
|
253
257
|
await testUtils.flushPromises();
|
|
254
258
|
|
|
@@ -378,24 +378,36 @@ describe('plugin-meetings', () => {
|
|
|
378
378
|
});
|
|
379
379
|
|
|
380
380
|
describe('joinMeeting', () => {
|
|
381
|
-
|
|
382
|
-
|
|
381
|
+
const joinMeetingResponse = {
|
|
382
|
+
body: {
|
|
383
|
+
mediaConnections: [],
|
|
384
|
+
locus: {
|
|
385
|
+
url: 'differentLocusUrl',
|
|
386
|
+
self: {
|
|
387
|
+
id: 'selfId',
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
headers: {
|
|
392
|
+
trackingid: 'trackingId',
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
let meeting;
|
|
396
|
+
|
|
397
|
+
beforeEach(() => {
|
|
398
|
+
meeting = {
|
|
383
399
|
meetingJoinUrl: 'meetingJoinUrl',
|
|
384
400
|
locusUrl: 'locusUrl',
|
|
385
401
|
meetingRequest: {
|
|
386
402
|
joinMeeting: sinon.stub().returns(
|
|
387
|
-
Promise.resolve(
|
|
388
|
-
body: {mediaConnections: 'mediaConnections'},
|
|
389
|
-
headers: {
|
|
390
|
-
trackingid: 'trackingId',
|
|
391
|
-
},
|
|
392
|
-
})
|
|
393
|
-
),
|
|
403
|
+
Promise.resolve(joinMeetingResponse)),
|
|
394
404
|
},
|
|
395
405
|
getWebexObject: sinon.stub().returns(webex),
|
|
406
|
+
setLocus: sinon.stub(),
|
|
396
407
|
};
|
|
408
|
+
});
|
|
397
409
|
|
|
398
|
-
|
|
410
|
+
it('#Should call `meetingRequest.joinMeeting', async () => {
|
|
399
411
|
await MeetingUtil.joinMeeting(meeting, {
|
|
400
412
|
reachability: 'reachability',
|
|
401
413
|
roapMessage: 'roapMessage',
|
|
@@ -409,6 +421,10 @@ describe('plugin-meetings', () => {
|
|
|
409
421
|
assert.equal(parameter.reachability, 'reachability');
|
|
410
422
|
assert.equal(parameter.roapMessage, 'roapMessage');
|
|
411
423
|
|
|
424
|
+
assert.calledOnce(meeting.setLocus)
|
|
425
|
+
const setLocusParameter = meeting.setLocus.getCall(0).args[0];
|
|
426
|
+
assert.deepEqual(setLocusParameter, MeetingUtil.parseLocusJoin(joinMeetingResponse))
|
|
427
|
+
|
|
412
428
|
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
413
429
|
name: 'client.locus.join.request',
|
|
414
430
|
options: {meetingId: meeting.id},
|
|
@@ -424,21 +440,12 @@ describe('plugin-meetings', () => {
|
|
|
424
440
|
},
|
|
425
441
|
options: {
|
|
426
442
|
meetingId: meeting.id,
|
|
427
|
-
mediaConnections:
|
|
443
|
+
mediaConnections: [],
|
|
428
444
|
},
|
|
429
445
|
});
|
|
430
|
-
parseLocusJoinSpy.restore();
|
|
431
446
|
});
|
|
432
447
|
|
|
433
448
|
it('#Should call meetingRequest.joinMeeting with breakoutsSupported=true when passed in as true', async () => {
|
|
434
|
-
const meeting = {
|
|
435
|
-
meetingRequest: {
|
|
436
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
437
|
-
},
|
|
438
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
442
449
|
await MeetingUtil.joinMeeting(meeting, {
|
|
443
450
|
breakoutsSupported: true,
|
|
444
451
|
});
|
|
@@ -447,18 +454,9 @@ describe('plugin-meetings', () => {
|
|
|
447
454
|
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
448
455
|
|
|
449
456
|
assert.equal(parameter.breakoutsSupported, true);
|
|
450
|
-
parseLocusJoinSpy.restore();
|
|
451
457
|
});
|
|
452
458
|
|
|
453
459
|
it('#Should call meetingRequest.joinMeeting with liveAnnotationSupported=true when passed in as true', async () => {
|
|
454
|
-
const meeting = {
|
|
455
|
-
meetingRequest: {
|
|
456
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
457
|
-
},
|
|
458
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
462
460
|
await MeetingUtil.joinMeeting(meeting, {
|
|
463
461
|
liveAnnotationSupported: true,
|
|
464
462
|
});
|
|
@@ -467,18 +465,9 @@ describe('plugin-meetings', () => {
|
|
|
467
465
|
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
468
466
|
|
|
469
467
|
assert.equal(parameter.liveAnnotationSupported, true);
|
|
470
|
-
parseLocusJoinSpy.restore();
|
|
471
468
|
});
|
|
472
469
|
|
|
473
470
|
it('#Should call meetingRequest.joinMeeting with locale=en_UK, deviceCapabilities=["TEST"] when they are passed in as those values', async () => {
|
|
474
|
-
const meeting = {
|
|
475
|
-
meetingRequest: {
|
|
476
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
477
|
-
},
|
|
478
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
482
471
|
await MeetingUtil.joinMeeting(meeting, {
|
|
483
472
|
locale: 'en_UK',
|
|
484
473
|
deviceCapabilities: ['TEST'],
|
|
@@ -489,21 +478,10 @@ describe('plugin-meetings', () => {
|
|
|
489
478
|
|
|
490
479
|
assert.equal(parameter.locale, 'en_UK');
|
|
491
480
|
assert.deepEqual(parameter.deviceCapabilities, ['TEST']);
|
|
492
|
-
parseLocusJoinSpy.restore();
|
|
493
481
|
});
|
|
494
482
|
|
|
495
483
|
it('#Should call meetingRequest.joinMeeting with preferTranscoding=false when multistream is enabled', async () => {
|
|
496
|
-
|
|
497
|
-
isMultistream: true,
|
|
498
|
-
meetingJoinUrl: 'meetingJoinUrl',
|
|
499
|
-
locusUrl: 'locusUrl',
|
|
500
|
-
meetingRequest: {
|
|
501
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
502
|
-
},
|
|
503
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
484
|
+
meeting.isMultistream = true;
|
|
507
485
|
await MeetingUtil.joinMeeting(meeting, {});
|
|
508
486
|
|
|
509
487
|
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
@@ -511,40 +489,22 @@ describe('plugin-meetings', () => {
|
|
|
511
489
|
|
|
512
490
|
assert.equal(parameter.inviteeAddress, 'meetingJoinUrl');
|
|
513
491
|
assert.equal(parameter.preferTranscoding, false);
|
|
514
|
-
parseLocusJoinSpy.restore();
|
|
515
492
|
});
|
|
516
493
|
|
|
517
494
|
it('#Should fallback sipUrl if meetingJoinUrl does not exists', async () => {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
locusUrl: 'locusUrl',
|
|
521
|
-
meetingRequest: {
|
|
522
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
523
|
-
},
|
|
524
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
495
|
+
meeting.meetingJoinUrl = undefined;
|
|
496
|
+
meeting.sipUri = 'sipUri';
|
|
528
497
|
await MeetingUtil.joinMeeting(meeting, {});
|
|
529
498
|
|
|
530
499
|
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
531
500
|
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
532
501
|
|
|
533
502
|
assert.equal(parameter.inviteeAddress, 'sipUri');
|
|
534
|
-
parseLocusJoinSpy.restore();
|
|
535
503
|
});
|
|
536
504
|
|
|
537
505
|
it('#Should fallback to meetingNumber if meetingJoinUrl/sipUrl does not exists', async () => {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
locusUrl: 'locusUrl',
|
|
541
|
-
meetingRequest: {
|
|
542
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
543
|
-
},
|
|
544
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
545
|
-
};
|
|
546
|
-
|
|
547
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
506
|
+
meeting.meetingJoinUrl = undefined;
|
|
507
|
+
meeting.meetingNumber = 'meetingNumber';
|
|
548
508
|
await MeetingUtil.joinMeeting(meeting, {});
|
|
549
509
|
|
|
550
510
|
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
@@ -552,28 +512,18 @@ describe('plugin-meetings', () => {
|
|
|
552
512
|
|
|
553
513
|
assert.isUndefined(parameter.inviteeAddress);
|
|
554
514
|
assert.equal(parameter.meetingNumber, 'meetingNumber');
|
|
555
|
-
parseLocusJoinSpy.restore();
|
|
556
515
|
});
|
|
557
516
|
|
|
558
517
|
it('should pass in the locusClusterUrl from meetingInfo', async () => {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
locusClusterUrl: 'locusClusterUrl',
|
|
562
|
-
},
|
|
563
|
-
meetingRequest: {
|
|
564
|
-
joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
|
|
565
|
-
},
|
|
566
|
-
getWebexObject: sinon.stub().returns(webex),
|
|
518
|
+
meeting.meetingInfo = {
|
|
519
|
+
locusClusterUrl: 'locusClusterUrl',
|
|
567
520
|
};
|
|
568
|
-
|
|
569
|
-
const parseLocusJoinSpy = sinon.stub(MeetingUtil, 'parseLocusJoin');
|
|
570
521
|
await MeetingUtil.joinMeeting(meeting, {});
|
|
571
522
|
|
|
572
523
|
assert.calledOnce(meeting.meetingRequest.joinMeeting);
|
|
573
524
|
const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
|
|
574
525
|
|
|
575
526
|
assert.equal(parameter.locusClusterUrl, 'locusClusterUrl');
|
|
576
|
-
parseLocusJoinSpy.restore();
|
|
577
527
|
});
|
|
578
528
|
});
|
|
579
529
|
|
|
@@ -1063,7 +1013,21 @@ describe('plugin-meetings', () => {
|
|
|
1063
1013
|
assert.equal(MeetingUtil.getIpVersion(webex), expectedOutput);
|
|
1064
1014
|
});
|
|
1065
1015
|
|
|
1066
|
-
it(`returns
|
|
1016
|
+
it(`returns ${expectedOutput} when supportsIpV4=${supportsIpV4} and supportsIpV6=${supportsIpV6} for Firefox if config is enabled`, () => {
|
|
1017
|
+
sinon
|
|
1018
|
+
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4')
|
|
1019
|
+
.get(() => supportsIpV4);
|
|
1020
|
+
sinon
|
|
1021
|
+
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6')
|
|
1022
|
+
.get(() => supportsIpV6);
|
|
1023
|
+
|
|
1024
|
+
webex.config.meetings.backendIpv6NativeSupport = true;
|
|
1025
|
+
isBrowserStub.callsFake((name) => name === 'firefox');
|
|
1026
|
+
|
|
1027
|
+
assert.equal(MeetingUtil.getIpVersion(webex), expectedOutput);
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
it(`returns undefined when supportsIpV4=${supportsIpV4} and supportsIpV6=${supportsIpV6}, config disabled and browser is firefox`, () => {
|
|
1067
1031
|
sinon
|
|
1068
1032
|
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4')
|
|
1069
1033
|
.get(() => supportsIpV4);
|
|
@@ -1071,6 +1035,7 @@ describe('plugin-meetings', () => {
|
|
|
1071
1035
|
.stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6')
|
|
1072
1036
|
.get(() => supportsIpV6);
|
|
1073
1037
|
|
|
1038
|
+
webex.config.meetings.backendIpv6NativeSupport = false;
|
|
1074
1039
|
isBrowserStub.callsFake((name) => name === 'firefox');
|
|
1075
1040
|
|
|
1076
1041
|
assert.equal(MeetingUtil.getIpVersion(webex), undefined);
|
|
@@ -18,6 +18,7 @@ import MeetingInfo, {
|
|
|
18
18
|
MeetingInfoV2CaptchaError,
|
|
19
19
|
MeetingInfoV2AdhocMeetingError,
|
|
20
20
|
MeetingInfoV2PolicyError,
|
|
21
|
+
MeetingInfoV2WebinarRegistrationError,
|
|
21
22
|
} from '@webex/plugin-meetings/src/meeting-info/meeting-info-v2';
|
|
22
23
|
import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
|
|
23
24
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
@@ -888,6 +889,42 @@ describe('plugin-meetings', () => {
|
|
|
888
889
|
});
|
|
889
890
|
}
|
|
890
891
|
);
|
|
892
|
+
|
|
893
|
+
forEach(
|
|
894
|
+
[
|
|
895
|
+
{errorCode: 403021},
|
|
896
|
+
{errorCode: 403022},
|
|
897
|
+
{errorCode: 403024},
|
|
898
|
+
],
|
|
899
|
+
({errorCode}) => {
|
|
900
|
+
it(`should throw a MeetingInfoV2WebinarRegistrationError for error code ${errorCode}`, async () => {
|
|
901
|
+
const message = 'a message';
|
|
902
|
+
const meetingInfoData = {meetingInfo: {registrationUrl: 'registrationUrl'}};
|
|
903
|
+
|
|
904
|
+
webex.request = sinon.stub().rejects({
|
|
905
|
+
statusCode: 403,
|
|
906
|
+
body: {message, code: errorCode, data: {meetingInfo: meetingInfoData}},
|
|
907
|
+
});
|
|
908
|
+
try {
|
|
909
|
+
await meetingInfo.createAdhocSpaceMeeting(conversationUrl, installedOrgID);
|
|
910
|
+
assert.fail('createAdhocSpaceMeeting should have thrown, but has not done that');
|
|
911
|
+
} catch (err) {
|
|
912
|
+
assert.instanceOf(err, MeetingInfoV2WebinarRegistrationError);
|
|
913
|
+
assert.deepEqual(err.message, `${message}, code=${errorCode}`);
|
|
914
|
+
assert.equal(err.wbxAppApiCode, errorCode);
|
|
915
|
+
assert.deepEqual(err.meetingInfo, meetingInfoData);
|
|
916
|
+
|
|
917
|
+
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
918
|
+
assert.calledWith(
|
|
919
|
+
Metrics.sendBehavioralMetric,
|
|
920
|
+
BEHAVIORAL_METRICS.WEBINAR_REGISTRATION_ERROR,
|
|
921
|
+
{code: errorCode}
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
}
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
);
|
|
891
928
|
});
|
|
892
929
|
});
|
|
893
930
|
});
|