@webex/plugin-meetings 3.8.0-next.2 → 3.8.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +4 -4
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +1 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/meeting/index.js +69 -4
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +21 -5
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/util.js +2 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +1 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +40 -8
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +52 -8
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +70 -45
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +14 -0
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/recording-controller/util.js +5 -5
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/meeting/index.d.ts +30 -0
- package/dist/types/multistream/remoteMediaManager.d.ts +10 -1
- package/dist/types/reachability/clusterReachability.d.ts +13 -1
- package/dist/types/reachability/index.d.ts +2 -1
- package/dist/types/reachability/reachability.types.d.ts +5 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/config.ts +1 -0
- package/src/constants.ts +1 -0
- package/src/interpretation/index.ts +3 -3
- package/src/locus-info/controlsUtils.ts +2 -2
- package/src/meeting/index.ts +66 -3
- package/src/meeting/locusMediaRequest.ts +27 -4
- package/src/meeting/util.ts +1 -1
- package/src/meetings/index.ts +1 -1
- package/src/multistream/remoteMediaManager.ts +32 -10
- package/src/reachability/clusterReachability.ts +47 -1
- package/src/reachability/index.ts +15 -0
- package/src/reachability/reachability.types.ts +6 -0
- package/src/recording-controller/util.ts +17 -13
- package/test/unit/spec/interpretation/index.ts +39 -1
- package/test/unit/spec/locus-info/controlsUtils.js +8 -0
- package/test/unit/spec/meeting/index.js +185 -108
- package/test/unit/spec/meeting/locusMediaRequest.ts +96 -58
- package/test/unit/spec/meeting/utils.js +44 -0
- package/test/unit/spec/meetings/index.js +13 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +397 -118
- package/test/unit/spec/reachability/clusterReachability.ts +47 -1
- package/test/unit/spec/reachability/index.ts +12 -0
|
@@ -22,16 +22,54 @@ describe('plugin-meetings', () => {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
describe('#initialize', () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
interpretation.querySupportLanguages = sinon.stub();
|
|
27
|
+
interpretation.set({
|
|
28
|
+
canManageInterpreters: undefined,
|
|
29
|
+
hostSIEnabled: undefined,
|
|
30
|
+
locusUrl: undefined
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
interpretation.querySupportLanguages.reset();
|
|
36
|
+
});
|
|
37
|
+
|
|
25
38
|
it('creates SimultaneousInterpretation as expected', () => {
|
|
26
39
|
assert.equal(interpretation.namespace, 'Meetings');
|
|
27
40
|
});
|
|
28
41
|
it('call querySupportLanguages correctly when meet the conditions', () => {
|
|
29
|
-
interpretation.querySupportLanguages = sinon.stub();
|
|
30
42
|
interpretation.set({
|
|
31
43
|
canManageInterpreters: true,
|
|
44
|
+
hostSIEnabled: true,
|
|
45
|
+
locusUrl: "MOCK_LOCUS_URL"
|
|
32
46
|
});
|
|
33
47
|
assert.called(interpretation.querySupportLanguages);
|
|
34
48
|
});
|
|
49
|
+
|
|
50
|
+
it('does not call querySupportLanguages when canManageInterpreters is not set', () => {
|
|
51
|
+
interpretation.set({
|
|
52
|
+
hostSIEnabled: true,
|
|
53
|
+
locusUrl: "MOCK_LOCUS_URL"
|
|
54
|
+
});
|
|
55
|
+
assert.notCalled(interpretation.querySupportLanguages);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('does not call querySupportLanguages when hostSIEnabled is not set', () => {
|
|
59
|
+
interpretation.set({
|
|
60
|
+
canManageInterpreters: true,
|
|
61
|
+
locusUrl: "MOCK_LOCUS_URL"
|
|
62
|
+
});
|
|
63
|
+
assert.notCalled(interpretation.querySupportLanguages);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('does not call querySupportLanguages when locusUrl is not set', () => {
|
|
67
|
+
interpretation.set({
|
|
68
|
+
canManageInterpreters: true,
|
|
69
|
+
hostSIEnabled: true,
|
|
70
|
+
});
|
|
71
|
+
assert.notCalled(interpretation.querySupportLanguages);
|
|
72
|
+
});
|
|
35
73
|
});
|
|
36
74
|
|
|
37
75
|
describe('#cleanUp', () => {
|
|
@@ -269,6 +269,14 @@ describe('plugin-meetings', () => {
|
|
|
269
269
|
assert.equal(updates.hasPracticeSessionEnabledChanged, true);
|
|
270
270
|
});
|
|
271
271
|
|
|
272
|
+
it('returns hasPracticeSessionEnabledChanged = false when enabled is false and previous state is false', () => {
|
|
273
|
+
const newControls = {practiceSession: {enabled: false}};
|
|
274
|
+
|
|
275
|
+
const {updates} = ControlsUtils.getControls(defaultControls, newControls);
|
|
276
|
+
|
|
277
|
+
assert.equal(updates.hasPracticeSessionEnabledChanged, false);
|
|
278
|
+
});
|
|
279
|
+
|
|
272
280
|
it('returns hasEntryExitToneChanged = true when mode changed', () => {
|
|
273
281
|
const newControls = {
|
|
274
282
|
entryExitTone: {
|
|
@@ -93,13 +93,14 @@ import CaptchaError from '../../../../src/common/errors/captcha-error';
|
|
|
93
93
|
import PermissionError from '../../../../src/common/errors/permission';
|
|
94
94
|
import JoinWebinarError from '../../../../src/common/errors/join-webinar-error';
|
|
95
95
|
import IntentToJoinError from '../../../../src/common/errors/intent-to-join';
|
|
96
|
-
import MultistreamNotSupportedError from '../../../../src/common/errors/multistream-not-supported-error'
|
|
96
|
+
import MultistreamNotSupportedError from '../../../../src/common/errors/multistream-not-supported-error';
|
|
97
97
|
import testUtils from '../../../utils/testUtils';
|
|
98
98
|
import {
|
|
99
99
|
MeetingInfoV2CaptchaError,
|
|
100
100
|
MeetingInfoV2PasswordError,
|
|
101
101
|
MeetingInfoV2PolicyError,
|
|
102
|
-
MeetingInfoV2JoinWebinarError,
|
|
102
|
+
MeetingInfoV2JoinWebinarError,
|
|
103
|
+
MeetingInfoV2JoinForbiddenError,
|
|
103
104
|
} from '../../../../src/meeting-info/meeting-info-v2';
|
|
104
105
|
import {
|
|
105
106
|
DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
@@ -115,7 +116,8 @@ import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
|
|
|
115
116
|
|
|
116
117
|
import {EVENT_TRIGGERS as VOICEAEVENTS} from '@webex/internal-plugin-voicea';
|
|
117
118
|
import { createBrbState } from '@webex/plugin-meetings/src/meeting/brbState';
|
|
118
|
-
import JoinForbiddenError
|
|
119
|
+
import JoinForbiddenError from '../../../../src/common/errors/join-forbidden-error';
|
|
120
|
+
import { EventEmitter } from 'stream';
|
|
119
121
|
|
|
120
122
|
describe('plugin-meetings', () => {
|
|
121
123
|
const logger = {
|
|
@@ -208,6 +210,8 @@ describe('plugin-meetings', () => {
|
|
|
208
210
|
let membersSpy;
|
|
209
211
|
let meetingRequestSpy;
|
|
210
212
|
let correlationId;
|
|
213
|
+
let isoLocalClientMeetingJoinTime;
|
|
214
|
+
let uploadEvent;
|
|
211
215
|
|
|
212
216
|
beforeEach(() => {
|
|
213
217
|
webex = new MockWebex({
|
|
@@ -277,6 +281,8 @@ describe('plugin-meetings', () => {
|
|
|
277
281
|
test4 = `test4-${uuid.v4()}`;
|
|
278
282
|
testDestination = `testDestination-${uuid.v4()}`;
|
|
279
283
|
correlationId = uuid.v4();
|
|
284
|
+
uploadEvent = new EventEmitter();
|
|
285
|
+
uploadEvent.addListener('progress', () => {})
|
|
280
286
|
|
|
281
287
|
meeting = new Meeting(
|
|
282
288
|
{
|
|
@@ -667,7 +673,7 @@ describe('plugin-meetings', () => {
|
|
|
667
673
|
beforeEach(() => {
|
|
668
674
|
meeting.join = sinon.stub().callsFake((joinOptions) => {
|
|
669
675
|
meeting.isMultistream = joinOptions.enableMultistream;
|
|
670
|
-
return Promise.resolve(fakeJoinResult)
|
|
676
|
+
return Promise.resolve(fakeJoinResult);
|
|
671
677
|
});
|
|
672
678
|
addMediaInternalStub = sinon
|
|
673
679
|
.stub(meeting, 'addMediaInternal')
|
|
@@ -1070,7 +1076,11 @@ describe('plugin-meetings', () => {
|
|
|
1070
1076
|
mediaOptions,
|
|
1071
1077
|
});
|
|
1072
1078
|
|
|
1073
|
-
assert.deepEqual(result, {
|
|
1079
|
+
assert.deepEqual(result, {
|
|
1080
|
+
join: fakeJoinResult,
|
|
1081
|
+
media: undefined,
|
|
1082
|
+
multistreamEnabled: false,
|
|
1083
|
+
});
|
|
1074
1084
|
|
|
1075
1085
|
assert.calledOnce(meeting.join);
|
|
1076
1086
|
|
|
@@ -1174,7 +1184,10 @@ describe('plugin-meetings', () => {
|
|
|
1174
1184
|
type: addMediaError.name,
|
|
1175
1185
|
}
|
|
1176
1186
|
);
|
|
1177
|
-
assert.calledOnceWithExactly(meeting.leave, {
|
|
1187
|
+
assert.calledOnceWithExactly(meeting.leave, {
|
|
1188
|
+
resourceId: undefined,
|
|
1189
|
+
reason: 'joinWithMedia failure',
|
|
1190
|
+
});
|
|
1178
1191
|
});
|
|
1179
1192
|
});
|
|
1180
1193
|
|
|
@@ -1680,10 +1693,6 @@ describe('plugin-meetings', () => {
|
|
|
1680
1693
|
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
|
|
1681
1694
|
});
|
|
1682
1695
|
|
|
1683
|
-
afterEach(() => {
|
|
1684
|
-
assert.exists(meeting.isoLocalClientMeetingJoinTime);
|
|
1685
|
-
});
|
|
1686
|
-
|
|
1687
1696
|
it('should join the meeting and return promise', async () => {
|
|
1688
1697
|
const join = meeting.join({pstnAudioType: 'dial-in'});
|
|
1689
1698
|
meeting.config.enableAutomaticLLM = true;
|
|
@@ -3550,18 +3559,18 @@ describe('plugin-meetings', () => {
|
|
|
3550
3559
|
it('counts the number of members that are in the meeting for MEDIA_QUALITY event', async () => {
|
|
3551
3560
|
let fakeMembersCollection = {
|
|
3552
3561
|
members: {
|
|
3553
|
-
member1: {
|
|
3554
|
-
member2: {
|
|
3555
|
-
member3: {
|
|
3562
|
+
member1: {isInMeeting: true},
|
|
3563
|
+
member2: {isInMeeting: true},
|
|
3564
|
+
member3: {isInMeeting: false},
|
|
3556
3565
|
},
|
|
3557
3566
|
};
|
|
3558
|
-
sinon.stub(meeting, 'getMembers').returns({
|
|
3559
|
-
const fakeData = {
|
|
3567
|
+
sinon.stub(meeting, 'getMembers').returns({membersCollection: fakeMembersCollection});
|
|
3568
|
+
const fakeData = {intervalMetadata: {}, networkType: 'wifi'};
|
|
3560
3569
|
|
|
3561
3570
|
statsAnalyzerStub.emit(
|
|
3562
|
-
{
|
|
3571
|
+
{file: 'test', function: 'test'},
|
|
3563
3572
|
StatsAnalyzerEventNames.MEDIA_QUALITY,
|
|
3564
|
-
{
|
|
3573
|
+
{data: fakeData}
|
|
3565
3574
|
);
|
|
3566
3575
|
|
|
3567
3576
|
assert.calledWithMatch(webex.internal.newMetrics.submitMQE, {
|
|
@@ -3570,15 +3579,17 @@ describe('plugin-meetings', () => {
|
|
|
3570
3579
|
meetingId: meeting.id,
|
|
3571
3580
|
},
|
|
3572
3581
|
payload: {
|
|
3573
|
-
intervals: [
|
|
3582
|
+
intervals: [
|
|
3583
|
+
sinon.match.has('intervalMetadata', sinon.match.has('meetingUserCount', 2)),
|
|
3584
|
+
],
|
|
3574
3585
|
},
|
|
3575
3586
|
});
|
|
3576
3587
|
fakeMembersCollection.members.member2.isInMeeting = false;
|
|
3577
3588
|
|
|
3578
3589
|
statsAnalyzerStub.emit(
|
|
3579
|
-
{
|
|
3590
|
+
{file: 'test', function: 'test'},
|
|
3580
3591
|
StatsAnalyzerEventNames.MEDIA_QUALITY,
|
|
3581
|
-
{
|
|
3592
|
+
{data: fakeData}
|
|
3582
3593
|
);
|
|
3583
3594
|
|
|
3584
3595
|
assert.calledWithMatch(webex.internal.newMetrics.submitMQE, {
|
|
@@ -3587,7 +3598,9 @@ describe('plugin-meetings', () => {
|
|
|
3587
3598
|
meetingId: meeting.id,
|
|
3588
3599
|
},
|
|
3589
3600
|
payload: {
|
|
3590
|
-
intervals: [
|
|
3601
|
+
intervals: [
|
|
3602
|
+
sinon.match.has('intervalMetadata', sinon.match.has('meetingUserCount', 1)),
|
|
3603
|
+
],
|
|
3591
3604
|
},
|
|
3592
3605
|
});
|
|
3593
3606
|
});
|
|
@@ -3842,7 +3855,6 @@ describe('plugin-meetings', () => {
|
|
|
3842
3855
|
});
|
|
3843
3856
|
|
|
3844
3857
|
describe('when in a multistream meeting', () => {
|
|
3845
|
-
|
|
3846
3858
|
beforeEach(() => {
|
|
3847
3859
|
meeting.isMultistream = true;
|
|
3848
3860
|
});
|
|
@@ -3853,7 +3865,7 @@ describe('plugin-meetings', () => {
|
|
|
3853
3865
|
await brbResult;
|
|
3854
3866
|
assert.exists(brbResult.then);
|
|
3855
3867
|
assert.calledOnce(meeting.brbState.enable);
|
|
3856
|
-
})
|
|
3868
|
+
});
|
|
3857
3869
|
|
|
3858
3870
|
it('should disable #beRightBack and return a promise', async () => {
|
|
3859
3871
|
const brbResult = meeting.beRightBack(false);
|
|
@@ -3861,7 +3873,7 @@ describe('plugin-meetings', () => {
|
|
|
3861
3873
|
await brbResult;
|
|
3862
3874
|
assert.exists(brbResult.then);
|
|
3863
3875
|
assert.calledOnce(meeting.brbState.enable);
|
|
3864
|
-
})
|
|
3876
|
+
});
|
|
3865
3877
|
|
|
3866
3878
|
it('should throw an error and reject the promise if setBrb fails', async () => {
|
|
3867
3879
|
const error = new Error('setBrb failed');
|
|
@@ -3874,7 +3886,7 @@ describe('plugin-meetings', () => {
|
|
|
3874
3886
|
assert.equal(err.message, 'setBrb failed');
|
|
3875
3887
|
assert.isRejected((Promise.reject()));
|
|
3876
3888
|
}
|
|
3877
|
-
})
|
|
3889
|
+
});
|
|
3878
3890
|
});
|
|
3879
3891
|
});
|
|
3880
3892
|
|
|
@@ -4006,7 +4018,7 @@ describe('plugin-meetings', () => {
|
|
|
4006
4018
|
initiateOffer: sinon.stub().resolves({}),
|
|
4007
4019
|
update: sinon.stub().resolves({}),
|
|
4008
4020
|
on: sinon.stub(),
|
|
4009
|
-
roapMessageReceived: sinon.stub()
|
|
4021
|
+
roapMessageReceived: sinon.stub(),
|
|
4010
4022
|
};
|
|
4011
4023
|
|
|
4012
4024
|
fakeMultistreamRoapMediaConnection = {
|
|
@@ -4035,7 +4047,7 @@ describe('plugin-meetings', () => {
|
|
|
4035
4047
|
|
|
4036
4048
|
locusMediaRequestStub = sinon
|
|
4037
4049
|
.stub(WebexPlugin.prototype, 'request')
|
|
4038
|
-
.resolves({body: {locus: {fullState: {}}}});
|
|
4050
|
+
.resolves({body: {locus: {fullState: {}}}, upload: sinon.match.instanceOf(EventEmitter), download: sinon.match.instanceOf(EventEmitter)});
|
|
4039
4051
|
|
|
4040
4052
|
// setup some things and mocks so that the call to join() works
|
|
4041
4053
|
// (we need to call join() because it creates the LocusMediaRequest instance
|
|
@@ -4144,6 +4156,8 @@ describe('plugin-meetings', () => {
|
|
|
4144
4156
|
id: 'fake clientMediaPreferences',
|
|
4145
4157
|
},
|
|
4146
4158
|
},
|
|
4159
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
|
4160
|
+
download: sinon.match.instanceOf(EventEmitter),
|
|
4147
4161
|
});
|
|
4148
4162
|
};
|
|
4149
4163
|
|
|
@@ -4171,6 +4185,8 @@ describe('plugin-meetings', () => {
|
|
|
4171
4185
|
},
|
|
4172
4186
|
],
|
|
4173
4187
|
},
|
|
4188
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
|
4189
|
+
download: sinon.match.instanceOf(EventEmitter),
|
|
4174
4190
|
});
|
|
4175
4191
|
};
|
|
4176
4192
|
|
|
@@ -4195,6 +4211,8 @@ describe('plugin-meetings', () => {
|
|
|
4195
4211
|
respOnlySdp: true,
|
|
4196
4212
|
usingResource: null,
|
|
4197
4213
|
},
|
|
4214
|
+
upload: sinon.match.instanceOf(EventEmitter),
|
|
4215
|
+
download: sinon.match.instanceOf(EventEmitter),
|
|
4198
4216
|
});
|
|
4199
4217
|
};
|
|
4200
4218
|
|
|
@@ -6337,7 +6355,10 @@ describe('plugin-meetings', () => {
|
|
|
6337
6355
|
.throws(new MeetingInfoV2JoinForbiddenError(403003, FAKE_MEETING_INFO)),
|
|
6338
6356
|
};
|
|
6339
6357
|
|
|
6340
|
-
await assert.isRejected(
|
|
6358
|
+
await assert.isRejected(
|
|
6359
|
+
meeting.fetchMeetingInfo({sendCAevents: true}),
|
|
6360
|
+
JoinForbiddenError
|
|
6361
|
+
);
|
|
6341
6362
|
|
|
6342
6363
|
assert.calledWith(
|
|
6343
6364
|
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
@@ -6353,10 +6374,7 @@ describe('plugin-meetings', () => {
|
|
|
6353
6374
|
|
|
6354
6375
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6355
6376
|
assert.equal(meeting.meetingInfoFailureCode, 403003);
|
|
6356
|
-
assert.equal(
|
|
6357
|
-
meeting.meetingInfoFailureReason,
|
|
6358
|
-
MEETING_INFO_FAILURE_REASON.NOT_REACH_JBH
|
|
6359
|
-
);
|
|
6377
|
+
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NOT_REACH_JBH);
|
|
6360
6378
|
assert.equal(meeting.requiredCaptcha, null);
|
|
6361
6379
|
});
|
|
6362
6380
|
|
|
@@ -6733,15 +6751,10 @@ describe('plugin-meetings', () => {
|
|
|
6733
6751
|
meeting.attrs.meetingInfoProvider = {
|
|
6734
6752
|
fetchMeetingInfo: sinon
|
|
6735
6753
|
.stub()
|
|
6736
|
-
.throws(
|
|
6737
|
-
new MeetingInfoV2JoinWebinarError(403021, FAKE_MEETING_INFO, 'a message')
|
|
6738
|
-
),
|
|
6754
|
+
.throws(new MeetingInfoV2JoinWebinarError(403021, FAKE_MEETING_INFO, 'a message')),
|
|
6739
6755
|
};
|
|
6740
6756
|
|
|
6741
|
-
await assert.isRejected(
|
|
6742
|
-
meeting.fetchMeetingInfo({sendCAevents: true}),
|
|
6743
|
-
JoinWebinarError
|
|
6744
|
-
);
|
|
6757
|
+
await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), JoinWebinarError);
|
|
6745
6758
|
|
|
6746
6759
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6747
6760
|
assert.equal(
|
|
@@ -6756,15 +6769,10 @@ describe('plugin-meetings', () => {
|
|
|
6756
6769
|
meeting.attrs.meetingInfoProvider = {
|
|
6757
6770
|
fetchMeetingInfo: sinon
|
|
6758
6771
|
.stub()
|
|
6759
|
-
.throws(
|
|
6760
|
-
new MeetingInfoV2JoinWebinarError(403026, FAKE_MEETING_INFO, 'a message')
|
|
6761
|
-
),
|
|
6772
|
+
.throws(new MeetingInfoV2JoinWebinarError(403026, FAKE_MEETING_INFO, 'a message')),
|
|
6762
6773
|
};
|
|
6763
6774
|
|
|
6764
|
-
await assert.isRejected(
|
|
6765
|
-
meeting.fetchMeetingInfo({sendCAevents: true}),
|
|
6766
|
-
JoinWebinarError
|
|
6767
|
-
);
|
|
6775
|
+
await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), JoinWebinarError);
|
|
6768
6776
|
|
|
6769
6777
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6770
6778
|
assert.equal(
|
|
@@ -6779,15 +6787,10 @@ describe('plugin-meetings', () => {
|
|
|
6779
6787
|
meeting.attrs.meetingInfoProvider = {
|
|
6780
6788
|
fetchMeetingInfo: sinon
|
|
6781
6789
|
.stub()
|
|
6782
|
-
.throws(
|
|
6783
|
-
new MeetingInfoV2JoinWebinarError(403037, FAKE_MEETING_INFO, 'a message')
|
|
6784
|
-
),
|
|
6790
|
+
.throws(new MeetingInfoV2JoinWebinarError(403037, FAKE_MEETING_INFO, 'a message')),
|
|
6785
6791
|
};
|
|
6786
6792
|
|
|
6787
|
-
await assert.isRejected(
|
|
6788
|
-
meeting.fetchMeetingInfo({sendCAevents: true}),
|
|
6789
|
-
JoinWebinarError
|
|
6790
|
-
);
|
|
6793
|
+
await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), JoinWebinarError);
|
|
6791
6794
|
|
|
6792
6795
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6793
6796
|
assert.equal(
|
|
@@ -7524,6 +7527,27 @@ describe('plugin-meetings', () => {
|
|
|
7524
7527
|
});
|
|
7525
7528
|
});
|
|
7526
7529
|
|
|
7530
|
+
describe('#setIsoLocalClientMeetingJoinTime', () => {
|
|
7531
|
+
it('should fallback to system clock ISO string when given an undefined value', () => {
|
|
7532
|
+
const currentSystemTime = new Date().toISOString();
|
|
7533
|
+
meeting.isoLocalClientMeetingJoinTime = undefined;
|
|
7534
|
+
assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
|
|
7535
|
+
});
|
|
7536
|
+
|
|
7537
|
+
it('should fallback to system clock ISO string when given an invalid value', () => {
|
|
7538
|
+
const currentSystemTime = new Date().toISOString();
|
|
7539
|
+
meeting.isoLocalClientMeetingJoinTime = 'invalid-date';
|
|
7540
|
+
assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
|
|
7541
|
+
});
|
|
7542
|
+
|
|
7543
|
+
it('should set the isoLocalClientMeetingJoinTime correctly for a valid date string', () => {
|
|
7544
|
+
const validDateString = 'Tue, 01 Apr 2025 13:00:36 GMT';
|
|
7545
|
+
const expectedISOString = new Date(validDateString).toISOString();
|
|
7546
|
+
meeting.isoLocalClientMeetingJoinTime = validDateString;
|
|
7547
|
+
assert.equal(meeting.isoLocalClientMeetingJoinTime, expectedISOString);
|
|
7548
|
+
});
|
|
7549
|
+
});
|
|
7550
|
+
|
|
7527
7551
|
describe('#updateCallStateForMetrics', () => {
|
|
7528
7552
|
it('should update the callState, overriding existing values', () => {
|
|
7529
7553
|
assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''});
|
|
@@ -9223,22 +9247,22 @@ describe('plugin-meetings', () => {
|
|
|
9223
9247
|
const assertBrb = (enabled) => {
|
|
9224
9248
|
meeting.brbState = createBrbState(meeting, false);
|
|
9225
9249
|
meeting.locusInfo.emit(
|
|
9226
|
-
{
|
|
9250
|
+
{function: 'test', file: 'test'},
|
|
9227
9251
|
LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED,
|
|
9228
|
-
{
|
|
9229
|
-
)
|
|
9252
|
+
{brb: {enabled}}
|
|
9253
|
+
);
|
|
9230
9254
|
assert.calledWithExactly(
|
|
9231
9255
|
TriggerProxy.trigger,
|
|
9232
9256
|
meeting,
|
|
9233
9257
|
{file: 'meeting/index', function: 'setUpLocusInfoSelfListener'},
|
|
9234
9258
|
EVENT_TRIGGERS.MEETING_SELF_BRB_UPDATE,
|
|
9235
|
-
{
|
|
9259
|
+
{payload: {brb: {enabled}}}
|
|
9236
9260
|
);
|
|
9237
|
-
}
|
|
9261
|
+
};
|
|
9238
9262
|
|
|
9239
9263
|
assertBrb(true);
|
|
9240
9264
|
assertBrb(false);
|
|
9241
|
-
})
|
|
9265
|
+
});
|
|
9242
9266
|
|
|
9243
9267
|
it('listens to the interpretation changed event', () => {
|
|
9244
9268
|
meeting.simultaneousInterpretation.updateSelfInterpretation = sinon.stub();
|
|
@@ -9922,6 +9946,22 @@ describe('plugin-meetings', () => {
|
|
|
9922
9946
|
});
|
|
9923
9947
|
});
|
|
9924
9948
|
|
|
9949
|
+
describe('#emailInput', () => {
|
|
9950
|
+
it('should set the email input', () => {
|
|
9951
|
+
assert.notOk(meeting.emailInput);
|
|
9952
|
+
meeting.emailInput = 'current';
|
|
9953
|
+
assert.equal(meeting.emailInput, 'current');
|
|
9954
|
+
});
|
|
9955
|
+
});
|
|
9956
|
+
|
|
9957
|
+
describe('#userNameInput', () => {
|
|
9958
|
+
it('should set the user name input', () => {
|
|
9959
|
+
assert.notOk(meeting.userNameInput);
|
|
9960
|
+
meeting.userNameInput = 'current';
|
|
9961
|
+
assert.equal(meeting.userNameInput, 'current');
|
|
9962
|
+
});
|
|
9963
|
+
});
|
|
9964
|
+
|
|
9925
9965
|
describe('#setPermissionTokenPayload', () => {
|
|
9926
9966
|
let now;
|
|
9927
9967
|
let clock;
|
|
@@ -11326,18 +11366,21 @@ describe('plugin-meetings', () => {
|
|
|
11326
11366
|
);
|
|
11327
11367
|
});
|
|
11328
11368
|
|
|
11329
|
-
|
|
11330
11369
|
it('connect ps data channel if ps started in webinar', async () => {
|
|
11331
11370
|
meeting.joinedWith = {state: 'JOINED'};
|
|
11332
|
-
meeting.locusInfo = {
|
|
11371
|
+
meeting.locusInfo = {
|
|
11372
|
+
url: 'a url',
|
|
11373
|
+
info: {
|
|
11374
|
+
datachannelUrl: 'a datachannel url',
|
|
11375
|
+
practiceSessionDatachannelUrl: 'a ps datachannel url',
|
|
11376
|
+
},
|
|
11377
|
+
};
|
|
11333
11378
|
meeting.webinar.isJoinPracticeSessionDataChannel = sinon.stub().returns(true);
|
|
11334
11379
|
await meeting.updateLLMConnection();
|
|
11335
11380
|
|
|
11336
11381
|
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
11337
11382
|
assert.calledWith(webex.internal.llm.registerAndConnect, 'a url', 'a ps datachannel url');
|
|
11338
|
-
|
|
11339
11383
|
});
|
|
11340
|
-
|
|
11341
11384
|
});
|
|
11342
11385
|
|
|
11343
11386
|
describe('#setLocus', () => {
|
|
@@ -11755,24 +11798,29 @@ describe('plugin-meetings', () => {
|
|
|
11755
11798
|
|
|
11756
11799
|
activeSharingId.whiteboard = beneficiaryId;
|
|
11757
11800
|
|
|
11758
|
-
eventTrigger.share.push(
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11801
|
+
eventTrigger.share.push(
|
|
11802
|
+
meeting.webinar.selfIsAttendee
|
|
11803
|
+
? {
|
|
11804
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
11805
|
+
functionName: 'remoteShare',
|
|
11806
|
+
eventPayload: {
|
|
11807
|
+
memberId: null,
|
|
11808
|
+
url,
|
|
11809
|
+
shareInstanceId,
|
|
11810
|
+
annotationInfo: undefined,
|
|
11811
|
+
resourceType: undefined,
|
|
11812
|
+
},
|
|
11813
|
+
}
|
|
11814
|
+
: {
|
|
11815
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
11816
|
+
functionName: 'startWhiteboardShare',
|
|
11817
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
11818
|
+
}
|
|
11819
|
+
);
|
|
11775
11820
|
|
|
11821
|
+
shareStatus = meeting.webinar.selfIsAttendee
|
|
11822
|
+
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
|
11823
|
+
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
11776
11824
|
}
|
|
11777
11825
|
|
|
11778
11826
|
if (eventTrigger.member) {
|
|
@@ -11804,24 +11852,29 @@ describe('plugin-meetings', () => {
|
|
|
11804
11852
|
newPayload.current.content.disposition = FLOOR_ACTION.ACCEPTED;
|
|
11805
11853
|
newPayload.current.content.beneficiaryId = otherBeneficiaryId;
|
|
11806
11854
|
|
|
11807
|
-
eventTrigger.share.push(
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11855
|
+
eventTrigger.share.push(
|
|
11856
|
+
meeting.webinar.selfIsAttendee
|
|
11857
|
+
? {
|
|
11858
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
11859
|
+
functionName: 'remoteShare',
|
|
11860
|
+
eventPayload: {
|
|
11861
|
+
memberId: null,
|
|
11862
|
+
url,
|
|
11863
|
+
shareInstanceId,
|
|
11864
|
+
annotationInfo: undefined,
|
|
11865
|
+
resourceType: undefined,
|
|
11866
|
+
},
|
|
11867
|
+
}
|
|
11868
|
+
: {
|
|
11869
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
11870
|
+
functionName: 'startWhiteboardShare',
|
|
11871
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
11872
|
+
}
|
|
11873
|
+
);
|
|
11824
11874
|
|
|
11875
|
+
shareStatus = meeting.webinar.selfIsAttendee
|
|
11876
|
+
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
|
11877
|
+
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
11825
11878
|
} else {
|
|
11826
11879
|
eventTrigger.share.push({
|
|
11827
11880
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
@@ -11951,24 +12004,24 @@ describe('plugin-meetings', () => {
|
|
|
11951
12004
|
describe('Whiteboard Share - Webinar Attendee', () => {
|
|
11952
12005
|
it('Scenario #1: Whiteboard sharing as a webinar attendee', () => {
|
|
11953
12006
|
// Set the webinar attendee flag
|
|
11954
|
-
meeting.webinar = {
|
|
12007
|
+
meeting.webinar = {selfIsAttendee: true};
|
|
11955
12008
|
meeting.locusInfo.info.isWebinar = true;
|
|
11956
12009
|
|
|
11957
12010
|
// Step 1: Start sharing whiteboard A
|
|
11958
12011
|
const data1 = generateData(
|
|
11959
|
-
blankPayload,
|
|
11960
|
-
true,
|
|
11961
|
-
false,
|
|
11962
|
-
USER_IDS.REMOTE_A,
|
|
12012
|
+
blankPayload, // Initial payload
|
|
12013
|
+
true, // isGranting: Granting share
|
|
12014
|
+
false, // isContent: Whiteboard (not content)
|
|
12015
|
+
USER_IDS.REMOTE_A, // Beneficiary ID: Remote user A
|
|
11963
12016
|
RESOURCE_URLS.WHITEBOARD_A // Resource URL: Whiteboard A
|
|
11964
12017
|
);
|
|
11965
12018
|
|
|
11966
12019
|
// Step 2: Stop sharing whiteboard A
|
|
11967
12020
|
const data2 = generateData(
|
|
11968
|
-
data1.payload,
|
|
11969
|
-
false,
|
|
11970
|
-
false,
|
|
11971
|
-
USER_IDS.REMOTE_A
|
|
12021
|
+
data1.payload, // Updated payload from Step 1
|
|
12022
|
+
false, // isGranting: Stopping share
|
|
12023
|
+
false, // isContent: Whiteboard
|
|
12024
|
+
USER_IDS.REMOTE_A // Beneficiary ID: Remote user A
|
|
11972
12025
|
);
|
|
11973
12026
|
|
|
11974
12027
|
// Validate the payload changes and status updates
|
|
@@ -11979,7 +12032,6 @@ describe('plugin-meetings', () => {
|
|
|
11979
12032
|
});
|
|
11980
12033
|
});
|
|
11981
12034
|
|
|
11982
|
-
|
|
11983
12035
|
describe('Whiteboard A --> Whiteboard B', () => {
|
|
11984
12036
|
it('Scenario #1: you share both whiteboards', () => {
|
|
11985
12037
|
const data1 = generateData(
|
|
@@ -12632,6 +12684,31 @@ describe('plugin-meetings', () => {
|
|
|
12632
12684
|
});
|
|
12633
12685
|
});
|
|
12634
12686
|
});
|
|
12687
|
+
|
|
12688
|
+
describe('handleShareVideoStreamMuteStateChange', () => {
|
|
12689
|
+
it('should emit MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE event with correct fields', () => {
|
|
12690
|
+
meeting.isMultistream = true;
|
|
12691
|
+
meeting.statsAnalyzer = {shareVideoEncoderImplementation: 'OpenH264'};
|
|
12692
|
+
meeting.mediaProperties.shareVideoStream = {
|
|
12693
|
+
getSettings: sinon.stub().returns({displaySurface: 'monitor', frameRate: 30}),
|
|
12694
|
+
};
|
|
12695
|
+
|
|
12696
|
+
meeting.handleShareVideoStreamMuteStateChange(true);
|
|
12697
|
+
|
|
12698
|
+
assert.calledOnceWithExactly(
|
|
12699
|
+
Metrics.sendBehavioralMetric,
|
|
12700
|
+
BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE,
|
|
12701
|
+
{
|
|
12702
|
+
correlationId: meeting.correlationId,
|
|
12703
|
+
muted: true,
|
|
12704
|
+
encoderImplementation: 'OpenH264',
|
|
12705
|
+
displaySurface: 'monitor',
|
|
12706
|
+
isMultistream: true,
|
|
12707
|
+
frameRate: 30,
|
|
12708
|
+
}
|
|
12709
|
+
);
|
|
12710
|
+
});
|
|
12711
|
+
});
|
|
12635
12712
|
});
|
|
12636
12713
|
|
|
12637
12714
|
describe('#startKeepAlive', () => {
|
|
@@ -13290,7 +13367,7 @@ describe('plugin-meetings', () => {
|
|
|
13290
13367
|
await meeting.roapMessageReceived(fakeMessage);
|
|
13291
13368
|
|
|
13292
13369
|
assert.fail('Expected MultistreamNotSupportedError to be thrown');
|
|
13293
|
-
} catch(e) {
|
|
13370
|
+
} catch (e) {
|
|
13294
13371
|
assert.isTrue(e instanceof MultistreamNotSupportedError);
|
|
13295
13372
|
}
|
|
13296
13373
|
|