@webex/plugin-meetings 3.8.1 → 3.9.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/README.md +26 -13
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +32 -3
- 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/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +26 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +11 -3
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +84 -91
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +4 -1
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/media/index.js +2 -2
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/brbState.js +17 -14
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +11 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +484 -287
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +19 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/{rtcMetrics/constants.js → meeting/type.js} +1 -5
- package/dist/meeting/type.js.map +1 -0
- package/dist/meeting/util.js +68 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +35 -33
- package/dist/meetings/index.js.map +1 -1
- package/dist/members/index.js +14 -11
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -3
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +25 -8
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +1 -0
- 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/multistream/remoteMedia.js +34 -5
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +42 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +32 -2
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/index.js +8 -13
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/constants.d.ts +28 -0
- package/dist/types/controls-options-manager/enums.d.ts +2 -1
- package/dist/types/controls-options-manager/types.d.ts +4 -1
- package/dist/types/locus-info/index.d.ts +2 -9
- package/dist/types/meeting/brbState.d.ts +0 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +10 -0
- package/dist/types/meeting/index.d.ts +47 -19
- package/dist/types/meeting/request.d.ts +9 -1
- package/dist/types/meeting/request.type.d.ts +74 -0
- package/dist/types/meeting/type.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +3 -0
- package/dist/types/members/index.d.ts +12 -8
- package/dist/types/members/request.d.ts +1 -1
- package/dist/types/members/util.d.ts +13 -6
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/remoteMedia.d.ts +20 -1
- package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
- package/dist/types/multistream/sendSlotManager.d.ts +16 -0
- package/dist/types/reachability/index.d.ts +2 -2
- package/dist/webinar/index.js +1 -1
- package/package.json +24 -25
- package/src/constants.ts +32 -2
- package/src/controls-options-manager/enums.ts +1 -0
- package/src/controls-options-manager/types.ts +6 -1
- package/src/controls-options-manager/util.ts +31 -0
- package/src/locus-info/controlsUtils.ts +15 -0
- package/src/locus-info/index.ts +103 -92
- package/src/locus-info/parser.ts +5 -1
- package/src/media/index.ts +2 -2
- package/src/meeting/brbState.ts +13 -9
- package/src/meeting/in-meeting-actions.ts +21 -0
- package/src/meeting/index.ts +278 -73
- package/src/meeting/request.ts +16 -0
- package/src/meeting/request.type.ts +64 -0
- package/src/meeting/type.ts +9 -0
- package/src/meeting/util.ts +73 -2
- package/src/meetings/index.ts +3 -2
- package/src/members/index.ts +22 -12
- package/src/members/request.ts +2 -2
- package/src/members/util.ts +34 -6
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +7 -7
- package/src/multistream/remoteMedia.ts +34 -4
- package/src/multistream/remoteMediaGroup.ts +37 -2
- package/src/multistream/sendSlotManager.ts +34 -2
- package/src/reachability/index.ts +8 -16
- package/test/unit/spec/controls-options-manager/util.js +58 -0
- package/test/unit/spec/locus-info/controlsUtils.js +52 -0
- package/test/unit/spec/locus-info/index.js +247 -89
- package/test/unit/spec/locus-info/parser.js +3 -2
- package/test/unit/spec/media/index.ts +107 -0
- package/test/unit/spec/meeting/brbState.ts +23 -4
- package/test/unit/spec/meeting/in-meeting-actions.ts +10 -0
- package/test/unit/spec/meeting/index.js +976 -91
- package/test/unit/spec/meeting/request.js +71 -0
- package/test/unit/spec/meeting/utils.js +122 -1
- package/test/unit/spec/meetings/index.js +2 -0
- package/test/unit/spec/members/index.js +98 -11
- package/test/unit/spec/members/request.js +57 -2
- package/test/unit/spec/members/utils.js +139 -17
- package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
- package/test/unit/spec/multistream/remoteMedia.ts +66 -2
- package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
- package/test/unit/spec/reachability/index.ts +160 -9
- package/dist/annotation/annotation.types.d.ts +0 -42
- package/dist/annotation/constants.d.ts +0 -31
- package/dist/annotation/index.d.ts +0 -117
- package/dist/breakouts/breakout.d.ts +0 -8
- package/dist/breakouts/collection.d.ts +0 -5
- package/dist/breakouts/edit-lock-error.d.ts +0 -15
- package/dist/breakouts/events.d.ts +0 -8
- package/dist/breakouts/index.d.ts +0 -5
- package/dist/breakouts/request.d.ts +0 -22
- package/dist/breakouts/utils.d.ts +0 -15
- package/dist/common/browser-detection.d.ts +0 -9
- package/dist/common/collection.d.ts +0 -48
- package/dist/common/config.d.ts +0 -2
- package/dist/common/errors/captcha-error.d.ts +0 -15
- package/dist/common/errors/intent-to-join.d.ts +0 -16
- package/dist/common/errors/join-meeting.d.ts +0 -17
- package/dist/common/errors/media.d.ts +0 -15
- package/dist/common/errors/no-meeting-info.d.ts +0 -14
- package/dist/common/errors/parameter.d.ts +0 -15
- package/dist/common/errors/password-error.d.ts +0 -15
- package/dist/common/errors/permission.d.ts +0 -14
- package/dist/common/errors/reclaim-host-role-error.d.ts +0 -60
- package/dist/common/errors/reclaim-host-role-error.js +0 -158
- package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
- package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
- package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/common/errors/reconnection-in-progress.js +0 -35
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/common/errors/reconnection.d.ts +0 -15
- package/dist/common/errors/stats.d.ts +0 -15
- package/dist/common/errors/webex-errors.d.ts +0 -81
- package/dist/common/errors/webex-meetings-error.d.ts +0 -20
- package/dist/common/events/events-scope.d.ts +0 -17
- package/dist/common/events/events.d.ts +0 -12
- package/dist/common/events/trigger-proxy.d.ts +0 -2
- package/dist/common/events/util.d.ts +0 -2
- package/dist/common/logs/logger-config.d.ts +0 -2
- package/dist/common/logs/logger-proxy.d.ts +0 -2
- package/dist/common/logs/request.d.ts +0 -34
- package/dist/common/queue.d.ts +0 -32
- package/dist/config.d.ts +0 -73
- package/dist/constants.d.ts +0 -952
- package/dist/controls-options-manager/constants.d.ts +0 -4
- package/dist/controls-options-manager/enums.d.ts +0 -5
- package/dist/controls-options-manager/index.d.ts +0 -120
- package/dist/controls-options-manager/types.d.ts +0 -43
- package/dist/controls-options-manager/util.d.ts +0 -7
- package/dist/index.d.ts +0 -4
- package/dist/interceptors/index.d.ts +0 -2
- package/dist/interceptors/locusRetry.d.ts +0 -27
- package/dist/interpretation/collection.d.ts +0 -5
- package/dist/interpretation/index.d.ts +0 -5
- package/dist/interpretation/siLanguage.d.ts +0 -5
- package/dist/locus-info/controlsUtils.d.ts +0 -2
- package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
- package/dist/locus-info/fullState.d.ts +0 -2
- package/dist/locus-info/hostUtils.d.ts +0 -2
- package/dist/locus-info/index.d.ts +0 -269
- package/dist/locus-info/infoUtils.d.ts +0 -2
- package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
- package/dist/locus-info/parser.d.ts +0 -212
- package/dist/locus-info/selfUtils.d.ts +0 -2
- package/dist/media/index.d.ts +0 -32
- package/dist/media/properties.d.ts +0 -108
- package/dist/media/util.d.ts +0 -2
- package/dist/mediaQualityMetrics/config.d.ts +0 -233
- package/dist/mediaQualityMetrics/config.js +0 -513
- package/dist/mediaQualityMetrics/config.js.map +0 -1
- package/dist/meeting/effectsState.d.ts +0 -42
- package/dist/meeting/effectsState.js +0 -260
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/meeting/in-meeting-actions.d.ts +0 -79
- package/dist/meeting/index.d.ts +0 -1622
- package/dist/meeting/locusMediaRequest.d.ts +0 -74
- package/dist/meeting/muteState.d.ts +0 -116
- package/dist/meeting/request.d.ts +0 -257
- package/dist/meeting/request.type.d.ts +0 -11
- package/dist/meeting/state.d.ts +0 -9
- package/dist/meeting/util.d.ts +0 -2
- package/dist/meeting/voicea-meeting.d.ts +0 -16
- package/dist/meeting-info/collection.d.ts +0 -20
- package/dist/meeting-info/index.d.ts +0 -57
- package/dist/meeting-info/meeting-info-v2.d.ts +0 -93
- package/dist/meeting-info/request.d.ts +0 -22
- package/dist/meeting-info/util.d.ts +0 -2
- package/dist/meeting-info/utilv2.d.ts +0 -2
- package/dist/meetings/collection.d.ts +0 -23
- package/dist/meetings/index.d.ts +0 -296
- package/dist/meetings/meetings.types.d.ts +0 -4
- package/dist/meetings/request.d.ts +0 -27
- package/dist/meetings/util.d.ts +0 -18
- package/dist/member/index.d.ts +0 -148
- package/dist/member/member.types.d.ts +0 -11
- package/dist/member/member.types.js +0 -18
- package/dist/member/member.types.js.map +0 -1
- package/dist/member/types.d.ts +0 -32
- package/dist/member/util.d.ts +0 -2
- package/dist/members/collection.d.ts +0 -24
- package/dist/members/index.d.ts +0 -308
- package/dist/members/request.d.ts +0 -58
- package/dist/members/types.d.ts +0 -25
- package/dist/members/util.d.ts +0 -2
- package/dist/metrics/config.d.ts +0 -169
- package/dist/metrics/config.js +0 -289
- package/dist/metrics/config.js.map +0 -1
- package/dist/metrics/constants.d.ts +0 -59
- package/dist/metrics/index.d.ts +0 -152
- package/dist/multistream/mediaRequestManager.d.ts +0 -119
- package/dist/multistream/receiveSlot.d.ts +0 -68
- package/dist/multistream/receiveSlotManager.d.ts +0 -56
- package/dist/multistream/remoteMedia.d.ts +0 -72
- package/dist/multistream/remoteMediaGroup.d.ts +0 -49
- package/dist/multistream/remoteMediaManager.d.ts +0 -300
- package/dist/multistream/sendSlotManager.d.ts +0 -69
- package/dist/networkQualityMonitor/index.d.ts +0 -70
- package/dist/networkQualityMonitor/index.js +0 -226
- package/dist/networkQualityMonitor/index.js.map +0 -1
- package/dist/peer-connection-manager/index.d.ts +0 -6
- package/dist/peer-connection-manager/index.js +0 -671
- package/dist/peer-connection-manager/index.js.map +0 -1
- package/dist/peer-connection-manager/util.d.ts +0 -6
- package/dist/peer-connection-manager/util.js +0 -110
- package/dist/peer-connection-manager/util.js.map +0 -1
- package/dist/personal-meeting-room/index.d.ts +0 -47
- package/dist/personal-meeting-room/request.d.ts +0 -14
- package/dist/personal-meeting-room/util.d.ts +0 -2
- package/dist/reachability/clusterReachability.d.ts +0 -109
- package/dist/reachability/index.d.ts +0 -139
- package/dist/reachability/request.d.ts +0 -35
- package/dist/reachability/util.d.ts +0 -8
- package/dist/reactions/constants.d.ts +0 -3
- package/dist/reactions/reactions.d.ts +0 -4
- package/dist/reactions/reactions.type.d.ts +0 -32
- package/dist/reconnection-manager/index.d.ts +0 -112
- package/dist/recording-controller/enums.d.ts +0 -7
- package/dist/recording-controller/index.d.ts +0 -193
- package/dist/recording-controller/util.d.ts +0 -13
- package/dist/roap/collection.d.ts +0 -10
- package/dist/roap/collection.js +0 -63
- package/dist/roap/collection.js.map +0 -1
- package/dist/roap/handler.d.ts +0 -47
- package/dist/roap/handler.js +0 -279
- package/dist/roap/handler.js.map +0 -1
- package/dist/roap/index.d.ts +0 -116
- package/dist/roap/request.d.ts +0 -35
- package/dist/roap/state.d.ts +0 -9
- package/dist/roap/state.js +0 -127
- package/dist/roap/state.js.map +0 -1
- package/dist/roap/turnDiscovery.d.ts +0 -81
- package/dist/roap/util.d.ts +0 -2
- package/dist/roap/util.js +0 -76
- package/dist/roap/util.js.map +0 -1
- package/dist/rtcMetrics/constants.d.ts +0 -4
- package/dist/rtcMetrics/constants.js.map +0 -1
- package/dist/rtcMetrics/index.d.ts +0 -61
- package/dist/rtcMetrics/index.js +0 -197
- package/dist/rtcMetrics/index.js.map +0 -1
- package/dist/statsAnalyzer/global.d.ts +0 -118
- package/dist/statsAnalyzer/global.js +0 -127
- package/dist/statsAnalyzer/global.js.map +0 -1
- package/dist/statsAnalyzer/index.d.ts +0 -193
- package/dist/statsAnalyzer/index.js +0 -1019
- package/dist/statsAnalyzer/index.js.map +0 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +0 -22
- package/dist/statsAnalyzer/mqaUtil.js +0 -181
- package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
- package/dist/transcription/index.d.ts +0 -64
- package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
- 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/dist/types/statsAnalyzer/global.d.ts +0 -36
- package/dist/types/statsAnalyzer/index.d.ts +0 -217
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
- package/dist/webinar/collection.d.ts +0 -16
- package/dist/webinar/index.d.ts +0 -5
@@ -56,6 +56,7 @@ import * as MeetingRequestImport from '@webex/plugin-meetings/src/meeting/reques
|
|
56
56
|
import LocusInfo from '@webex/plugin-meetings/src/locus-info';
|
57
57
|
import MediaProperties from '@webex/plugin-meetings/src/media/properties';
|
58
58
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
59
|
+
import MembersUtil from '@webex/plugin-meetings/src/members/util';
|
59
60
|
import MeetingsUtil from '@webex/plugin-meetings/src/meetings/util';
|
60
61
|
import Media from '@webex/plugin-meetings/src/media/index';
|
61
62
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
@@ -244,6 +245,7 @@ describe('plugin-meetings', () => {
|
|
244
245
|
});
|
245
246
|
|
246
247
|
webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache = sinon.stub();
|
248
|
+
webex.internal.newMetrics.callDiagnosticMetrics.clearEventLimitsForCorrelationId = sinon.stub();
|
247
249
|
webex.internal.support.submitLogs = sinon.stub().returns(Promise.resolve());
|
248
250
|
webex.internal.services = {get: sinon.stub().returns('locus-url')};
|
249
251
|
webex.credentials.getOrgId = sinon.stub().returns('fake-org-id');
|
@@ -368,6 +370,35 @@ describe('plugin-meetings', () => {
|
|
368
370
|
assert.instanceOf(meeting.simultaneousInterpretation, SimultaneousInterpretation);
|
369
371
|
assert.instanceOf(meeting.webinar, Webinar);
|
370
372
|
});
|
373
|
+
|
374
|
+
it('should call the callback with the meeting that has id already set', () => {
|
375
|
+
let meetingIdFromCallback;
|
376
|
+
// check that the meeting id is already set correctly at the time when the callback is called
|
377
|
+
const meetingCreationCallback = sinon.stub().callsFake((meeting) => {
|
378
|
+
meetingIdFromCallback = meeting.id;
|
379
|
+
});
|
380
|
+
|
381
|
+
meeting = new Meeting(
|
382
|
+
{
|
383
|
+
userId: uuid1,
|
384
|
+
resource: uuid2,
|
385
|
+
deviceUrl: uuid3,
|
386
|
+
locus: {url: url1},
|
387
|
+
destination: testDestination,
|
388
|
+
destinationType: DESTINATION_TYPE.MEETING_ID,
|
389
|
+
correlationId,
|
390
|
+
selfId: uuid1,
|
391
|
+
},
|
392
|
+
{
|
393
|
+
parent: webex,
|
394
|
+
},
|
395
|
+
meetingCreationCallback
|
396
|
+
);
|
397
|
+
assert.exists(meeting.id);
|
398
|
+
assert.calledOnceWithExactly(meetingCreationCallback, meeting);
|
399
|
+
assert.equal(meeting.id, meetingIdFromCallback);
|
400
|
+
});
|
401
|
+
|
371
402
|
it('creates MediaRequestManager instances', () => {
|
372
403
|
assert.instanceOf(meeting.mediaRequestManagers.audio, MediaRequestManager);
|
373
404
|
assert.instanceOf(meeting.mediaRequestManagers.video, MediaRequestManager);
|
@@ -454,6 +485,18 @@ describe('plugin-meetings', () => {
|
|
454
485
|
});
|
455
486
|
});
|
456
487
|
|
488
|
+
it('pstnCorrelationId getter/setter should work correctly', () => {
|
489
|
+
const testPstnCorrelationId = uuid.v4();
|
490
|
+
|
491
|
+
meeting.pstnCorrelationId = testPstnCorrelationId;
|
492
|
+
assert.equal(meeting.pstnCorrelationId, testPstnCorrelationId);
|
493
|
+
assert.equal(meeting.callStateForMetrics.pstnCorrelationId, testPstnCorrelationId);
|
494
|
+
|
495
|
+
meeting.pstnCorrelationId = undefined;
|
496
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
497
|
+
assert.equal(meeting.callStateForMetrics.pstnCorrelationId, undefined);
|
498
|
+
});
|
499
|
+
|
457
500
|
describe('creates ReceiveSlot manager instance', () => {
|
458
501
|
let mockReceiveSlotManagerCtor;
|
459
502
|
let providedCreateSlotCallback;
|
@@ -581,7 +624,6 @@ describe('plugin-meetings', () => {
|
|
581
624
|
assert.isFalse(meeting.isLocusCall());
|
582
625
|
});
|
583
626
|
});
|
584
|
-
|
585
627
|
describe('#invite', () => {
|
586
628
|
it('should have #invite', () => {
|
587
629
|
assert.exists(meeting.invite);
|
@@ -592,8 +634,6 @@ describe('plugin-meetings', () => {
|
|
592
634
|
it('should proxy members #addMember and return a promise', async () => {
|
593
635
|
const invite = meeting.invite(uuid1, false);
|
594
636
|
|
595
|
-
assert.exists(invite.then);
|
596
|
-
await invite;
|
597
637
|
assert.calledOnce(meeting.members.addMember);
|
598
638
|
assert.calledWith(meeting.members.addMember, uuid1, false);
|
599
639
|
});
|
@@ -614,20 +654,20 @@ describe('plugin-meetings', () => {
|
|
614
654
|
assert.calledWith(meeting.members.cancelPhoneInvite, uuid1);
|
615
655
|
});
|
616
656
|
});
|
617
|
-
describe('#
|
618
|
-
it('should have #
|
619
|
-
assert.exists(meeting.
|
657
|
+
describe('#cancelInviteByMemberId', () => {
|
658
|
+
it('should have #cancelInviteByMemberId', () => {
|
659
|
+
assert.exists(meeting.cancelInviteByMemberId);
|
620
660
|
});
|
621
661
|
beforeEach(() => {
|
622
|
-
meeting.members.
|
662
|
+
meeting.members.cancelInviteByMemberId = sinon.stub().returns(Promise.resolve(test1));
|
623
663
|
});
|
624
|
-
it('should proxy members #
|
625
|
-
const cancel = meeting.
|
664
|
+
it('should proxy members #cancelInviteByMemberId and return a promise', async () => {
|
665
|
+
const cancel = meeting.cancelInviteByMemberId({memberId: uuid1});
|
626
666
|
|
627
667
|
assert.exists(cancel.then);
|
628
668
|
await cancel;
|
629
|
-
assert.calledOnce(meeting.members.
|
630
|
-
assert.calledWith(meeting.members.
|
669
|
+
assert.calledOnce(meeting.members.cancelInviteByMemberId);
|
670
|
+
assert.calledWith(meeting.members.cancelInviteByMemberId, {memberId: uuid1});
|
631
671
|
});
|
632
672
|
});
|
633
673
|
describe('#admit', () => {
|
@@ -1208,8 +1248,73 @@ describe('plugin-meetings', () => {
|
|
1208
1248
|
reason: 'joinWithMedia failure',
|
1209
1249
|
});
|
1210
1250
|
});
|
1211
|
-
});
|
1212
1251
|
|
1252
|
+
it('should ignore sendVideo/receiveVideo when videoEnabled is false', async () => {
|
1253
|
+
await meeting.joinWithMedia({
|
1254
|
+
joinOptions,
|
1255
|
+
mediaOptions: {
|
1256
|
+
videoEnabled: false,
|
1257
|
+
sendVideo: true,
|
1258
|
+
receiveVideo: true,
|
1259
|
+
allowMediaInLobby: true,
|
1260
|
+
},
|
1261
|
+
});
|
1262
|
+
|
1263
|
+
assert.calledWithMatch(
|
1264
|
+
meeting.addMediaInternal,
|
1265
|
+
sinon.match.any,
|
1266
|
+
sinon.match.any,
|
1267
|
+
sinon.match.any,
|
1268
|
+
sinon.match.has('videoEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
|
1269
|
+
);
|
1270
|
+
});
|
1271
|
+
|
1272
|
+
it('should ignore sendAudio/receiveAudio when audioEnabled is false', async () => {
|
1273
|
+
await meeting.joinWithMedia({
|
1274
|
+
joinOptions,
|
1275
|
+
mediaOptions: {
|
1276
|
+
audioEnabled: false,
|
1277
|
+
sendAudio: true,
|
1278
|
+
receiveAudio: false,
|
1279
|
+
allowMediaInLobby: true,
|
1280
|
+
},
|
1281
|
+
});
|
1282
|
+
|
1283
|
+
assert.calledWithMatch(
|
1284
|
+
meeting.addMediaInternal,
|
1285
|
+
sinon.match.any,
|
1286
|
+
sinon.match.any,
|
1287
|
+
sinon.match.any,
|
1288
|
+
sinon.match.has('audioEnabled', false).and(sinon.match.has('allowMediaInLobby', true))
|
1289
|
+
);
|
1290
|
+
});
|
1291
|
+
|
1292
|
+
it('should use provided send/receive values when videoEnabled/audioEnabled are true or not set', async () => {
|
1293
|
+
await meeting.joinWithMedia({
|
1294
|
+
joinOptions,
|
1295
|
+
mediaOptions: {
|
1296
|
+
sendVideo: true,
|
1297
|
+
receiveVideo: false,
|
1298
|
+
sendAudio: false,
|
1299
|
+
receiveAudio: true,
|
1300
|
+
allowMediaInLobby: true,
|
1301
|
+
},
|
1302
|
+
});
|
1303
|
+
|
1304
|
+
assert.calledWith(
|
1305
|
+
meeting.addMediaInternal,
|
1306
|
+
sinon.match.any,
|
1307
|
+
sinon.match.any,
|
1308
|
+
sinon.match.any,
|
1309
|
+
sinon.match({
|
1310
|
+
sendVideo: true,
|
1311
|
+
receiveVideo: false,
|
1312
|
+
sendAudio: false,
|
1313
|
+
receiveAudio: true,
|
1314
|
+
})
|
1315
|
+
);
|
1316
|
+
});
|
1317
|
+
});
|
1213
1318
|
describe('#isTranscriptionSupported', () => {
|
1214
1319
|
it('should return false if the feature is not supported for the meeting', () => {
|
1215
1320
|
meeting.locusInfo.controls = {transcribe: {caption: false}};
|
@@ -1223,6 +1328,44 @@ describe('plugin-meetings', () => {
|
|
1223
1328
|
});
|
1224
1329
|
});
|
1225
1330
|
|
1331
|
+
describe('#update spoken language', () => {
|
1332
|
+
beforeEach(() => {
|
1333
|
+
webex.internal.voicea.onSpokenLanguageUpdate = sinon.stub();
|
1334
|
+
meeting.transcription = {languageOptions: {currentSpokenLanguage: 'en'}};
|
1335
|
+
});
|
1336
|
+
afterEach(() => {
|
1337
|
+
// Restore the original methods after each test
|
1338
|
+
sinon.restore();
|
1339
|
+
});
|
1340
|
+
it('should call voicea.onSpokenLanguageUpdate when joined', async () => {
|
1341
|
+
meeting.joinedWith = {state: 'JOINED'};
|
1342
|
+
await meeting.locusInfo.emitScoped(
|
1343
|
+
{function: 'test', file: 'test'},
|
1344
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
1345
|
+
{spokenLanguage: 'fr'}
|
1346
|
+
);
|
1347
|
+
assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'fr', meeting.id);
|
1348
|
+
assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'fr');
|
1349
|
+
assert.calledWith(
|
1350
|
+
TriggerProxy.trigger,
|
1351
|
+
meeting,
|
1352
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
1353
|
+
EVENT_TRIGGERS.MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED
|
1354
|
+
);
|
1355
|
+
});
|
1356
|
+
|
1357
|
+
it('should also call voicea.onSpokenLanguageUpdate when not joined', async () => {
|
1358
|
+
meeting.joinedWith = {state: 'NOT_JOINED'};
|
1359
|
+
await meeting.locusInfo.emitScoped(
|
1360
|
+
{function: 'test', file: 'test'},
|
1361
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
|
1362
|
+
{spokenLanguage: 'de'}
|
1363
|
+
);
|
1364
|
+
assert.calledWith(webex.internal.voicea.onSpokenLanguageUpdate, 'de');
|
1365
|
+
assert.equal(meeting.transcription.languageOptions.currentSpokenLanguage, 'de');
|
1366
|
+
});
|
1367
|
+
});
|
1368
|
+
|
1226
1369
|
describe('#startTranscription', () => {
|
1227
1370
|
beforeEach(() => {
|
1228
1371
|
webex.internal.voicea.on = sinon.stub();
|
@@ -1846,21 +1989,25 @@ describe('plugin-meetings', () => {
|
|
1846
1989
|
});
|
1847
1990
|
});
|
1848
1991
|
|
1849
|
-
it('should
|
1992
|
+
it('should handle join failure', async () => {
|
1850
1993
|
MeetingUtil.isPinOrGuest = sinon.stub().returns(false);
|
1994
|
+
webex.internal.newMetrics.submitClientEvent = sinon.stub();
|
1995
|
+
|
1851
1996
|
await meeting.join().catch(() => {
|
1852
|
-
assert.
|
1853
|
-
|
1854
|
-
|
1855
|
-
);
|
1856
|
-
assert.
|
1857
|
-
webex.internal.newMetrics.submitClientEvent
|
1997
|
+
assert.calledOnce(MeetingUtil.joinMeeting);
|
1998
|
+
|
1999
|
+
// Assert that client.locus.join.response error event is not sent from this function, it is now emitted from MeetingUtil.joinMeeting
|
2000
|
+
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
2001
|
+
assert.calledWithMatch(
|
2002
|
+
webex.internal.newMetrics.submitClientEvent,
|
1858
2003
|
{
|
1859
|
-
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
2004
|
+
name: 'client.call.initiated',
|
2005
|
+
payload: {
|
2006
|
+
trigger: 'user-interaction',
|
2007
|
+
isRoapCallEnabled: true,
|
2008
|
+
pstnAudioType: undefined
|
2009
|
+
},
|
2010
|
+
options: {meetingId: meeting.id},
|
1864
2011
|
}
|
1865
2012
|
);
|
1866
2013
|
});
|
@@ -2061,16 +2208,15 @@ describe('plugin-meetings', () => {
|
|
2061
2208
|
};
|
2062
2209
|
meeting.mediaProperties.setMediaDirection = sinon.stub().returns(true);
|
2063
2210
|
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
2064
|
-
meeting.mediaProperties.getCurrentConnectionInfo = sinon
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
ipVersion: 'IPv6',
|
2071
|
-
});
|
2211
|
+
meeting.mediaProperties.getCurrentConnectionInfo = sinon.stub().resolves({
|
2212
|
+
connectionType: 'udp',
|
2213
|
+
selectedCandidatePairChanges: 2,
|
2214
|
+
numTransports: 1,
|
2215
|
+
ipVersion: 'IPv6',
|
2216
|
+
});
|
2072
2217
|
meeting.audio = muteStateStub;
|
2073
2218
|
meeting.video = muteStateStub;
|
2219
|
+
sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.ipv4_and_ipv6);
|
2074
2220
|
sinon.stub(Media, 'createMediaConnection').returns(fakeMediaConnection);
|
2075
2221
|
sinon.stub(meeting, 'setupMediaConnectionListeners');
|
2076
2222
|
sinon.stub(meeting, 'setMercuryListener');
|
@@ -2187,10 +2333,12 @@ describe('plugin-meetings', () => {
|
|
2187
2333
|
someReachabilityMetric1: 'some value1',
|
2188
2334
|
someReachabilityMetric2: 'some value2',
|
2189
2335
|
selectedCandidatePairChanges: 2,
|
2190
|
-
|
2191
|
-
|
2336
|
+
subnet_reachable: null,
|
2337
|
+
selected_cluster: null,
|
2338
|
+
selected_subnet: null,
|
2192
2339
|
numTransports: 1,
|
2193
2340
|
iceCandidatesCount: 0,
|
2341
|
+
ipver: 1,
|
2194
2342
|
}
|
2195
2343
|
);
|
2196
2344
|
});
|
@@ -2235,8 +2383,10 @@ describe('plugin-meetings', () => {
|
|
2235
2383
|
signalingState: 'unknown',
|
2236
2384
|
connectionState: 'unknown',
|
2237
2385
|
iceConnectionState: 'unknown',
|
2238
|
-
|
2239
|
-
|
2386
|
+
subnet_reachable: null,
|
2387
|
+
selected_cluster: null,
|
2388
|
+
selected_subnet: null,
|
2389
|
+
ipver: 1,
|
2240
2390
|
})
|
2241
2391
|
);
|
2242
2392
|
|
@@ -2302,8 +2452,10 @@ describe('plugin-meetings', () => {
|
|
2302
2452
|
selectedCandidatePairChanges: 2,
|
2303
2453
|
numTransports: 1,
|
2304
2454
|
iceCandidatesCount: 0,
|
2305
|
-
|
2306
|
-
|
2455
|
+
subnet_reachable: null,
|
2456
|
+
selected_cluster: null,
|
2457
|
+
selected_subnet: null,
|
2458
|
+
ipver: 1,
|
2307
2459
|
}
|
2308
2460
|
);
|
2309
2461
|
});
|
@@ -2361,8 +2513,10 @@ describe('plugin-meetings', () => {
|
|
2361
2513
|
signalingState: 'have-local-offer',
|
2362
2514
|
connectionState: 'connecting',
|
2363
2515
|
iceConnectionState: 'checking',
|
2364
|
-
|
2365
|
-
|
2516
|
+
subnet_reachable: null,
|
2517
|
+
selected_cluster: null,
|
2518
|
+
selected_subnet: null,
|
2519
|
+
ipver: 1,
|
2366
2520
|
})
|
2367
2521
|
);
|
2368
2522
|
|
@@ -2420,8 +2574,10 @@ describe('plugin-meetings', () => {
|
|
2420
2574
|
signalingState: 'have-local-offer',
|
2421
2575
|
connectionState: 'connecting',
|
2422
2576
|
iceConnectionState: 'checking',
|
2423
|
-
|
2424
|
-
|
2577
|
+
subnet_reachable: null,
|
2578
|
+
selected_cluster: null,
|
2579
|
+
selected_subnet: null,
|
2580
|
+
ipver: 1,
|
2425
2581
|
})
|
2426
2582
|
);
|
2427
2583
|
|
@@ -2943,8 +3099,10 @@ describe('plugin-meetings', () => {
|
|
2943
3099
|
selectedCandidatePairChanges: 2,
|
2944
3100
|
numTransports: 1,
|
2945
3101
|
iceCandidatesCount: 0,
|
2946
|
-
|
2947
|
-
|
3102
|
+
subnet_reachable: null,
|
3103
|
+
selected_cluster: null,
|
3104
|
+
selected_subnet: null,
|
3105
|
+
ipver: 1,
|
2948
3106
|
},
|
2949
3107
|
]);
|
2950
3108
|
|
@@ -3146,13 +3304,15 @@ describe('plugin-meetings', () => {
|
|
3146
3304
|
connectionType: 'udp',
|
3147
3305
|
selectedCandidatePairChanges: 2,
|
3148
3306
|
ipVersion: 'IPv6',
|
3307
|
+
ipver: 1,
|
3149
3308
|
numTransports: 1,
|
3150
3309
|
isMultistream: false,
|
3151
3310
|
retriedWithTurnServer: true,
|
3152
3311
|
isJoinWithMediaRetry: false,
|
3153
3312
|
iceCandidatesCount: 0,
|
3154
|
-
|
3155
|
-
|
3313
|
+
subnet_reachable: null,
|
3314
|
+
selected_cluster: null,
|
3315
|
+
selected_subnet: null,
|
3156
3316
|
},
|
3157
3317
|
]);
|
3158
3318
|
meeting.roap.doTurnDiscovery;
|
@@ -3286,11 +3446,12 @@ describe('plugin-meetings', () => {
|
|
3286
3446
|
meeting.mediaConnections = [
|
3287
3447
|
{
|
3288
3448
|
mediaAgentCluster: 'some.cluster',
|
3289
|
-
}
|
3290
|
-
]
|
3449
|
+
},
|
3450
|
+
];
|
3291
3451
|
meeting.iceCandidatesCount = 3;
|
3292
3452
|
meeting.iceCandidateErrors.set('701_error', 3);
|
3293
3453
|
meeting.iceCandidateErrors.set('701_turn_host_lookup_received_error', 1);
|
3454
|
+
MeetingUtil.getIpVersion.returns(IP_VERSION.only_ipv6);
|
3294
3455
|
|
3295
3456
|
await meeting.addMedia({
|
3296
3457
|
mediaSettings: {},
|
@@ -3306,6 +3467,7 @@ describe('plugin-meetings', () => {
|
|
3306
3467
|
connectionType: 'udp',
|
3307
3468
|
selectedCandidatePairChanges: 2,
|
3308
3469
|
ipVersion: 'IPv6',
|
3470
|
+
ipver: 6,
|
3309
3471
|
numTransports: 1,
|
3310
3472
|
isMultistream: false,
|
3311
3473
|
retriedWithTurnServer: false,
|
@@ -3315,8 +3477,9 @@ describe('plugin-meetings', () => {
|
|
3315
3477
|
iceCandidatesCount: 3,
|
3316
3478
|
'701_error': 3,
|
3317
3479
|
'701_turn_host_lookup_received_error': 1,
|
3318
|
-
|
3319
|
-
|
3480
|
+
subnet_reachable: null,
|
3481
|
+
selected_cluster: 'some.cluster',
|
3482
|
+
selected_subnet: null,
|
3320
3483
|
}
|
3321
3484
|
);
|
3322
3485
|
|
@@ -3379,9 +3542,11 @@ describe('plugin-meetings', () => {
|
|
3379
3542
|
iceConnectionState: 'unknown',
|
3380
3543
|
selectedCandidatePairChanges: 2,
|
3381
3544
|
numTransports: 1,
|
3382
|
-
|
3383
|
-
|
3545
|
+
subnet_reachable: null,
|
3546
|
+
selected_cluster: null,
|
3547
|
+
selected_subnet: null,
|
3384
3548
|
iceCandidatesCount: 0,
|
3549
|
+
ipver: 1,
|
3385
3550
|
}
|
3386
3551
|
);
|
3387
3552
|
|
@@ -3442,16 +3607,18 @@ describe('plugin-meetings', () => {
|
|
3442
3607
|
numTransports: 1,
|
3443
3608
|
'701_error': 2,
|
3444
3609
|
'701_turn_host_lookup_received_error': 1,
|
3445
|
-
|
3446
|
-
|
3610
|
+
subnet_reachable: null,
|
3611
|
+
selected_cluster: null,
|
3612
|
+
selected_subnet: null,
|
3447
3613
|
iceCandidatesCount: 0,
|
3614
|
+
ipver: 1,
|
3448
3615
|
}
|
3449
3616
|
);
|
3450
3617
|
|
3451
3618
|
assert.isOk(errorThrown);
|
3452
3619
|
});
|
3453
3620
|
|
3454
|
-
it('should send
|
3621
|
+
it('should send subnet reachablity metrics if media connection success', async () => {
|
3455
3622
|
meeting.roap.doTurnDiscovery = sinon.stub().returns({
|
3456
3623
|
turnServerInfo: undefined,
|
3457
3624
|
turnDiscoverySkippedReason: undefined,
|
@@ -3465,6 +3632,12 @@ describe('plugin-meetings', () => {
|
|
3465
3632
|
stopReachability: sinon.stub(),
|
3466
3633
|
isSubnetReachable: sinon.stub().returns(false),
|
3467
3634
|
};
|
3635
|
+
meeting.mediaServerIp = '1.2.3.4';
|
3636
|
+
meeting.mediaConnections = [
|
3637
|
+
{
|
3638
|
+
mediaAgentCluster: 'some.cluster',
|
3639
|
+
},
|
3640
|
+
];
|
3468
3641
|
|
3469
3642
|
const forceRtcMetricsSend = sinon.stub().resolves();
|
3470
3643
|
const closeMediaConnectionStub = sinon.stub();
|
@@ -3485,6 +3658,7 @@ describe('plugin-meetings', () => {
|
|
3485
3658
|
locus_id: meeting.locusUrl.split('/').pop(),
|
3486
3659
|
connectionType: 'udp',
|
3487
3660
|
ipVersion: 'IPv6',
|
3661
|
+
ipver: 1,
|
3488
3662
|
selectedCandidatePairChanges: 2,
|
3489
3663
|
numTransports: 1,
|
3490
3664
|
isMultistream: false,
|
@@ -3492,12 +3666,13 @@ describe('plugin-meetings', () => {
|
|
3492
3666
|
isJoinWithMediaRetry: false,
|
3493
3667
|
iceCandidatesCount: 0,
|
3494
3668
|
reachability_public_udp_success: 5,
|
3495
|
-
|
3496
|
-
|
3669
|
+
subnet_reachable: false,
|
3670
|
+
selected_cluster: 'some.cluster',
|
3671
|
+
selected_subnet: '1.X.X.X',
|
3497
3672
|
});
|
3498
3673
|
});
|
3499
3674
|
|
3500
|
-
it('should send
|
3675
|
+
it('should send subnet reachablity metrics if media connection fails', async () => {
|
3501
3676
|
let errorThrown = undefined;
|
3502
3677
|
|
3503
3678
|
meeting.roap.doTurnDiscovery = sinon.stub().returns({
|
@@ -3513,6 +3688,12 @@ describe('plugin-meetings', () => {
|
|
3513
3688
|
stopReachability: sinon.stub(),
|
3514
3689
|
isSubnetReachable: sinon.stub().returns(true),
|
3515
3690
|
};
|
3691
|
+
meeting.mediaServerIp = '1.2.3.4';
|
3692
|
+
meeting.mediaConnections = [
|
3693
|
+
{
|
3694
|
+
mediaAgentCluster: 'some.cluster',
|
3695
|
+
},
|
3696
|
+
];
|
3516
3697
|
|
3517
3698
|
const forceRtcMetricsSend = sinon.stub().resolves();
|
3518
3699
|
const closeMediaConnectionStub = sinon.stub();
|
@@ -3554,9 +3735,11 @@ describe('plugin-meetings', () => {
|
|
3554
3735
|
selectedCandidatePairChanges: 2,
|
3555
3736
|
numTransports: 1,
|
3556
3737
|
reachability_public_udp_success: 5,
|
3557
|
-
|
3558
|
-
|
3738
|
+
subnet_reachable: true,
|
3739
|
+
selected_cluster: 'some.cluster',
|
3740
|
+
selected_subnet: '1.X.X.X',
|
3559
3741
|
iceCandidatesCount: 0,
|
3742
|
+
ipver: 1,
|
3560
3743
|
}
|
3561
3744
|
);
|
3562
3745
|
|
@@ -3862,13 +4045,14 @@ describe('plugin-meetings', () => {
|
|
3862
4045
|
});
|
3863
4046
|
});
|
3864
4047
|
|
3865
|
-
it('counts the number of members that are in the meeting for MEDIA_QUALITY event', async () => {
|
4048
|
+
it('counts the number of members that are in the meeting or lobby for MEDIA_QUALITY event', async () => {
|
3866
4049
|
let fakeMembersCollection = {
|
3867
4050
|
members: {
|
3868
|
-
member1: {isInMeeting: true},
|
3869
|
-
member2: {isInMeeting: true},
|
3870
|
-
member3: {isInMeeting: false},
|
3871
|
-
|
4051
|
+
member1: {isInMeeting: true, isInLobby: false},
|
4052
|
+
member2: {isInMeeting: false, isInLobby: true},
|
4053
|
+
member3: {isInMeeting: false, isInLobby: false},
|
4054
|
+
member4: {isInMeeting: true, isInLobby: false},
|
4055
|
+
}
|
3872
4056
|
};
|
3873
4057
|
sinon.stub(meeting, 'getMembers').returns({membersCollection: fakeMembersCollection});
|
3874
4058
|
const fakeData = {intervalMetadata: {}};
|
@@ -3886,11 +4070,12 @@ describe('plugin-meetings', () => {
|
|
3886
4070
|
},
|
3887
4071
|
payload: {
|
3888
4072
|
intervals: [
|
3889
|
-
sinon.match.has('intervalMetadata', sinon.match.has('meetingUserCount',
|
4073
|
+
sinon.match.has('intervalMetadata', sinon.match.has('meetingUserCount', 3)),
|
3890
4074
|
],
|
3891
4075
|
},
|
3892
4076
|
});
|
3893
|
-
|
4077
|
+
// Move member2 from lobby to neither in meeting nor lobby
|
4078
|
+
fakeMembersCollection.members.member2.isInLobby = false;
|
3894
4079
|
|
3895
4080
|
statsAnalyzerStub.emit(
|
3896
4081
|
{file: 'test', function: 'test'},
|
@@ -3905,7 +4090,7 @@ describe('plugin-meetings', () => {
|
|
3905
4090
|
},
|
3906
4091
|
payload: {
|
3907
4092
|
intervals: [
|
3908
|
-
sinon.match.has('intervalMetadata', sinon.match.has('meetingUserCount',
|
4093
|
+
sinon.match.has('intervalMetadata', sinon.match.has('meetingUserCount', 2)),
|
3909
4094
|
],
|
3910
4095
|
},
|
3911
4096
|
});
|
@@ -4152,7 +4337,7 @@ describe('plugin-meetings', () => {
|
|
4152
4337
|
meeting.deviceUrl = 'device url';
|
4153
4338
|
meeting.selfId = 'self id';
|
4154
4339
|
meeting.brbState = createBrbState(meeting, false);
|
4155
|
-
meeting.brbState
|
4340
|
+
sinon.stub(meeting.brbState, 'enable').resolves();
|
4156
4341
|
});
|
4157
4342
|
|
4158
4343
|
afterEach(() => {
|
@@ -4216,6 +4401,17 @@ describe('plugin-meetings', () => {
|
|
4216
4401
|
|
4217
4402
|
assert.notCalled(meeting.audio.handleServerRemoteMuteUpdate);
|
4218
4403
|
});
|
4404
|
+
|
4405
|
+
it('should reject when brb enable fails', async () => {
|
4406
|
+
meeting.brbState.enable.restore();
|
4407
|
+
|
4408
|
+
const error = new Error();
|
4409
|
+
meeting.meetingRequest.setBrb = sinon.stub().rejects(error);
|
4410
|
+
|
4411
|
+
await expect(meeting.beRightBack(true)).to.be.rejectedWith(error);
|
4412
|
+
|
4413
|
+
assert.isFalse(meeting.brbState.state.syncToServerInProgress);
|
4414
|
+
});
|
4219
4415
|
});
|
4220
4416
|
});
|
4221
4417
|
|
@@ -6362,25 +6558,36 @@ describe('plugin-meetings', () => {
|
|
6362
6558
|
const DIAL_IN_URL = meeting.dialInUrl;
|
6363
6559
|
|
6364
6560
|
assert.calledWith(meeting.meetingRequest.dialIn, {
|
6365
|
-
correlationId: meeting.
|
6561
|
+
correlationId: meeting.pstnCorrelationId,
|
6366
6562
|
dialInUrl: DIAL_IN_URL,
|
6367
6563
|
locusUrl: meeting.locusUrl,
|
6368
6564
|
clientUrl: meeting.deviceUrl,
|
6369
6565
|
});
|
6370
6566
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
6371
6567
|
|
6568
|
+
// Verify pstnCorrelationId was set
|
6569
|
+
assert.exists(meeting.pstnCorrelationId);
|
6570
|
+
assert.notEqual(meeting.pstnCorrelationId, meeting.correlationId);
|
6571
|
+
const firstPstnCorrelationId = meeting.pstnCorrelationId
|
6572
|
+
|
6372
6573
|
meeting.meetingRequest.dialIn.resetHistory();
|
6373
6574
|
|
6374
6575
|
// try again. the dial in urls should match
|
6375
6576
|
await meeting.usePhoneAudio();
|
6376
6577
|
|
6377
6578
|
assert.calledWith(meeting.meetingRequest.dialIn, {
|
6378
|
-
correlationId: meeting.
|
6579
|
+
correlationId: meeting.pstnCorrelationId,
|
6379
6580
|
dialInUrl: DIAL_IN_URL,
|
6380
6581
|
locusUrl: meeting.locusUrl,
|
6381
6582
|
clientUrl: meeting.deviceUrl,
|
6382
6583
|
});
|
6383
6584
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
6585
|
+
// A new PSTN correlationId should be generated for the second attempt
|
6586
|
+
assert.notEqual(
|
6587
|
+
meeting.pstnCorrelationId,
|
6588
|
+
firstPstnCorrelationId,
|
6589
|
+
'pstnCorrelationId should be regenerated on each dial-in attempt'
|
6590
|
+
);
|
6384
6591
|
});
|
6385
6592
|
|
6386
6593
|
it('given a phone number, triggers dial-out, delegating request to meetingRequest correctly', async () => {
|
@@ -6390,7 +6597,7 @@ describe('plugin-meetings', () => {
|
|
6390
6597
|
const DIAL_OUT_URL = meeting.dialOutUrl;
|
6391
6598
|
|
6392
6599
|
assert.calledWith(meeting.meetingRequest.dialOut, {
|
6393
|
-
correlationId: meeting.
|
6600
|
+
correlationId: meeting.pstnCorrelationId,
|
6394
6601
|
dialOutUrl: DIAL_OUT_URL,
|
6395
6602
|
locusUrl: meeting.locusUrl,
|
6396
6603
|
clientUrl: meeting.deviceUrl,
|
@@ -6398,49 +6605,126 @@ describe('plugin-meetings', () => {
|
|
6398
6605
|
});
|
6399
6606
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
6400
6607
|
|
6608
|
+
// Verify pstnCorrelationId was set
|
6609
|
+
assert.exists(meeting.pstnCorrelationId);
|
6610
|
+
assert.notEqual(meeting.pstnCorrelationId, meeting.correlationId);
|
6611
|
+
const firstPstnCorrelationId = meeting.pstnCorrelationId;
|
6612
|
+
|
6401
6613
|
meeting.meetingRequest.dialOut.resetHistory();
|
6402
6614
|
|
6403
6615
|
// try again. the dial out urls should match
|
6404
6616
|
await meeting.usePhoneAudio(phoneNumber);
|
6405
6617
|
|
6406
6618
|
assert.calledWith(meeting.meetingRequest.dialOut, {
|
6407
|
-
correlationId: meeting.
|
6619
|
+
correlationId: meeting.pstnCorrelationId,
|
6408
6620
|
dialOutUrl: DIAL_OUT_URL,
|
6409
6621
|
locusUrl: meeting.locusUrl,
|
6410
6622
|
clientUrl: meeting.deviceUrl,
|
6411
6623
|
phoneNumber,
|
6412
6624
|
});
|
6413
6625
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
6626
|
+
// A new PSTN correlationId should be generated for the second attempt
|
6627
|
+
assert.notEqual(
|
6628
|
+
meeting.pstnCorrelationId,
|
6629
|
+
firstPstnCorrelationId,
|
6630
|
+
'pstnCorrelationId should be regenerated on each dial-out attempt'
|
6631
|
+
);
|
6414
6632
|
});
|
6415
6633
|
|
6416
|
-
it('rejects if the request failed (dial in)', () => {
|
6417
|
-
const error = '
|
6634
|
+
it('rejects if the request failed (dial in)', async () => {
|
6635
|
+
const error = {error: {message: 'dial in failed'}, stack: 'error stack'};
|
6418
6636
|
|
6419
6637
|
meeting.meetingRequest.dialIn = sinon.stub().returns(Promise.reject(error));
|
6420
6638
|
|
6421
|
-
|
6422
|
-
.usePhoneAudio()
|
6423
|
-
|
6424
|
-
|
6425
|
-
|
6639
|
+
try {
|
6640
|
+
await meeting.usePhoneAudio();
|
6641
|
+
throw new Error('Promise resolved when it should have rejected');
|
6642
|
+
} catch (e) {
|
6643
|
+
assert.equal(e, error);
|
6426
6644
|
|
6427
|
-
|
6645
|
+
// Verify behavioral metric was sent with dial_in_correlation_id
|
6646
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
|
6647
|
+
correlation_id: meeting.correlationId,
|
6648
|
+
dial_in_url: meeting.dialInUrl,
|
6649
|
+
dial_in_correlation_id: sinon.match.string,
|
6650
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
6651
|
+
client_url: meeting.deviceUrl,
|
6652
|
+
reason: error.error.message,
|
6653
|
+
stack: error.stack,
|
6428
6654
|
});
|
6655
|
+
|
6656
|
+
// Verify pstnCorrelationId was cleared after error
|
6657
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6658
|
+
}
|
6429
6659
|
});
|
6430
6660
|
|
6431
6661
|
it('rejects if the request failed (dial out)', async () => {
|
6432
|
-
const error = '
|
6662
|
+
const error = {error: {message: 'dial out failed'}, stack: 'error stack'};
|
6433
6663
|
|
6434
6664
|
meeting.meetingRequest.dialOut = sinon.stub().returns(Promise.reject(error));
|
6435
6665
|
|
6436
|
-
|
6437
|
-
.usePhoneAudio('+441234567890')
|
6438
|
-
|
6439
|
-
|
6440
|
-
|
6666
|
+
try {
|
6667
|
+
await meeting.usePhoneAudio('+441234567890');
|
6668
|
+
throw new Error('Promise resolved when it should have rejected');
|
6669
|
+
} catch (e) {
|
6670
|
+
assert.equal(e, error);
|
6441
6671
|
|
6442
|
-
|
6672
|
+
// Verify behavioral metric was sent with dial_out_correlation_id
|
6673
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
|
6674
|
+
correlation_id: meeting.correlationId,
|
6675
|
+
dial_out_url: meeting.dialOutUrl,
|
6676
|
+
dial_out_correlation_id: sinon.match.string,
|
6677
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
6678
|
+
client_url: meeting.deviceUrl,
|
6679
|
+
reason: error.error.message,
|
6680
|
+
stack: error.stack,
|
6443
6681
|
});
|
6682
|
+
|
6683
|
+
// Verify pstnCorrelationId was cleared after error
|
6684
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6685
|
+
}
|
6686
|
+
});
|
6687
|
+
});
|
6688
|
+
|
6689
|
+
describe('#disconnectPhoneAudio', () => {
|
6690
|
+
beforeEach(() => {
|
6691
|
+
// Mock the MeetingUtil.disconnectPhoneAudio method
|
6692
|
+
sinon.stub(MeetingUtil, 'disconnectPhoneAudio').resolves();
|
6693
|
+
meeting.dialInUrl = 'dialin:///test-dial-in-url';
|
6694
|
+
meeting.dialOutUrl = 'dialout:///test-dial-out-url';
|
6695
|
+
meeting.dialInDeviceStatus = 'JOINED';
|
6696
|
+
meeting.dialOutDeviceStatus = 'JOINED';
|
6697
|
+
});
|
6698
|
+
|
6699
|
+
afterEach(() => {
|
6700
|
+
MeetingUtil.disconnectPhoneAudio.restore();
|
6701
|
+
});
|
6702
|
+
|
6703
|
+
it('should disconnect phone audio and clear pstnCorrelationId', async () => {
|
6704
|
+
meeting.pstnCorrelationId = 'test-pstn-correlation-id';
|
6705
|
+
|
6706
|
+
await meeting.disconnectPhoneAudio();
|
6707
|
+
|
6708
|
+
// Verify that pstnCorrelationId is cleared
|
6709
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6710
|
+
|
6711
|
+
// Verify that MeetingUtil.disconnectPhoneAudio was called for both dial-in and dial-out
|
6712
|
+
assert.calledTwice(MeetingUtil.disconnectPhoneAudio);
|
6713
|
+
assert.calledWith(MeetingUtil.disconnectPhoneAudio, meeting, meeting.dialInUrl);
|
6714
|
+
assert.calledWith(MeetingUtil.disconnectPhoneAudio, meeting, meeting.dialOutUrl);
|
6715
|
+
});
|
6716
|
+
|
6717
|
+
it('should handle case when no PSTN connection is active', async () => {
|
6718
|
+
meeting.dialInDeviceStatus = 'IDLE';
|
6719
|
+
meeting.dialOutDeviceStatus = 'IDLE';
|
6720
|
+
meeting.pstnCorrelationId = 'test-pstn-correlation-id';
|
6721
|
+
|
6722
|
+
await meeting.disconnectPhoneAudio();
|
6723
|
+
|
6724
|
+
// Verify that pstnCorrelationId is still cleared even when no phone connection is active
|
6725
|
+
assert.equal(meeting.pstnCorrelationId, undefined);
|
6726
|
+
// And verify no disconnect was attempted
|
6727
|
+
assert.notCalled(MeetingUtil.disconnectPhoneAudio);
|
6444
6728
|
});
|
6445
6729
|
});
|
6446
6730
|
|
@@ -7957,6 +8241,7 @@ describe('plugin-meetings', () => {
|
|
7957
8241
|
|
7958
8242
|
meeting.requestScreenShareFloor = sinon.stub().resolves({});
|
7959
8243
|
meeting.releaseScreenShareFloor = sinon.stub().resolves({});
|
8244
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
7960
8245
|
meeting.mediaProperties.mediaDirection = {
|
7961
8246
|
sendAudio: 'fake value', // using non-boolean here so that we can check that these values are untouched in tests
|
7962
8247
|
sendVideo: 'fake value',
|
@@ -8038,6 +8323,12 @@ describe('plugin-meetings', () => {
|
|
8038
8323
|
payload: {mediaType: 'share', shareInstanceId: meeting.localShareInstanceId},
|
8039
8324
|
options: {meetingId: meeting.id},
|
8040
8325
|
});
|
8326
|
+
|
8327
|
+
// ensure the share start timestamp is saved
|
8328
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
8329
|
+
key: 'internal.client.share.initiated',
|
8330
|
+
});
|
8331
|
+
|
8041
8332
|
assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
|
8042
8333
|
|
8043
8334
|
assert.equal(meeting.shareCAEventSentStatus.transmitStart, false);
|
@@ -8056,6 +8347,11 @@ describe('plugin-meetings', () => {
|
|
8056
8347
|
options: {meetingId: meeting.id},
|
8057
8348
|
});
|
8058
8349
|
|
8350
|
+
// ensure the share start timestamp is saved
|
8351
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
8352
|
+
key: 'internal.client.share.initiated',
|
8353
|
+
});
|
8354
|
+
|
8059
8355
|
assert.calledWith(
|
8060
8356
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
|
8061
8357
|
stream
|
@@ -10011,6 +10307,24 @@ describe('plugin-meetings', () => {
|
|
10011
10307
|
);
|
10012
10308
|
});
|
10013
10309
|
|
10310
|
+
it('listens to CONTROLS_POLLING_QA_CHANGED', async () => {
|
10311
|
+
const state = {example: 'value'};
|
10312
|
+
|
10313
|
+
await meeting.locusInfo.emitScoped(
|
10314
|
+
{function: 'test', file: 'test'},
|
10315
|
+
LOCUSINFO.EVENTS.CONTROLS_POLLING_QA_CHANGED,
|
10316
|
+
{state}
|
10317
|
+
);
|
10318
|
+
|
10319
|
+
assert.calledWith(
|
10320
|
+
TriggerProxy.trigger,
|
10321
|
+
meeting,
|
10322
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
10323
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_POLLING_QA_UPDATED,
|
10324
|
+
{state}
|
10325
|
+
);
|
10326
|
+
});
|
10327
|
+
|
10014
10328
|
it('listens to the locus interpretation update event', () => {
|
10015
10329
|
const interpretation = {
|
10016
10330
|
siLanguages: [{languageCode: 20, languageName: 'en'}],
|
@@ -10311,6 +10625,8 @@ describe('plugin-meetings', () => {
|
|
10311
10625
|
meeting.mediaProperties = {mediaDirection: {sendShare: true}};
|
10312
10626
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
10313
10627
|
(meeting.deviceUrl = 'deviceUrl.com'), (meeting.localShareInstanceId = '1234-5678');
|
10628
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
10629
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration = sinon.stub().returns(1000);
|
10314
10630
|
});
|
10315
10631
|
it('should call changeMeetingFloor()', async () => {
|
10316
10632
|
meeting.screenShareFloorState = 'GRANTED';
|
@@ -10328,6 +10644,22 @@ describe('plugin-meetings', () => {
|
|
10328
10644
|
assert.exists(share.then);
|
10329
10645
|
await share;
|
10330
10646
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
10647
|
+
|
10648
|
+
// ensure the share stop timestamp is saved
|
10649
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
10650
|
+
key: 'internal.client.share.stopped',
|
10651
|
+
});
|
10652
|
+
|
10653
|
+
// ensure the CA share stopped metric is submitted with duration
|
10654
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
10655
|
+
name: 'client.share.stopped',
|
10656
|
+
payload: {
|
10657
|
+
mediaType: 'share',
|
10658
|
+
shareInstanceId: meeting.localShareInstanceId,
|
10659
|
+
shareDuration: 1000,
|
10660
|
+
},
|
10661
|
+
options: {meetingId: meeting.id},
|
10662
|
+
});
|
10331
10663
|
});
|
10332
10664
|
it('should not call changeMeetingFloor() if someone else already has the floor', async () => {
|
10333
10665
|
// change selfId so that it doesn't match the beneficiary id from meeting.locusInfo.mediaShares
|
@@ -11603,6 +11935,14 @@ describe('plugin-meetings', () => {
|
|
11603
11935
|
requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
|
11604
11936
|
displayHints: userDisplayHints,
|
11605
11937
|
});
|
11938
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
11939
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_ATTENDEE_START_POLLING_QA],
|
11940
|
+
displayHints: userDisplayHints,
|
11941
|
+
});
|
11942
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
11943
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_ATTENDEE_START_POLLING_QA],
|
11944
|
+
displayHints: userDisplayHints,
|
11945
|
+
});
|
11606
11946
|
|
11607
11947
|
assert.calledWith(
|
11608
11948
|
TriggerProxy.trigger,
|
@@ -11892,6 +12232,7 @@ describe('plugin-meetings', () => {
|
|
11892
12232
|
meeting.locusInfo.self = {url: url1};
|
11893
12233
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
11894
12234
|
meeting.deviceUrl = 'deviceUrl.com';
|
12235
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
11895
12236
|
});
|
11896
12237
|
it('should have #startWhiteboardShare', () => {
|
11897
12238
|
assert.exists(meeting.startWhiteboardShare);
|
@@ -11919,6 +12260,11 @@ describe('plugin-meetings', () => {
|
|
11919
12260
|
payload: {mediaType: 'whiteboard'},
|
11920
12261
|
options: {meetingId: meeting.id},
|
11921
12262
|
});
|
12263
|
+
|
12264
|
+
// ensure the share start timestamp is saved
|
12265
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
12266
|
+
key: 'internal.client.share.initiated',
|
12267
|
+
});
|
11922
12268
|
});
|
11923
12269
|
});
|
11924
12270
|
describe('#stopWhiteboardShare', () => {
|
@@ -11930,6 +12276,9 @@ describe('plugin-meetings', () => {
|
|
11930
12276
|
meeting.locusInfo.self = {url: url1};
|
11931
12277
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
11932
12278
|
meeting.deviceUrl = 'deviceUrl.com';
|
12279
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
12280
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration = sinon.stub().returns(1000);
|
12281
|
+
webex.internal.newMetrics.submitClientEvent = sinon.stub();
|
11933
12282
|
});
|
11934
12283
|
it('should stop the whiteboard share', async () => {
|
11935
12284
|
const whiteboardShare = meeting.stopWhiteboardShare();
|
@@ -11944,6 +12293,21 @@ describe('plugin-meetings', () => {
|
|
11944
12293
|
uri: url1,
|
11945
12294
|
});
|
11946
12295
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
12296
|
+
|
12297
|
+
// ensure the share stop timestamp is saved
|
12298
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
12299
|
+
key: 'internal.client.share.stopped',
|
12300
|
+
});
|
12301
|
+
|
12302
|
+
// ensure the CA share stopped metric is submitted with duration
|
12303
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
12304
|
+
name: 'client.share.stopped',
|
12305
|
+
payload: {
|
12306
|
+
mediaType: 'whiteboard',
|
12307
|
+
shareDuration: 1000,
|
12308
|
+
},
|
12309
|
+
options: {meetingId: meeting.id},
|
12310
|
+
});
|
11947
12311
|
});
|
11948
12312
|
});
|
11949
12313
|
});
|
@@ -12016,6 +12380,9 @@ describe('plugin-meetings', () => {
|
|
12016
12380
|
meeting.selfId = '9528d952-e4de-46cf-8157-fd4823b98377';
|
12017
12381
|
meeting.deviceUrl = 'my-web-url';
|
12018
12382
|
meeting.locusInfo.info = {isWebinar: false};
|
12383
|
+
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
12384
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration = sinon.stub().returns(1500);
|
12385
|
+
webex.internal.newMetrics.submitClientEvent = sinon.stub();
|
12019
12386
|
});
|
12020
12387
|
|
12021
12388
|
const USER_IDS = {
|
@@ -12242,7 +12609,7 @@ describe('plugin-meetings', () => {
|
|
12242
12609
|
activeSharingId.whiteboard = beneficiaryId;
|
12243
12610
|
|
12244
12611
|
eventTrigger.share.push(
|
12245
|
-
meeting.webinar.selfIsAttendee
|
12612
|
+
meeting.webinar.selfIsAttendee || meeting.guest
|
12246
12613
|
? {
|
12247
12614
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
12248
12615
|
functionName: 'remoteShare',
|
@@ -12261,7 +12628,8 @@ describe('plugin-meetings', () => {
|
|
12261
12628
|
}
|
12262
12629
|
);
|
12263
12630
|
|
12264
|
-
shareStatus =
|
12631
|
+
shareStatus =
|
12632
|
+
meeting.webinar.selfIsAttendee || meeting.guest
|
12265
12633
|
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
12266
12634
|
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
12267
12635
|
}
|
@@ -12479,6 +12847,36 @@ describe('plugin-meetings', () => {
|
|
12479
12847
|
});
|
12480
12848
|
});
|
12481
12849
|
|
12850
|
+
describe('Whiteboard Share - User is guest', () => {
|
12851
|
+
it('User receives a remote share instead of whiteboard share', () => {
|
12852
|
+
// Set the guest flag
|
12853
|
+
meeting.guest = true;
|
12854
|
+
|
12855
|
+
// Step 1: Start sharing whiteboard A
|
12856
|
+
const data1 = generateData(
|
12857
|
+
blankPayload, // Initial payload
|
12858
|
+
true, // isGranting: Granting share
|
12859
|
+
false, // isContent: Whiteboard (not content)
|
12860
|
+
USER_IDS.REMOTE_A, // Beneficiary ID: Remote user A
|
12861
|
+
RESOURCE_URLS.WHITEBOARD_A // Resource URL: Whiteboard A
|
12862
|
+
);
|
12863
|
+
|
12864
|
+
// Step 2: Stop sharing whiteboard A
|
12865
|
+
const data2 = generateData(
|
12866
|
+
data1.payload, // Updated payload from Step 1
|
12867
|
+
false, // isGranting: Stopping share
|
12868
|
+
false, // isContent: Whiteboard
|
12869
|
+
USER_IDS.REMOTE_A // Beneficiary ID: Remote user A
|
12870
|
+
);
|
12871
|
+
|
12872
|
+
// Validate the payload changes and status updates
|
12873
|
+
payloadTestHelper([data1]);
|
12874
|
+
|
12875
|
+
// Specific assertions for guest
|
12876
|
+
assert.equal(meeting.shareStatus, SHARE_STATUS.REMOTE_SHARE_ACTIVE);
|
12877
|
+
});
|
12878
|
+
});
|
12879
|
+
|
12482
12880
|
describe('Whiteboard A --> Whiteboard B', () => {
|
12483
12881
|
it('Scenario #1: you share both whiteboards', () => {
|
12484
12882
|
const data1 = generateData(
|
@@ -13130,7 +13528,54 @@ describe('plugin-meetings', () => {
|
|
13130
13528
|
payloadTestHelper([data1, data2, data3]);
|
13131
13529
|
});
|
13132
13530
|
});
|
13133
|
-
|
13531
|
+
|
13532
|
+
it('should send share stopped metric when whiteboard sharing stops', () => {
|
13533
|
+
// Start whiteboard sharing (this won't trigger metrics)
|
13534
|
+
const data1 = generateData(
|
13535
|
+
blankPayload,
|
13536
|
+
true, // isGranting: true
|
13537
|
+
false, // isContent: false (whiteboard)
|
13538
|
+
USER_IDS.ME,
|
13539
|
+
RESOURCE_URLS.WHITEBOARD_A
|
13540
|
+
);
|
13541
|
+
|
13542
|
+
// Stop whiteboard sharing (this should trigger metrics)
|
13543
|
+
const data2 = generateData(
|
13544
|
+
data1.payload,
|
13545
|
+
false, // isGranting: false (stopping share)
|
13546
|
+
false, // isContent: false (whiteboard)
|
13547
|
+
USER_IDS.ME
|
13548
|
+
);
|
13549
|
+
|
13550
|
+
// Trigger the events
|
13551
|
+
meeting.locusInfo.emit(
|
13552
|
+
{function: 'test', file: 'test'},
|
13553
|
+
EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES,
|
13554
|
+
data1.payload
|
13555
|
+
);
|
13556
|
+
|
13557
|
+
meeting.locusInfo.emit(
|
13558
|
+
{function: 'test', file: 'test'},
|
13559
|
+
EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES,
|
13560
|
+
data2.payload
|
13561
|
+
);
|
13562
|
+
|
13563
|
+
// Verify metrics were called when whiteboard sharing stopped
|
13564
|
+
assert.calledWith(webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp, {
|
13565
|
+
key: 'internal.client.share.stopped',
|
13566
|
+
});
|
13567
|
+
|
13568
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
13569
|
+
name: 'client.share.stopped',
|
13570
|
+
payload: {
|
13571
|
+
mediaType: 'whiteboard',
|
13572
|
+
shareDuration: 1500, // mocked return value
|
13573
|
+
},
|
13574
|
+
options: {
|
13575
|
+
meetingId: meeting.id,
|
13576
|
+
},
|
13577
|
+
});
|
13578
|
+
});
|
13134
13579
|
|
13135
13580
|
describe('handleShareVideoStreamMuteStateChange', () => {
|
13136
13581
|
it('should emit MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE event with correct fields', () => {
|
@@ -13157,6 +13602,7 @@ describe('plugin-meetings', () => {
|
|
13157
13602
|
});
|
13158
13603
|
});
|
13159
13604
|
});
|
13605
|
+
});
|
13160
13606
|
|
13161
13607
|
describe('#startKeepAlive', () => {
|
13162
13608
|
let clock;
|
@@ -13923,4 +14369,443 @@ describe('plugin-meetings', () => {
|
|
13923
14369
|
assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
|
13924
14370
|
});
|
13925
14371
|
});
|
14372
|
+
|
14373
|
+
describe('#setStage', () => {
|
14374
|
+
const check = async (options, expectedVideoLayout) => {
|
14375
|
+
const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
|
14376
|
+
meeting.locusUrl = locusUrl;
|
14377
|
+
|
14378
|
+
const setStagePromise = meeting.setStage(options);
|
14379
|
+
|
14380
|
+
assert.exists(setStagePromise.then);
|
14381
|
+
await setStagePromise;
|
14382
|
+
|
14383
|
+
assert.calledOnceWithExactly(
|
14384
|
+
meeting.meetingRequest.synchronizeStage,
|
14385
|
+
locusUrl,
|
14386
|
+
expectedVideoLayout
|
14387
|
+
);
|
14388
|
+
};
|
14389
|
+
|
14390
|
+
beforeEach(() => {
|
14391
|
+
meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
|
14392
|
+
});
|
14393
|
+
|
14394
|
+
it('sends the expected request when no options are provided', async () => {
|
14395
|
+
await check(undefined, {
|
14396
|
+
overrideDefault: true,
|
14397
|
+
lockAttendeeViewOnStageOnly: false,
|
14398
|
+
stageParameters: {
|
14399
|
+
activeSpeakerProportion: 0.5,
|
14400
|
+
showActiveSpeaker: {show: false, order: 0},
|
14401
|
+
stageManagerType: 0,
|
14402
|
+
},
|
14403
|
+
});
|
14404
|
+
});
|
14405
|
+
|
14406
|
+
it('sends the expected request when empty options are provided', async () => {
|
14407
|
+
await check(
|
14408
|
+
{},
|
14409
|
+
{
|
14410
|
+
overrideDefault: true,
|
14411
|
+
lockAttendeeViewOnStageOnly: false,
|
14412
|
+
stageParameters: {
|
14413
|
+
activeSpeakerProportion: 0.5,
|
14414
|
+
showActiveSpeaker: {show: false, order: 0},
|
14415
|
+
stageManagerType: 0,
|
14416
|
+
},
|
14417
|
+
}
|
14418
|
+
);
|
14419
|
+
});
|
14420
|
+
|
14421
|
+
[0.25, 0.5, 0.75].forEach((activeSpeakerProportion) => {
|
14422
|
+
it(`sends the expected request when only the active speaker proportion option is provided as ${activeSpeakerProportion}`, async () => {
|
14423
|
+
await check(
|
14424
|
+
{activeSpeakerProportion},
|
14425
|
+
{
|
14426
|
+
overrideDefault: true,
|
14427
|
+
lockAttendeeViewOnStageOnly: false,
|
14428
|
+
stageParameters: {
|
14429
|
+
activeSpeakerProportion,
|
14430
|
+
showActiveSpeaker: {show: false, order: 0},
|
14431
|
+
stageManagerType: 0,
|
14432
|
+
},
|
14433
|
+
}
|
14434
|
+
);
|
14435
|
+
});
|
14436
|
+
});
|
14437
|
+
|
14438
|
+
it('sends the expected request when only the custom background option is provided', async () => {
|
14439
|
+
const customBackground = {
|
14440
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14441
|
+
};
|
14442
|
+
|
14443
|
+
await check(
|
14444
|
+
{customBackground},
|
14445
|
+
{
|
14446
|
+
overrideDefault: true,
|
14447
|
+
lockAttendeeViewOnStageOnly: false,
|
14448
|
+
stageParameters: {
|
14449
|
+
activeSpeakerProportion: 0.5,
|
14450
|
+
showActiveSpeaker: {show: false, order: 0},
|
14451
|
+
stageManagerType: 2,
|
14452
|
+
},
|
14453
|
+
customLayouts: {background: customBackground},
|
14454
|
+
}
|
14455
|
+
);
|
14456
|
+
});
|
14457
|
+
|
14458
|
+
it('sends the expected request when only the custom logo option is provided', async () => {
|
14459
|
+
const customLogo = {
|
14460
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14461
|
+
position: 'LowerRight',
|
14462
|
+
};
|
14463
|
+
|
14464
|
+
await check(
|
14465
|
+
{customLogo},
|
14466
|
+
{
|
14467
|
+
overrideDefault: true,
|
14468
|
+
lockAttendeeViewOnStageOnly: false,
|
14469
|
+
stageParameters: {
|
14470
|
+
activeSpeakerProportion: 0.5,
|
14471
|
+
showActiveSpeaker: {show: false, order: 0},
|
14472
|
+
stageManagerType: 1,
|
14473
|
+
},
|
14474
|
+
customLayouts: {logo: customLogo},
|
14475
|
+
}
|
14476
|
+
);
|
14477
|
+
});
|
14478
|
+
|
14479
|
+
it('sends the expected request when only the custom name label option is provided', async () => {
|
14480
|
+
const customNameLabel = {
|
14481
|
+
accentColor: '#0A7806',
|
14482
|
+
background: {color: 'rgba(255, 255, 255, 1)'},
|
14483
|
+
border: {color: 'rgba(255, 255, 255, 1)'},
|
14484
|
+
content: {
|
14485
|
+
displayName: {color: 'rgba(0, 0, 0, 0.95)'},
|
14486
|
+
subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
|
14487
|
+
},
|
14488
|
+
decoration: {color: 'rgba(10, 120, 6, 1)'},
|
14489
|
+
fadeOut: {delay: 15},
|
14490
|
+
type: 'Primary',
|
14491
|
+
};
|
14492
|
+
|
14493
|
+
await check(
|
14494
|
+
{customNameLabel},
|
14495
|
+
{
|
14496
|
+
overrideDefault: true,
|
14497
|
+
lockAttendeeViewOnStageOnly: false,
|
14498
|
+
stageParameters: {
|
14499
|
+
activeSpeakerProportion: 0.5,
|
14500
|
+
showActiveSpeaker: {show: false, order: 0},
|
14501
|
+
stageManagerType: 4,
|
14502
|
+
},
|
14503
|
+
nameLabelStyle: customNameLabel,
|
14504
|
+
}
|
14505
|
+
);
|
14506
|
+
});
|
14507
|
+
|
14508
|
+
it('sends the expected request when only the custom background and logo options are provided', async () => {
|
14509
|
+
const customBackground = {
|
14510
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14511
|
+
};
|
14512
|
+
const customLogo = {
|
14513
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14514
|
+
position: 'UpperRight',
|
14515
|
+
};
|
14516
|
+
|
14517
|
+
await check(
|
14518
|
+
{customBackground, customLogo},
|
14519
|
+
{
|
14520
|
+
overrideDefault: true,
|
14521
|
+
lockAttendeeViewOnStageOnly: false,
|
14522
|
+
stageParameters: {
|
14523
|
+
activeSpeakerProportion: 0.5,
|
14524
|
+
showActiveSpeaker: {show: false, order: 0},
|
14525
|
+
stageManagerType: 3,
|
14526
|
+
},
|
14527
|
+
customLayouts: {background: customBackground, logo: customLogo},
|
14528
|
+
}
|
14529
|
+
);
|
14530
|
+
});
|
14531
|
+
|
14532
|
+
it('sends the expected request when only the custom background and name label options are provided', async () => {
|
14533
|
+
const customBackground = {
|
14534
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14535
|
+
};
|
14536
|
+
const customNameLabel = {
|
14537
|
+
accentColor: '#00A3FF',
|
14538
|
+
background: {color: 'rgba(0, 163, 255, 1)'},
|
14539
|
+
border: {color: 'rgba(0, 163, 255, 1)'},
|
14540
|
+
content: {
|
14541
|
+
displayName: {color: 'rgba(255, 255, 255, 0.95)'},
|
14542
|
+
subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
|
14543
|
+
},
|
14544
|
+
decoration: {color: 'rgba(255, 255, 255, 0.95)'},
|
14545
|
+
fadeOut: {delay: 15},
|
14546
|
+
type: 'PrimaryInverted',
|
14547
|
+
};
|
14548
|
+
|
14549
|
+
await check(
|
14550
|
+
{customBackground, customNameLabel},
|
14551
|
+
{
|
14552
|
+
overrideDefault: true,
|
14553
|
+
lockAttendeeViewOnStageOnly: false,
|
14554
|
+
stageParameters: {
|
14555
|
+
activeSpeakerProportion: 0.5,
|
14556
|
+
showActiveSpeaker: {show: false, order: 0},
|
14557
|
+
stageManagerType: 6,
|
14558
|
+
},
|
14559
|
+
customLayouts: {background: customBackground},
|
14560
|
+
nameLabelStyle: customNameLabel,
|
14561
|
+
}
|
14562
|
+
);
|
14563
|
+
});
|
14564
|
+
|
14565
|
+
it('sends the expected request when only the custom logo and name label options are provided', async () => {
|
14566
|
+
const customLogo = {
|
14567
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14568
|
+
position: 'UpperLeft',
|
14569
|
+
};
|
14570
|
+
const customNameLabel = {
|
14571
|
+
accentColor: '#942B2B',
|
14572
|
+
background: {color: 'rgba(255, 255, 255, 1)'},
|
14573
|
+
border: {color: 'rgba(148, 43, 43, 1)'},
|
14574
|
+
content: {
|
14575
|
+
displayName: {color: 'rgba(0, 0, 0, 0.95)'},
|
14576
|
+
subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
|
14577
|
+
},
|
14578
|
+
decoration: {color: 'rgba(0, 0, 0, 0)'},
|
14579
|
+
fadeOut: {delay: 15},
|
14580
|
+
type: 'Secondary',
|
14581
|
+
};
|
14582
|
+
|
14583
|
+
await check(
|
14584
|
+
{customLogo, customNameLabel},
|
14585
|
+
{
|
14586
|
+
overrideDefault: true,
|
14587
|
+
lockAttendeeViewOnStageOnly: false,
|
14588
|
+
stageParameters: {
|
14589
|
+
activeSpeakerProportion: 0.5,
|
14590
|
+
showActiveSpeaker: {show: false, order: 0},
|
14591
|
+
stageManagerType: 5,
|
14592
|
+
},
|
14593
|
+
customLayouts: {logo: customLogo},
|
14594
|
+
nameLabelStyle: customNameLabel,
|
14595
|
+
}
|
14596
|
+
);
|
14597
|
+
});
|
14598
|
+
|
14599
|
+
it('sends the expected request when only the custom background, logo, name label options are provided', async () => {
|
14600
|
+
const customBackground = {
|
14601
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14602
|
+
};
|
14603
|
+
const customLogo = {
|
14604
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14605
|
+
position: 'LowerLeft',
|
14606
|
+
};
|
14607
|
+
const customNameLabel = {
|
14608
|
+
accentColor: '#EBD960',
|
14609
|
+
background: {color: 'rgba(235, 217, 96, 0.55)'},
|
14610
|
+
border: {color: 'rgba(235, 217, 96, 0.55)'},
|
14611
|
+
content: {
|
14612
|
+
displayName: {color: 'rgba(255, 255, 255, 0.95)'},
|
14613
|
+
subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
|
14614
|
+
},
|
14615
|
+
decoration: {color: 'rgba(0, 0, 0, 0)'},
|
14616
|
+
fadeOut: {delay: 15},
|
14617
|
+
type: 'SecondaryInverted',
|
14618
|
+
};
|
14619
|
+
|
14620
|
+
await check(
|
14621
|
+
{customBackground, customLogo, customNameLabel},
|
14622
|
+
{
|
14623
|
+
overrideDefault: true,
|
14624
|
+
lockAttendeeViewOnStageOnly: false,
|
14625
|
+
stageParameters: {
|
14626
|
+
activeSpeakerProportion: 0.5,
|
14627
|
+
showActiveSpeaker: {show: false, order: 0},
|
14628
|
+
stageManagerType: 7,
|
14629
|
+
},
|
14630
|
+
customLayouts: {background: customBackground, logo: customLogo},
|
14631
|
+
nameLabelStyle: customNameLabel,
|
14632
|
+
}
|
14633
|
+
);
|
14634
|
+
});
|
14635
|
+
|
14636
|
+
it('sends the expected request when only the important participants option is provided as empty', async () => {
|
14637
|
+
await check(
|
14638
|
+
{importantParticipants: []},
|
14639
|
+
{
|
14640
|
+
overrideDefault: true,
|
14641
|
+
lockAttendeeViewOnStageOnly: false,
|
14642
|
+
stageParameters: {
|
14643
|
+
activeSpeakerProportion: 0.5,
|
14644
|
+
showActiveSpeaker: {show: false, order: 0},
|
14645
|
+
stageManagerType: 0,
|
14646
|
+
},
|
14647
|
+
}
|
14648
|
+
);
|
14649
|
+
});
|
14650
|
+
|
14651
|
+
it('sends the expected request when only the important participants option is provided as populated', async () => {
|
14652
|
+
const importantParticipants = [
|
14653
|
+
{mainCsi: 11111111, participantId: uuidv4()},
|
14654
|
+
{mainCsi: 22222222, participantId: uuidv4()},
|
14655
|
+
{mainCsi: 33333333, participantId: uuidv4()},
|
14656
|
+
{mainCsi: 44444444, participantId: uuidv4()},
|
14657
|
+
{mainCsi: 55555555, participantId: uuidv4()},
|
14658
|
+
{mainCsi: 66666666, participantId: uuidv4()},
|
14659
|
+
{mainCsi: 77777777, participantId: uuidv4()},
|
14660
|
+
{mainCsi: 88888888, participantId: uuidv4()},
|
14661
|
+
];
|
14662
|
+
|
14663
|
+
await check(
|
14664
|
+
{importantParticipants},
|
14665
|
+
{
|
14666
|
+
overrideDefault: true,
|
14667
|
+
lockAttendeeViewOnStageOnly: false,
|
14668
|
+
stageParameters: {
|
14669
|
+
activeSpeakerProportion: 0.5,
|
14670
|
+
importantParticipants: [
|
14671
|
+
{...importantParticipants[0], order: 1},
|
14672
|
+
{...importantParticipants[1], order: 2},
|
14673
|
+
{...importantParticipants[2], order: 3},
|
14674
|
+
{...importantParticipants[3], order: 4},
|
14675
|
+
{...importantParticipants[4], order: 5},
|
14676
|
+
{...importantParticipants[5], order: 6},
|
14677
|
+
{...importantParticipants[6], order: 7},
|
14678
|
+
{...importantParticipants[7], order: 8},
|
14679
|
+
],
|
14680
|
+
showActiveSpeaker: {show: false, order: 0},
|
14681
|
+
stageManagerType: 0,
|
14682
|
+
},
|
14683
|
+
}
|
14684
|
+
);
|
14685
|
+
});
|
14686
|
+
|
14687
|
+
[false, true].forEach((lockAttendeeViewOnStage) => {
|
14688
|
+
it(`sends the expected request when only the lock attendee view on stage option is provided as ${lockAttendeeViewOnStage}`, async () => {
|
14689
|
+
await check(
|
14690
|
+
{lockAttendeeViewOnStage},
|
14691
|
+
{
|
14692
|
+
overrideDefault: true,
|
14693
|
+
lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
|
14694
|
+
stageParameters: {
|
14695
|
+
activeSpeakerProportion: 0.5,
|
14696
|
+
showActiveSpeaker: {show: false, order: 0},
|
14697
|
+
stageManagerType: 0,
|
14698
|
+
},
|
14699
|
+
}
|
14700
|
+
);
|
14701
|
+
});
|
14702
|
+
});
|
14703
|
+
|
14704
|
+
[false, true].forEach((showActiveSpeaker) => {
|
14705
|
+
it(`sends the expected request when only the show active speaker option is provided as ${showActiveSpeaker}`, async () => {
|
14706
|
+
await check(
|
14707
|
+
{showActiveSpeaker},
|
14708
|
+
{
|
14709
|
+
overrideDefault: true,
|
14710
|
+
lockAttendeeViewOnStageOnly: false,
|
14711
|
+
stageParameters: {
|
14712
|
+
activeSpeakerProportion: 0.5,
|
14713
|
+
showActiveSpeaker: {show: showActiveSpeaker, order: 0},
|
14714
|
+
stageManagerType: 0,
|
14715
|
+
},
|
14716
|
+
}
|
14717
|
+
);
|
14718
|
+
});
|
14719
|
+
});
|
14720
|
+
|
14721
|
+
it('sends the expected request when all options are provided', async () => {
|
14722
|
+
const activeSpeakerProportion = 0.6;
|
14723
|
+
const customBackground = {
|
14724
|
+
url: `https://test.wbx2.com/background/${uuidv4()}.jpg`,
|
14725
|
+
};
|
14726
|
+
const customLogo = {
|
14727
|
+
url: `https://test.wbx2.com/logo/${uuidv4()}.png`,
|
14728
|
+
position: 'UpperMiddle',
|
14729
|
+
};
|
14730
|
+
const customNameLabel = {
|
14731
|
+
accentColor: '#0A7806',
|
14732
|
+
background: {color: 'rgba(255, 255, 255, 1)'},
|
14733
|
+
border: {color: 'rgba(255, 255, 255, 1)'},
|
14734
|
+
content: {
|
14735
|
+
displayName: {color: 'rgba(0, 0, 0, 0.95)'},
|
14736
|
+
subtitle: {color: 'rgba(0, 0, 0, 0.6)'},
|
14737
|
+
},
|
14738
|
+
decoration: {color: 'rgba(10, 120, 6, 1)'},
|
14739
|
+
fadeOut: {delay: 15},
|
14740
|
+
type: 'Primary',
|
14741
|
+
};
|
14742
|
+
const importantParticipants = [
|
14743
|
+
{mainCsi: 11111111, participantId: uuidv4()},
|
14744
|
+
{mainCsi: 22222222, participantId: uuidv4()},
|
14745
|
+
{mainCsi: 33333333, participantId: uuidv4()},
|
14746
|
+
{mainCsi: 44444444, participantId: uuidv4()},
|
14747
|
+
{mainCsi: 55555555, participantId: uuidv4()},
|
14748
|
+
{mainCsi: 66666666, participantId: uuidv4()},
|
14749
|
+
{mainCsi: 77777777, participantId: uuidv4()},
|
14750
|
+
{mainCsi: 88888888, participantId: uuidv4()},
|
14751
|
+
];
|
14752
|
+
const lockAttendeeViewOnStage = true;
|
14753
|
+
const showActiveSpeaker = true;
|
14754
|
+
|
14755
|
+
await check(
|
14756
|
+
{
|
14757
|
+
activeSpeakerProportion,
|
14758
|
+
customBackground,
|
14759
|
+
customLogo,
|
14760
|
+
customNameLabel,
|
14761
|
+
importantParticipants,
|
14762
|
+
lockAttendeeViewOnStage,
|
14763
|
+
showActiveSpeaker,
|
14764
|
+
},
|
14765
|
+
{
|
14766
|
+
overrideDefault: true,
|
14767
|
+
lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
|
14768
|
+
stageParameters: {
|
14769
|
+
activeSpeakerProportion,
|
14770
|
+
importantParticipants: [
|
14771
|
+
{...importantParticipants[0], order: 1},
|
14772
|
+
{...importantParticipants[1], order: 2},
|
14773
|
+
{...importantParticipants[2], order: 3},
|
14774
|
+
{...importantParticipants[3], order: 4},
|
14775
|
+
{...importantParticipants[4], order: 5},
|
14776
|
+
{...importantParticipants[5], order: 6},
|
14777
|
+
{...importantParticipants[6], order: 7},
|
14778
|
+
{...importantParticipants[7], order: 8},
|
14779
|
+
],
|
14780
|
+
showActiveSpeaker: {show: showActiveSpeaker, order: 0},
|
14781
|
+
stageManagerType: 7,
|
14782
|
+
},
|
14783
|
+
customLayouts: {background: customBackground, logo: customLogo},
|
14784
|
+
nameLabelStyle: customNameLabel,
|
14785
|
+
}
|
14786
|
+
);
|
14787
|
+
});
|
14788
|
+
});
|
14789
|
+
|
14790
|
+
describe('#unsetStage', () => {
|
14791
|
+
beforeEach(() => {
|
14792
|
+
meeting.meetingRequest.synchronizeStage = sinon.stub().returns(Promise.resolve());
|
14793
|
+
});
|
14794
|
+
|
14795
|
+
it('sends the expected request', async () => {
|
14796
|
+
const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
|
14797
|
+
meeting.locusUrl = locusUrl;
|
14798
|
+
|
14799
|
+
const unsetStagePromise = meeting.unsetStage();
|
14800
|
+
|
14801
|
+
assert.exists(unsetStagePromise.then);
|
14802
|
+
await unsetStagePromise;
|
14803
|
+
|
14804
|
+
assert.calledOnceWithExactly(
|
14805
|
+
meeting.meetingRequest.synchronizeStage,
|
14806
|
+
locusUrl,
|
14807
|
+
{overrideDefault: false}
|
14808
|
+
);
|
14809
|
+
});
|
14810
|
+
});
|
13926
14811
|
});
|