@webex/plugin-meetings 3.6.0-next.9 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +24 -2
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +1 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +10 -3
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +12 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +28 -4
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js +2 -1
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/index.js +61 -3
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +19 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +536 -409
- package/dist/meeting/index.js.map +1 -1
- package/dist/meetings/index.js +2 -0
- package/dist/meetings/index.js.map +1 -1
- package/dist/members/index.js +3 -2
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +9 -5
- package/dist/members/util.js.map +1 -1
- package/dist/networkQualityMonitor/index.js +227 -0
- package/dist/networkQualityMonitor/index.js.map +1 -0
- package/dist/reachability/index.js +3 -3
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +2 -1
- package/dist/reachability/request.js.map +1 -1
- package/dist/rtcMetrics/constants.js +11 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.js +197 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/constants.d.ts +19 -0
- package/dist/types/controls-options-manager/enums.d.ts +2 -1
- package/dist/types/controls-options-manager/index.d.ts +2 -1
- package/dist/types/controls-options-manager/types.d.ts +2 -0
- package/dist/types/locus-info/index.d.ts +9 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +18 -0
- package/dist/types/meeting/index.d.ts +12 -1
- package/dist/types/members/index.d.ts +2 -1
- package/dist/types/members/util.d.ts +3 -1
- package/dist/types/networkQualityMonitor/index.d.ts +70 -0
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +71 -0
- package/dist/webinar/index.js +32 -19
- package/dist/webinar/index.js.map +1 -1
- package/package.json +22 -22
- package/src/config.ts +1 -0
- package/src/constants.ts +25 -0
- package/src/controls-options-manager/enums.ts +1 -0
- package/src/controls-options-manager/index.ts +19 -2
- package/src/controls-options-manager/types.ts +2 -0
- package/src/controls-options-manager/util.ts +12 -0
- package/src/locus-info/controlsUtils.ts +46 -2
- package/src/locus-info/fullState.ts +1 -0
- package/src/locus-info/index.ts +60 -0
- package/src/meeting/in-meeting-actions.ts +37 -0
- package/src/meeting/index.ts +114 -9
- package/src/meetings/index.ts +46 -39
- package/src/members/index.ts +4 -2
- package/src/members/util.ts +3 -1
- package/src/reachability/index.ts +3 -3
- package/src/reachability/request.ts +1 -0
- package/src/webinar/index.ts +31 -17
- package/test/unit/spec/controls-options-manager/index.js +56 -32
- package/test/unit/spec/controls-options-manager/util.js +44 -0
- package/test/unit/spec/locus-info/controlsUtils.js +80 -4
- package/test/unit/spec/locus-info/index.js +59 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +18 -0
- package/test/unit/spec/meeting/index.js +222 -82
- package/test/unit/spec/meetings/index.js +16 -1
- package/test/unit/spec/members/index.js +25 -2
- package/test/unit/spec/members/request.js +37 -3
- package/test/unit/spec/members/utils.js +15 -1
- package/test/unit/spec/reachability/index.ts +1 -1
- package/test/unit/spec/reachability/request.js +13 -8
- package/test/unit/spec/webinar/index.ts +82 -16
|
@@ -90,8 +90,8 @@ import WebExMeetingsErrors from '../../../../src/common/errors/webex-meetings-er
|
|
|
90
90
|
import ParameterError from '../../../../src/common/errors/parameter';
|
|
91
91
|
import PasswordError from '../../../../src/common/errors/password-error';
|
|
92
92
|
import CaptchaError from '../../../../src/common/errors/captcha-error';
|
|
93
|
-
import PermissionError
|
|
94
|
-
import WebinarRegistrationError
|
|
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 {
|
|
@@ -377,7 +377,10 @@ describe('plugin-meetings', () => {
|
|
|
377
377
|
}
|
|
378
378
|
);
|
|
379
379
|
assert.equal(newMeeting.correlationId, newMeeting.id);
|
|
380
|
-
assert.deepEqual(newMeeting.callStateForMetrics, {
|
|
380
|
+
assert.deepEqual(newMeeting.callStateForMetrics, {
|
|
381
|
+
correlationId: newMeeting.id,
|
|
382
|
+
sessionCorrelationId: '',
|
|
383
|
+
});
|
|
381
384
|
});
|
|
382
385
|
|
|
383
386
|
it('correlationId can be provided in callStateForMetrics', () => {
|
|
@@ -3442,47 +3445,60 @@ describe('plugin-meetings', () => {
|
|
|
3442
3445
|
});
|
|
3443
3446
|
});
|
|
3444
3447
|
|
|
3445
|
-
|
|
3448
|
+
describe('bundlePolicy', () => {
|
|
3446
3449
|
const FAKE_TURN_URL = 'turns:webex.com:3478';
|
|
3447
3450
|
const FAKE_TURN_USER = 'some-turn-username';
|
|
3448
3451
|
const FAKE_TURN_PASSWORD = 'some-password';
|
|
3449
3452
|
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
3454
|
-
turnServerInfo: {
|
|
3455
|
-
url: FAKE_TURN_URL,
|
|
3456
|
-
username: FAKE_TURN_USER,
|
|
3457
|
-
password: FAKE_TURN_PASSWORD,
|
|
3458
|
-
},
|
|
3459
|
-
turnDiscoverySkippedReason: undefined,
|
|
3460
|
-
});
|
|
3461
|
-
const media = meeting.addMedia({
|
|
3462
|
-
mediaSettings: {},
|
|
3463
|
-
bundlePolicy: 'bundlePolicy-value',
|
|
3464
|
-
});
|
|
3453
|
+
beforeEach(() => {
|
|
3454
|
+
meeting.meetingState = 'ACTIVE';
|
|
3455
|
+
Media.createMediaConnection.resetHistory();
|
|
3465
3456
|
|
|
3466
|
-
|
|
3467
|
-
await media;
|
|
3468
|
-
assert.calledOnce(meeting.roap.doTurnDiscovery);
|
|
3469
|
-
assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
|
|
3470
|
-
assert.calledOnce(Media.createMediaConnection);
|
|
3471
|
-
assert.calledWith(
|
|
3472
|
-
Media.createMediaConnection,
|
|
3473
|
-
false,
|
|
3474
|
-
meeting.getMediaConnectionDebugId(),
|
|
3475
|
-
meeting.id,
|
|
3476
|
-
sinon.match({
|
|
3457
|
+
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
3477
3458
|
turnServerInfo: {
|
|
3478
3459
|
url: FAKE_TURN_URL,
|
|
3479
3460
|
username: FAKE_TURN_USER,
|
|
3480
3461
|
password: FAKE_TURN_PASSWORD,
|
|
3481
3462
|
},
|
|
3482
|
-
|
|
3483
|
-
})
|
|
3484
|
-
);
|
|
3485
|
-
|
|
3463
|
+
turnDiscoverySkippedReason: undefined,
|
|
3464
|
+
});
|
|
3465
|
+
});
|
|
3466
|
+
|
|
3467
|
+
const runCheck = async (bundlePolicy, expectedValue) => {
|
|
3468
|
+
const media = meeting.addMedia({
|
|
3469
|
+
mediaSettings: {},
|
|
3470
|
+
bundlePolicy,
|
|
3471
|
+
});
|
|
3472
|
+
|
|
3473
|
+
assert.exists(media);
|
|
3474
|
+
await media;
|
|
3475
|
+
assert.calledOnce(meeting.roap.doTurnDiscovery);
|
|
3476
|
+
assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
|
|
3477
|
+
assert.calledOnce(Media.createMediaConnection);
|
|
3478
|
+
assert.calledWith(
|
|
3479
|
+
Media.createMediaConnection,
|
|
3480
|
+
false,
|
|
3481
|
+
meeting.getMediaConnectionDebugId(),
|
|
3482
|
+
meeting.id,
|
|
3483
|
+
sinon.match({
|
|
3484
|
+
turnServerInfo: {
|
|
3485
|
+
url: FAKE_TURN_URL,
|
|
3486
|
+
username: FAKE_TURN_USER,
|
|
3487
|
+
password: FAKE_TURN_PASSWORD,
|
|
3488
|
+
},
|
|
3489
|
+
bundlePolicy: expectedValue,
|
|
3490
|
+
})
|
|
3491
|
+
);
|
|
3492
|
+
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
3493
|
+
};
|
|
3494
|
+
|
|
3495
|
+
it('should pass bundlePolicy to createMediaConnection', async () => {
|
|
3496
|
+
await runCheck('max-compat', 'max-compat');
|
|
3497
|
+
});
|
|
3498
|
+
|
|
3499
|
+
it('should pass max-bundle to createMediaConnection if bundlePolicy is not provided', async () => {
|
|
3500
|
+
await runCheck(undefined, 'max-bundle');
|
|
3501
|
+
});
|
|
3486
3502
|
});
|
|
3487
3503
|
|
|
3488
3504
|
it('succeeds even if getDevices() throws', async () => {
|
|
@@ -3795,12 +3811,12 @@ describe('plugin-meetings', () => {
|
|
|
3795
3811
|
id: 'fake locus from mocked join request',
|
|
3796
3812
|
locusUrl: 'fake locus url',
|
|
3797
3813
|
mediaId: 'fake media id',
|
|
3798
|
-
})
|
|
3814
|
+
});
|
|
3799
3815
|
sinon.stub(meeting.meetingRequest, 'joinMeeting').resolves({
|
|
3800
3816
|
headers: {
|
|
3801
3817
|
trackingid: 'fake tracking id',
|
|
3802
|
-
}
|
|
3803
|
-
})
|
|
3818
|
+
},
|
|
3819
|
+
});
|
|
3804
3820
|
await meeting.join({enableMultistream: isMultistream});
|
|
3805
3821
|
});
|
|
3806
3822
|
|
|
@@ -3993,7 +4009,10 @@ describe('plugin-meetings', () => {
|
|
|
3993
4009
|
assert.notCalled(
|
|
3994
4010
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream
|
|
3995
4011
|
);
|
|
3996
|
-
assert.throws(
|
|
4012
|
+
assert.throws(
|
|
4013
|
+
meeting.publishStreams(localStreams),
|
|
4014
|
+
`Attempted to publish microphone stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4015
|
+
);
|
|
3997
4016
|
} else {
|
|
3998
4017
|
assert.calledOnceWithExactly(
|
|
3999
4018
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream,
|
|
@@ -4006,7 +4025,10 @@ describe('plugin-meetings', () => {
|
|
|
4006
4025
|
assert.notCalled(
|
|
4007
4026
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream
|
|
4008
4027
|
);
|
|
4009
|
-
assert.throws(
|
|
4028
|
+
assert.throws(
|
|
4029
|
+
meeting.publishStreams(localStreams),
|
|
4030
|
+
`Attempted to publish camera stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4031
|
+
);
|
|
4010
4032
|
} else {
|
|
4011
4033
|
assert.calledOnceWithExactly(
|
|
4012
4034
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream,
|
|
@@ -4019,7 +4041,10 @@ describe('plugin-meetings', () => {
|
|
|
4019
4041
|
assert.notCalled(
|
|
4020
4042
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream
|
|
4021
4043
|
);
|
|
4022
|
-
assert.throws(
|
|
4044
|
+
assert.throws(
|
|
4045
|
+
meeting.publishStreams(localStreams),
|
|
4046
|
+
`Attempted to publish screenShare audio stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4047
|
+
);
|
|
4023
4048
|
} else {
|
|
4024
4049
|
assert.calledOnceWithExactly(
|
|
4025
4050
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
|
|
@@ -4032,7 +4057,10 @@ describe('plugin-meetings', () => {
|
|
|
4032
4057
|
assert.notCalled(
|
|
4033
4058
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream
|
|
4034
4059
|
);
|
|
4035
|
-
assert.throws(
|
|
4060
|
+
assert.throws(
|
|
4061
|
+
meeting.publishStreams(localStreams),
|
|
4062
|
+
`Attempted to publish screenShare video stream with ended readyState, correlationId=${meeting.correlationId}`
|
|
4063
|
+
);
|
|
4036
4064
|
} else {
|
|
4037
4065
|
assert.calledOnceWithExactly(
|
|
4038
4066
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream,
|
|
@@ -4327,14 +4355,14 @@ describe('plugin-meetings', () => {
|
|
|
4327
4355
|
const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
|
|
4328
4356
|
await meeting.addMedia({audioEnabled: false});
|
|
4329
4357
|
//calling handleDeviceLogging with audioEnaled as true adn videoEnabled as false
|
|
4330
|
-
assert.calledWith(handleDeviceLoggingSpy,false,true);
|
|
4358
|
+
assert.calledWith(handleDeviceLoggingSpy, false, true);
|
|
4331
4359
|
});
|
|
4332
4360
|
|
|
4333
4361
|
it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
|
|
4334
4362
|
const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
|
|
4335
4363
|
await meeting.addMedia({videoEnabled: false});
|
|
4336
4364
|
//calling handleDeviceLogging audioEnabled as true videoEnabled as false
|
|
4337
|
-
assert.calledWith(handleDeviceLoggingSpy,true,false);
|
|
4365
|
+
assert.calledWith(handleDeviceLoggingSpy, true, false);
|
|
4338
4366
|
});
|
|
4339
4367
|
|
|
4340
4368
|
it('addMedia() works correctly when video is disabled with no streams to publish', async () => {
|
|
@@ -4403,12 +4431,11 @@ describe('plugin-meetings', () => {
|
|
|
4403
4431
|
assert.calledTwice(locusMediaRequestStub);
|
|
4404
4432
|
});
|
|
4405
4433
|
|
|
4406
|
-
|
|
4407
4434
|
it('addMedia() works correctly when both shareAudio and shareVideo is disabled with no streams publish', async () => {
|
|
4408
4435
|
const handleDeviceLoggingSpy = sinon.spy(Meeting, 'handleDeviceLogging');
|
|
4409
4436
|
await meeting.addMedia({shareAudioEnabled: false, shareVideoEnabled: false});
|
|
4410
4437
|
//calling handleDeviceLogging with audioEnabled true and videoEnabled as true
|
|
4411
|
-
assert.calledWith(handleDeviceLoggingSpy,true,true);
|
|
4438
|
+
assert.calledWith(handleDeviceLoggingSpy, true, true);
|
|
4412
4439
|
});
|
|
4413
4440
|
|
|
4414
4441
|
describe('publishStreams()/unpublishStreams() calls', () => {
|
|
@@ -6263,14 +6290,22 @@ describe('plugin-meetings', () => {
|
|
|
6263
6290
|
meeting.attrs.meetingInfoProvider = {
|
|
6264
6291
|
fetchMeetingInfo: sinon
|
|
6265
6292
|
.stub()
|
|
6266
|
-
.throws(
|
|
6293
|
+
.throws(
|
|
6294
|
+
new MeetingInfoV2WebinarRegistrationError(403021, FAKE_MEETING_INFO, 'a message')
|
|
6295
|
+
),
|
|
6267
6296
|
};
|
|
6268
6297
|
|
|
6269
|
-
await assert.isRejected(
|
|
6298
|
+
await assert.isRejected(
|
|
6299
|
+
meeting.fetchMeetingInfo({sendCAevents: true}),
|
|
6300
|
+
WebinarRegistrationError
|
|
6301
|
+
);
|
|
6270
6302
|
|
|
6271
6303
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6272
6304
|
assert.equal(meeting.meetingInfoFailureCode, 403021);
|
|
6273
|
-
assert.equal(
|
|
6305
|
+
assert.equal(
|
|
6306
|
+
meeting.meetingInfoFailureReason,
|
|
6307
|
+
MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION
|
|
6308
|
+
);
|
|
6274
6309
|
});
|
|
6275
6310
|
});
|
|
6276
6311
|
|
|
@@ -6985,7 +7020,10 @@ describe('plugin-meetings', () => {
|
|
|
6985
7020
|
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
6986
7021
|
meeting.setCorrelationId(uuid1);
|
|
6987
7022
|
assert.equal(meeting.correlationId, uuid1);
|
|
6988
|
-
assert.deepEqual(meeting.callStateForMetrics, {
|
|
7023
|
+
assert.deepEqual(meeting.callStateForMetrics, {
|
|
7024
|
+
correlationId: uuid1,
|
|
7025
|
+
sessionCorrelationId: '',
|
|
7026
|
+
});
|
|
6989
7027
|
});
|
|
6990
7028
|
});
|
|
6991
7029
|
|
|
@@ -7657,11 +7695,11 @@ describe('plugin-meetings', () => {
|
|
|
7657
7695
|
id: 'stream',
|
|
7658
7696
|
getTracks: () => [{id: 'track', addEventListener: sinon.stub()}],
|
|
7659
7697
|
};
|
|
7660
|
-
const simulateConnectionStateChange = (newState) => {
|
|
7698
|
+
const simulateConnectionStateChange = async (newState) => {
|
|
7661
7699
|
meeting.mediaProperties.webrtcMediaConnection.getConnectionState = sinon
|
|
7662
7700
|
.stub()
|
|
7663
7701
|
.returns(newState);
|
|
7664
|
-
eventListeners[MediaConnectionEventNames.PEER_CONNECTION_STATE_CHANGED]();
|
|
7702
|
+
await eventListeners[MediaConnectionEventNames.PEER_CONNECTION_STATE_CHANGED]();
|
|
7665
7703
|
};
|
|
7666
7704
|
|
|
7667
7705
|
beforeEach(() => {
|
|
@@ -7731,11 +7769,17 @@ describe('plugin-meetings', () => {
|
|
|
7731
7769
|
});
|
|
7732
7770
|
|
|
7733
7771
|
it('should collect ice candidates', () => {
|
|
7734
|
-
eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: 'candidate'});
|
|
7772
|
+
eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: {candidate: 'candidate'}});
|
|
7735
7773
|
|
|
7736
7774
|
assert.equal(meeting.iceCandidatesCount, 1);
|
|
7737
7775
|
});
|
|
7738
7776
|
|
|
7777
|
+
it('should not collect empty ice candidates', () => {
|
|
7778
|
+
eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: {candidate: ''}});
|
|
7779
|
+
|
|
7780
|
+
assert.equal(meeting.iceCandidatesCount, 0);
|
|
7781
|
+
});
|
|
7782
|
+
|
|
7739
7783
|
it('should not collect null ice candidates', () => {
|
|
7740
7784
|
eventListeners[MediaConnectionEventNames.ICE_CANDIDATE]({candidate: null});
|
|
7741
7785
|
|
|
@@ -7917,7 +7961,7 @@ describe('plugin-meetings', () => {
|
|
|
7917
7961
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
7918
7962
|
meeting.reconnectionManager.iceReconnected = sinon.stub().returns(undefined);
|
|
7919
7963
|
meeting.setNetworkStatus = sinon.stub().returns(undefined);
|
|
7920
|
-
meeting.statsAnalyzer = {startAnalyzer: sinon.stub()};
|
|
7964
|
+
meeting.statsAnalyzer = {startAnalyzer: sinon.stub(), stopAnalyzer: sinon.stub()};
|
|
7921
7965
|
meeting.mediaProperties.webrtcMediaConnection = {
|
|
7922
7966
|
// mock the on() method and store all the listeners
|
|
7923
7967
|
on: sinon.stub().callsFake((event, listener) => {
|
|
@@ -7992,10 +8036,10 @@ describe('plugin-meetings', () => {
|
|
|
7992
8036
|
});
|
|
7993
8037
|
|
|
7994
8038
|
describe('CONNECTION_STATE_CHANGED event when state = "Failed"', () => {
|
|
7995
|
-
const mockFailedEvent = () => {
|
|
8039
|
+
const mockFailedEvent = async () => {
|
|
7996
8040
|
meeting.setupMediaConnectionListeners();
|
|
7997
8041
|
|
|
7998
|
-
simulateConnectionStateChange(ConnectionState.Failed);
|
|
8042
|
+
await simulateConnectionStateChange(ConnectionState.Failed);
|
|
7999
8043
|
};
|
|
8000
8044
|
|
|
8001
8045
|
const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
|
|
@@ -8025,6 +8069,22 @@ describe('plugin-meetings', () => {
|
|
|
8025
8069
|
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
8026
8070
|
checkBehavioralMetricSent(true);
|
|
8027
8071
|
});
|
|
8072
|
+
|
|
8073
|
+
it('stop stats analyzer during reconnection ', async () => {
|
|
8074
|
+
meeting.hasMediaConnectionConnectedAtLeastOnce = true;
|
|
8075
|
+
meeting.statsAnalyzer.stopAnalyzer = sinon.stub().resolves();
|
|
8076
|
+
meeting.reconnectionManager = {
|
|
8077
|
+
reconnect: sinon.stub().resolves(),
|
|
8078
|
+
resetReconnectionTimer: () => {}
|
|
8079
|
+
};
|
|
8080
|
+
meeting.currentMediaStatus = {
|
|
8081
|
+
video: true
|
|
8082
|
+
};
|
|
8083
|
+
|
|
8084
|
+
await mockFailedEvent();
|
|
8085
|
+
|
|
8086
|
+
assert.calledOnce(meeting.statsAnalyzer.stopAnalyzer);
|
|
8087
|
+
});
|
|
8028
8088
|
});
|
|
8029
8089
|
|
|
8030
8090
|
describe('should send correct metrics for ROAP_FAILURE event', () => {
|
|
@@ -8885,6 +8945,78 @@ describe('plugin-meetings', () => {
|
|
|
8885
8945
|
);
|
|
8886
8946
|
});
|
|
8887
8947
|
|
|
8948
|
+
it('listens to MEETING_CONTROLS_WEBCAST_UPDATED', async () => {
|
|
8949
|
+
const state = {example: 'value'};
|
|
8950
|
+
|
|
8951
|
+
await meeting.locusInfo.emitScoped(
|
|
8952
|
+
{function: 'test', file: 'test'},
|
|
8953
|
+
LOCUSINFO.EVENTS.CONTROLS_WEBCAST_CHANGED,
|
|
8954
|
+
{state}
|
|
8955
|
+
);
|
|
8956
|
+
|
|
8957
|
+
assert.calledWith(
|
|
8958
|
+
TriggerProxy.trigger,
|
|
8959
|
+
meeting,
|
|
8960
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
8961
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_WEBCAST_UPDATED,
|
|
8962
|
+
{state}
|
|
8963
|
+
);
|
|
8964
|
+
});
|
|
8965
|
+
|
|
8966
|
+
it('listens to MEETING_CONTROLS_MEETING_FULL_UPDATED', async () => {
|
|
8967
|
+
const state = {example: 'value'};
|
|
8968
|
+
|
|
8969
|
+
await meeting.locusInfo.emitScoped(
|
|
8970
|
+
{function: 'test', file: 'test'},
|
|
8971
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_FULL_CHANGED,
|
|
8972
|
+
{state}
|
|
8973
|
+
);
|
|
8974
|
+
|
|
8975
|
+
assert.calledWith(
|
|
8976
|
+
TriggerProxy.trigger,
|
|
8977
|
+
meeting,
|
|
8978
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
8979
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_MEETING_FULL_UPDATED,
|
|
8980
|
+
{state}
|
|
8981
|
+
);
|
|
8982
|
+
});
|
|
8983
|
+
|
|
8984
|
+
it('listens to MEETING_CONTROLS_PRACTICE_SESSION_STATUS_UPDATED', async () => {
|
|
8985
|
+
const state = {example: 'value'};
|
|
8986
|
+
|
|
8987
|
+
await meeting.locusInfo.emitScoped(
|
|
8988
|
+
{function: 'test', file: 'test'},
|
|
8989
|
+
LOCUSINFO.EVENTS.CONTROLS_PRACTICE_SESSION_STATUS_UPDATED,
|
|
8990
|
+
{state}
|
|
8991
|
+
);
|
|
8992
|
+
|
|
8993
|
+
assert.calledWith(
|
|
8994
|
+
TriggerProxy.trigger,
|
|
8995
|
+
meeting,
|
|
8996
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
8997
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_PRACTICE_SESSION_STATUS_UPDATED,
|
|
8998
|
+
{state}
|
|
8999
|
+
);
|
|
9000
|
+
});
|
|
9001
|
+
|
|
9002
|
+
it('listens to MEETING_CONTROLS_STAGE_VIEW_UPDATED', async () => {
|
|
9003
|
+
const state = {example: 'value'};
|
|
9004
|
+
|
|
9005
|
+
await meeting.locusInfo.emitScoped(
|
|
9006
|
+
{function: 'test', file: 'test'},
|
|
9007
|
+
LOCUSINFO.EVENTS.CONTROLS_STAGE_VIEW_UPDATED,
|
|
9008
|
+
{state}
|
|
9009
|
+
);
|
|
9010
|
+
|
|
9011
|
+
assert.calledWith(
|
|
9012
|
+
TriggerProxy.trigger,
|
|
9013
|
+
meeting,
|
|
9014
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
9015
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_STAGE_VIEW_UPDATED,
|
|
9016
|
+
{state}
|
|
9017
|
+
);
|
|
9018
|
+
});
|
|
9019
|
+
|
|
8888
9020
|
it('listens to MEETING_CONTROLS_VIDEO_UPDATED', async () => {
|
|
8889
9021
|
const state = {example: 'value'};
|
|
8890
9022
|
|
|
@@ -8998,12 +9130,6 @@ describe('plugin-meetings', () => {
|
|
|
8998
9130
|
approval: {
|
|
8999
9131
|
url: 'url',
|
|
9000
9132
|
},
|
|
9001
|
-
webcast: {
|
|
9002
|
-
url: 'url',
|
|
9003
|
-
},
|
|
9004
|
-
webinarAttendeesSearching: {
|
|
9005
|
-
url: 'url',
|
|
9006
|
-
},
|
|
9007
9133
|
},
|
|
9008
9134
|
};
|
|
9009
9135
|
|
|
@@ -9017,10 +9143,6 @@ describe('plugin-meetings', () => {
|
|
|
9017
9143
|
meeting.simultaneousInterpretation = {
|
|
9018
9144
|
approvalUrlUpdate: sinon.stub().returns(undefined),
|
|
9019
9145
|
};
|
|
9020
|
-
meeting.webinar = {
|
|
9021
|
-
webcastUrlUpdate: sinon.stub().returns(undefined),
|
|
9022
|
-
webinarAttendeesSearchingUrlUpdate: sinon.stub().returns(undefined),
|
|
9023
|
-
};
|
|
9024
9146
|
|
|
9025
9147
|
meeting.locusInfo.emit(
|
|
9026
9148
|
{function: 'test', file: 'test'},
|
|
@@ -9040,19 +9162,37 @@ describe('plugin-meetings', () => {
|
|
|
9040
9162
|
meeting.simultaneousInterpretation.approvalUrlUpdate,
|
|
9041
9163
|
newLocusServices.services.approval.url
|
|
9042
9164
|
);
|
|
9043
|
-
assert.calledWith(
|
|
9044
|
-
meeting.webinar.webcastUrlUpdate,
|
|
9045
|
-
newLocusServices.services.webcast.url
|
|
9046
|
-
);
|
|
9047
|
-
assert.calledWith(
|
|
9048
|
-
meeting.webinar.webinarAttendeesSearchingUrlUpdate,
|
|
9049
|
-
newLocusServices.services.webinarAttendeesSearching.url
|
|
9050
|
-
);
|
|
9051
9165
|
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
9052
9166
|
done();
|
|
9053
9167
|
});
|
|
9054
9168
|
});
|
|
9055
9169
|
|
|
9170
|
+
describe('#setUpLocusResourcesListener', () => {
|
|
9171
|
+
it('listens to the locus resources update event', (done) => {
|
|
9172
|
+
const newLocusResources = {
|
|
9173
|
+
resources: {
|
|
9174
|
+
webcastInstance: {
|
|
9175
|
+
url: 'url',
|
|
9176
|
+
},
|
|
9177
|
+
},
|
|
9178
|
+
};
|
|
9179
|
+
|
|
9180
|
+
meeting.webinar = {
|
|
9181
|
+
updateWebcastUrl: sinon.stub().returns(undefined),
|
|
9182
|
+
};
|
|
9183
|
+
|
|
9184
|
+
meeting.locusInfo.emit(
|
|
9185
|
+
{function: 'test', file: 'test'},
|
|
9186
|
+
'LINKS_RESOURCES',
|
|
9187
|
+
newLocusResources
|
|
9188
|
+
);
|
|
9189
|
+
|
|
9190
|
+
assert.calledWith(meeting.webinar.updateWebcastUrl, newLocusResources);
|
|
9191
|
+
|
|
9192
|
+
done();
|
|
9193
|
+
});
|
|
9194
|
+
});
|
|
9195
|
+
|
|
9056
9196
|
describe('#setUpLocusInfoMediaInactiveListener', () => {
|
|
9057
9197
|
it('listens to disconnect due to un activity ', (done) => {
|
|
9058
9198
|
TriggerProxy.trigger.reset();
|
|
@@ -12205,14 +12345,10 @@ describe('plugin-meetings', () => {
|
|
|
12205
12345
|
const testEmit = async (unmuteAllowed) => {
|
|
12206
12346
|
meeting.audio = {
|
|
12207
12347
|
handleServerLocalUnmuteRequired: sinon.stub(),
|
|
12208
|
-
}
|
|
12209
|
-
await meeting.locusInfo.emitScoped(
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
{
|
|
12213
|
-
unmuteAllowed,
|
|
12214
|
-
}
|
|
12215
|
-
);
|
|
12348
|
+
};
|
|
12349
|
+
await meeting.locusInfo.emitScoped({}, LOCUSINFO.EVENTS.LOCAL_UNMUTE_REQUIRED, {
|
|
12350
|
+
unmuteAllowed,
|
|
12351
|
+
});
|
|
12216
12352
|
|
|
12217
12353
|
assert.calledWith(
|
|
12218
12354
|
TriggerProxy.trigger,
|
|
@@ -12228,7 +12364,11 @@ describe('plugin-meetings', () => {
|
|
|
12228
12364
|
},
|
|
12229
12365
|
}
|
|
12230
12366
|
);
|
|
12231
|
-
assert.calledOnceWithExactly(
|
|
12367
|
+
assert.calledOnceWithExactly(
|
|
12368
|
+
meeting.audio.handleServerLocalUnmuteRequired,
|
|
12369
|
+
meeting,
|
|
12370
|
+
unmuteAllowed
|
|
12371
|
+
);
|
|
12232
12372
|
};
|
|
12233
12373
|
|
|
12234
12374
|
[true, false].forEach((unmuteAllowed) => {
|
|
@@ -2077,6 +2077,21 @@ describe('plugin-meetings', () => {
|
|
|
2077
2077
|
]);
|
|
2078
2078
|
});
|
|
2079
2079
|
|
|
2080
|
+
it('should handle failure to get user information if scopes are insufficient', async () => {
|
|
2081
|
+
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
2082
|
+
Object.assign(webex.people, {
|
|
2083
|
+
_getMe: sinon.stub().returns(Promise.reject()),
|
|
2084
|
+
});
|
|
2085
|
+
|
|
2086
|
+
await webex.meetings.fetchUserPreferredWebexSite();
|
|
2087
|
+
|
|
2088
|
+
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
2089
|
+
assert.calledOnceWithExactly(
|
|
2090
|
+
loggerProxySpy,
|
|
2091
|
+
'Failed to retrieve user information. No preferredWebexSite will be set'
|
|
2092
|
+
);
|
|
2093
|
+
});
|
|
2094
|
+
|
|
2080
2095
|
const setup = ({me = { type: 'validuser'}, user} = {}) => {
|
|
2081
2096
|
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
2082
2097
|
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
@@ -2093,7 +2108,7 @@ describe('plugin-meetings', () => {
|
|
|
2093
2108
|
|
|
2094
2109
|
Object.assign(webex.people, {
|
|
2095
2110
|
_getMe: sinon.stub().returns(Promise.resolve(me)),
|
|
2096
|
-
|
|
2111
|
+
});
|
|
2097
2112
|
};
|
|
2098
2113
|
|
|
2099
2114
|
it('should not call request.getMeetingPreferences if user is a guest', async () => {
|
|
@@ -660,17 +660,20 @@ describe('plugin-meetings', () => {
|
|
|
660
660
|
resultPromise,
|
|
661
661
|
spies,
|
|
662
662
|
expectedRequestingMemberId,
|
|
663
|
-
expectedLocusUrl
|
|
663
|
+
expectedLocusUrl,
|
|
664
|
+
expectedRoles,
|
|
664
665
|
) => {
|
|
665
666
|
await assert.isFulfilled(resultPromise);
|
|
666
667
|
assert.calledOnceWithExactly(
|
|
667
668
|
spies.generateLowerAllHandsMemberOptions,
|
|
668
669
|
expectedRequestingMemberId,
|
|
669
|
-
expectedLocusUrl
|
|
670
|
+
expectedLocusUrl,
|
|
671
|
+
expectedRoles,
|
|
670
672
|
);
|
|
671
673
|
assert.calledOnceWithExactly(spies.lowerAllHandsMember, {
|
|
672
674
|
requestingParticipantId: expectedRequestingMemberId,
|
|
673
675
|
locusUrl: expectedLocusUrl,
|
|
676
|
+
...(expectedRoles !== undefined && { roles: expectedRoles })
|
|
674
677
|
});
|
|
675
678
|
assert.strictEqual(resultPromise, spies.lowerAllHandsMember.getCall(0).returnValue);
|
|
676
679
|
};
|
|
@@ -707,6 +710,26 @@ describe('plugin-meetings', () => {
|
|
|
707
710
|
|
|
708
711
|
await checkValid(resultPromise, spies, requestingMemberId, url1);
|
|
709
712
|
});
|
|
713
|
+
|
|
714
|
+
it('should make the correct request when called with valid requestingMemberId and roles', async () => {
|
|
715
|
+
const requestingMemberId = 'test-member-id';
|
|
716
|
+
const roles = ['panelist', 'attendee'];
|
|
717
|
+
const { members, spies } = setup('test-locus-url');
|
|
718
|
+
|
|
719
|
+
const resultPromise = members.lowerAllHands(requestingMemberId, roles);
|
|
720
|
+
|
|
721
|
+
await checkValid(resultPromise, spies, requestingMemberId, 'test-locus-url', roles);
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('should handle an empty roles array correctly', async () => {
|
|
725
|
+
const requestingMemberId = 'test-member-id';
|
|
726
|
+
const roles = [];
|
|
727
|
+
const { members, spies } = setup('test-locus-url');
|
|
728
|
+
|
|
729
|
+
const resultPromise = members.lowerAllHands(requestingMemberId, roles);
|
|
730
|
+
|
|
731
|
+
await checkValid(resultPromise, spies, requestingMemberId, 'test-locus-url', roles);
|
|
732
|
+
});
|
|
710
733
|
});
|
|
711
734
|
|
|
712
735
|
describe('#editDisplayName', () => {
|
|
@@ -225,7 +225,7 @@ describe('plugin-meetings', () => {
|
|
|
225
225
|
});
|
|
226
226
|
|
|
227
227
|
describe('#assignRolesMember', () => {
|
|
228
|
-
it('sends a PATCH to the locus endpoint', async () => {
|
|
228
|
+
it('sends a assignRolesMember PATCH to the locus endpoint', async () => {
|
|
229
229
|
const locusUrl = url1;
|
|
230
230
|
const memberId = 'test1';
|
|
231
231
|
const roles = [
|
|
@@ -255,7 +255,7 @@ describe('plugin-meetings', () => {
|
|
|
255
255
|
});
|
|
256
256
|
|
|
257
257
|
describe('#raiseHand', () => {
|
|
258
|
-
it('sends a PATCH to the locus endpoint', async () => {
|
|
258
|
+
it('sends a raiseOrLowerHandMember PATCH to the locus endpoint', async () => {
|
|
259
259
|
const locusUrl = url1;
|
|
260
260
|
const memberId = 'test1';
|
|
261
261
|
|
|
@@ -319,7 +319,7 @@ describe('plugin-meetings', () => {
|
|
|
319
319
|
assert.strictEqual(result, requestResponse);
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
it('sends a PATCH to the locus endpoint', async () => {
|
|
322
|
+
it('sends a lowerAllHandsMember PATCH to the locus endpoint', async () => {
|
|
323
323
|
const locusUrl = url1;
|
|
324
324
|
const memberId = 'test1';
|
|
325
325
|
|
|
@@ -348,6 +348,40 @@ describe('plugin-meetings', () => {
|
|
|
348
348
|
},
|
|
349
349
|
});
|
|
350
350
|
});
|
|
351
|
+
|
|
352
|
+
it('sends a lowerAllHandsMember PATCH to the locus endpoint with roles', async () => {
|
|
353
|
+
const locusUrl = url1;
|
|
354
|
+
const memberId = 'test1';
|
|
355
|
+
const roles = ['attendee'];
|
|
356
|
+
|
|
357
|
+
const options = {
|
|
358
|
+
requestingParticipantId: memberId,
|
|
359
|
+
locusUrl,
|
|
360
|
+
roles,
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const getRequestParamsSpy = sandbox.spy(membersUtil, 'getLowerAllHandsMemberRequestParams');
|
|
364
|
+
|
|
365
|
+
await membersRequest.lowerAllHandsMember(options);
|
|
366
|
+
|
|
367
|
+
assert.calledOnceWithExactly(getRequestParamsSpy, {
|
|
368
|
+
requestingParticipantId: memberId,
|
|
369
|
+
locusUrl: url1,
|
|
370
|
+
roles: ['attendee'],
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
checkRequest({
|
|
374
|
+
method: 'PATCH',
|
|
375
|
+
uri: `${locusUrl}/controls`,
|
|
376
|
+
body: {
|
|
377
|
+
hand: {
|
|
378
|
+
raised: false,
|
|
379
|
+
roles: ['attendee'],
|
|
380
|
+
},
|
|
381
|
+
requestingParticipantId: memberId,
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
});
|
|
351
385
|
});
|
|
352
386
|
|
|
353
387
|
describe('#editDisplayName', () => {
|
|
@@ -101,7 +101,7 @@ describe('plugin-meetings', () => {
|
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
describe('#generateLowerAllHandsMemberOptions', () => {
|
|
104
|
-
it('returns the correct options', () => {
|
|
104
|
+
it('returns the correct options without roles', () => {
|
|
105
105
|
const requestingParticipantId = 'test';
|
|
106
106
|
const locusUrl = 'urlTest1';
|
|
107
107
|
|
|
@@ -113,6 +113,20 @@ describe('plugin-meetings', () => {
|
|
|
113
113
|
}
|
|
114
114
|
);
|
|
115
115
|
});
|
|
116
|
+
it('returns the correct options with roles', () => {
|
|
117
|
+
const requestingParticipantId = 'test';
|
|
118
|
+
const locusUrl = 'urlTest1';
|
|
119
|
+
const roles = ['panelist'];
|
|
120
|
+
|
|
121
|
+
assert.deepEqual(
|
|
122
|
+
MembersUtil.generateLowerAllHandsMemberOptions(requestingParticipantId, locusUrl, roles),
|
|
123
|
+
{
|
|
124
|
+
requestingParticipantId,
|
|
125
|
+
locusUrl,
|
|
126
|
+
roles,
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
});
|
|
116
130
|
});
|
|
117
131
|
describe('#generateEditDisplayNameMemberOptions', () => {
|
|
118
132
|
it('returns the correct options', () => {
|