@webex/plugin-meetings 3.8.0-next.3 → 3.8.0-next.30
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 +89 -5
- 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 +4 -1
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +359 -60
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +60 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +3 -0
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +9 -0
- package/dist/metrics/constants.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/reachability/request.js +19 -3
- package/dist/reachability/request.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/meeting-info/meeting-info-v2.d.ts +80 -0
- package/dist/types/meetings/index.d.ts +29 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/metrics/constants.d.ts +9 -0
- 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 +85 -7
- package/src/meeting/locusMediaRequest.ts +27 -4
- package/src/meeting/util.ts +2 -1
- package/src/meeting-info/meeting-info-v2.ts +247 -6
- package/src/meetings/index.ts +72 -1
- package/src/member/index.ts +11 -0
- package/src/member/util.ts +3 -0
- package/src/metrics/constants.ts +9 -0
- package/src/reachability/clusterReachability.ts +47 -1
- package/src/reachability/index.ts +15 -0
- package/src/reachability/reachability.types.ts +6 -0
- package/src/reachability/request.ts +7 -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 +200 -108
- package/test/unit/spec/meeting/locusMediaRequest.ts +96 -58
- package/test/unit/spec/meeting/utils.js +55 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
- package/test/unit/spec/meetings/index.js +78 -1
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/reachability/clusterReachability.ts +47 -1
- package/test/unit/spec/reachability/index.ts +12 -0
- package/test/unit/spec/reachability/request.js +47 -2
|
@@ -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: ''});
|
|
@@ -8590,13 +8614,19 @@ describe('plugin-meetings', () => {
|
|
|
8590
8614
|
const fakeErrorMessage = 'test error';
|
|
8591
8615
|
const fakeRootCauseName = 'root cause name';
|
|
8592
8616
|
const fakeErrorName = 'test error name';
|
|
8617
|
+
let clock;
|
|
8593
8618
|
|
|
8594
8619
|
beforeEach(() => {
|
|
8620
|
+
clock = sinon.useFakeTimers();
|
|
8595
8621
|
meeting.setupMediaConnectionListeners();
|
|
8596
8622
|
webex.internal.newMetrics.submitClientEvent.resetHistory();
|
|
8597
8623
|
Metrics.sendBehavioralMetric.resetHistory();
|
|
8598
8624
|
});
|
|
8599
8625
|
|
|
8626
|
+
afterEach(() => {
|
|
8627
|
+
clock.restore();
|
|
8628
|
+
});
|
|
8629
|
+
|
|
8600
8630
|
const checkMetricSent = (event, error) => {
|
|
8601
8631
|
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
|
8602
8632
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
@@ -8665,6 +8695,13 @@ describe('plugin-meetings', () => {
|
|
|
8665
8695
|
});
|
|
8666
8696
|
|
|
8667
8697
|
it('should send metrics for SdpAnswerHandlingError error', () => {
|
|
8698
|
+
meeting.sdpResponseTimer = '1234';
|
|
8699
|
+
meeting.deferSDPAnswer = {
|
|
8700
|
+
reject: sinon.stub(),
|
|
8701
|
+
};
|
|
8702
|
+
|
|
8703
|
+
const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
|
|
8704
|
+
|
|
8668
8705
|
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
|
8669
8706
|
name: fakeErrorName,
|
|
8670
8707
|
cause: {name: fakeRootCauseName},
|
|
@@ -8679,6 +8716,8 @@ describe('plugin-meetings', () => {
|
|
|
8679
8716
|
fakeErrorMessage,
|
|
8680
8717
|
fakeRootCauseName
|
|
8681
8718
|
);
|
|
8719
|
+
assert.calledOnce(meeting.deferSDPAnswer.reject);
|
|
8720
|
+
assert.calledOnce(clearTimeoutSpy);
|
|
8682
8721
|
});
|
|
8683
8722
|
|
|
8684
8723
|
it('should send metrics for SdpError error', () => {
|
|
@@ -9223,22 +9262,22 @@ describe('plugin-meetings', () => {
|
|
|
9223
9262
|
const assertBrb = (enabled) => {
|
|
9224
9263
|
meeting.brbState = createBrbState(meeting, false);
|
|
9225
9264
|
meeting.locusInfo.emit(
|
|
9226
|
-
{
|
|
9265
|
+
{function: 'test', file: 'test'},
|
|
9227
9266
|
LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED,
|
|
9228
|
-
{
|
|
9229
|
-
)
|
|
9267
|
+
{brb: {enabled}}
|
|
9268
|
+
);
|
|
9230
9269
|
assert.calledWithExactly(
|
|
9231
9270
|
TriggerProxy.trigger,
|
|
9232
9271
|
meeting,
|
|
9233
9272
|
{file: 'meeting/index', function: 'setUpLocusInfoSelfListener'},
|
|
9234
9273
|
EVENT_TRIGGERS.MEETING_SELF_BRB_UPDATE,
|
|
9235
|
-
{
|
|
9274
|
+
{payload: {brb: {enabled}}}
|
|
9236
9275
|
);
|
|
9237
|
-
}
|
|
9276
|
+
};
|
|
9238
9277
|
|
|
9239
9278
|
assertBrb(true);
|
|
9240
9279
|
assertBrb(false);
|
|
9241
|
-
})
|
|
9280
|
+
});
|
|
9242
9281
|
|
|
9243
9282
|
it('listens to the interpretation changed event', () => {
|
|
9244
9283
|
meeting.simultaneousInterpretation.updateSelfInterpretation = sinon.stub();
|
|
@@ -9922,6 +9961,22 @@ describe('plugin-meetings', () => {
|
|
|
9922
9961
|
});
|
|
9923
9962
|
});
|
|
9924
9963
|
|
|
9964
|
+
describe('#emailInput', () => {
|
|
9965
|
+
it('should set the email input', () => {
|
|
9966
|
+
assert.notOk(meeting.emailInput);
|
|
9967
|
+
meeting.emailInput = 'current';
|
|
9968
|
+
assert.equal(meeting.emailInput, 'current');
|
|
9969
|
+
});
|
|
9970
|
+
});
|
|
9971
|
+
|
|
9972
|
+
describe('#userNameInput', () => {
|
|
9973
|
+
it('should set the user name input', () => {
|
|
9974
|
+
assert.notOk(meeting.userNameInput);
|
|
9975
|
+
meeting.userNameInput = 'current';
|
|
9976
|
+
assert.equal(meeting.userNameInput, 'current');
|
|
9977
|
+
});
|
|
9978
|
+
});
|
|
9979
|
+
|
|
9925
9980
|
describe('#setPermissionTokenPayload', () => {
|
|
9926
9981
|
let now;
|
|
9927
9982
|
let clock;
|
|
@@ -11326,18 +11381,21 @@ describe('plugin-meetings', () => {
|
|
|
11326
11381
|
);
|
|
11327
11382
|
});
|
|
11328
11383
|
|
|
11329
|
-
|
|
11330
11384
|
it('connect ps data channel if ps started in webinar', async () => {
|
|
11331
11385
|
meeting.joinedWith = {state: 'JOINED'};
|
|
11332
|
-
meeting.locusInfo = {
|
|
11386
|
+
meeting.locusInfo = {
|
|
11387
|
+
url: 'a url',
|
|
11388
|
+
info: {
|
|
11389
|
+
datachannelUrl: 'a datachannel url',
|
|
11390
|
+
practiceSessionDatachannelUrl: 'a ps datachannel url',
|
|
11391
|
+
},
|
|
11392
|
+
};
|
|
11333
11393
|
meeting.webinar.isJoinPracticeSessionDataChannel = sinon.stub().returns(true);
|
|
11334
11394
|
await meeting.updateLLMConnection();
|
|
11335
11395
|
|
|
11336
11396
|
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
11337
11397
|
assert.calledWith(webex.internal.llm.registerAndConnect, 'a url', 'a ps datachannel url');
|
|
11338
|
-
|
|
11339
11398
|
});
|
|
11340
|
-
|
|
11341
11399
|
});
|
|
11342
11400
|
|
|
11343
11401
|
describe('#setLocus', () => {
|
|
@@ -11755,24 +11813,29 @@ describe('plugin-meetings', () => {
|
|
|
11755
11813
|
|
|
11756
11814
|
activeSharingId.whiteboard = beneficiaryId;
|
|
11757
11815
|
|
|
11758
|
-
eventTrigger.share.push(
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11816
|
+
eventTrigger.share.push(
|
|
11817
|
+
meeting.webinar.selfIsAttendee
|
|
11818
|
+
? {
|
|
11819
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
11820
|
+
functionName: 'remoteShare',
|
|
11821
|
+
eventPayload: {
|
|
11822
|
+
memberId: null,
|
|
11823
|
+
url,
|
|
11824
|
+
shareInstanceId,
|
|
11825
|
+
annotationInfo: undefined,
|
|
11826
|
+
resourceType: undefined,
|
|
11827
|
+
},
|
|
11828
|
+
}
|
|
11829
|
+
: {
|
|
11830
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
11831
|
+
functionName: 'startWhiteboardShare',
|
|
11832
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
11833
|
+
}
|
|
11834
|
+
);
|
|
11775
11835
|
|
|
11836
|
+
shareStatus = meeting.webinar.selfIsAttendee
|
|
11837
|
+
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
|
11838
|
+
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
11776
11839
|
}
|
|
11777
11840
|
|
|
11778
11841
|
if (eventTrigger.member) {
|
|
@@ -11804,24 +11867,29 @@ describe('plugin-meetings', () => {
|
|
|
11804
11867
|
newPayload.current.content.disposition = FLOOR_ACTION.ACCEPTED;
|
|
11805
11868
|
newPayload.current.content.beneficiaryId = otherBeneficiaryId;
|
|
11806
11869
|
|
|
11807
|
-
eventTrigger.share.push(
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11870
|
+
eventTrigger.share.push(
|
|
11871
|
+
meeting.webinar.selfIsAttendee
|
|
11872
|
+
? {
|
|
11873
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
11874
|
+
functionName: 'remoteShare',
|
|
11875
|
+
eventPayload: {
|
|
11876
|
+
memberId: null,
|
|
11877
|
+
url,
|
|
11878
|
+
shareInstanceId,
|
|
11879
|
+
annotationInfo: undefined,
|
|
11880
|
+
resourceType: undefined,
|
|
11881
|
+
},
|
|
11882
|
+
}
|
|
11883
|
+
: {
|
|
11884
|
+
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
11885
|
+
functionName: 'startWhiteboardShare',
|
|
11886
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
11887
|
+
}
|
|
11888
|
+
);
|
|
11824
11889
|
|
|
11890
|
+
shareStatus = meeting.webinar.selfIsAttendee
|
|
11891
|
+
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
|
11892
|
+
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
11825
11893
|
} else {
|
|
11826
11894
|
eventTrigger.share.push({
|
|
11827
11895
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
@@ -11951,24 +12019,24 @@ describe('plugin-meetings', () => {
|
|
|
11951
12019
|
describe('Whiteboard Share - Webinar Attendee', () => {
|
|
11952
12020
|
it('Scenario #1: Whiteboard sharing as a webinar attendee', () => {
|
|
11953
12021
|
// Set the webinar attendee flag
|
|
11954
|
-
meeting.webinar = {
|
|
12022
|
+
meeting.webinar = {selfIsAttendee: true};
|
|
11955
12023
|
meeting.locusInfo.info.isWebinar = true;
|
|
11956
12024
|
|
|
11957
12025
|
// Step 1: Start sharing whiteboard A
|
|
11958
12026
|
const data1 = generateData(
|
|
11959
|
-
blankPayload,
|
|
11960
|
-
true,
|
|
11961
|
-
false,
|
|
11962
|
-
USER_IDS.REMOTE_A,
|
|
12027
|
+
blankPayload, // Initial payload
|
|
12028
|
+
true, // isGranting: Granting share
|
|
12029
|
+
false, // isContent: Whiteboard (not content)
|
|
12030
|
+
USER_IDS.REMOTE_A, // Beneficiary ID: Remote user A
|
|
11963
12031
|
RESOURCE_URLS.WHITEBOARD_A // Resource URL: Whiteboard A
|
|
11964
12032
|
);
|
|
11965
12033
|
|
|
11966
12034
|
// Step 2: Stop sharing whiteboard A
|
|
11967
12035
|
const data2 = generateData(
|
|
11968
|
-
data1.payload,
|
|
11969
|
-
false,
|
|
11970
|
-
false,
|
|
11971
|
-
USER_IDS.REMOTE_A
|
|
12036
|
+
data1.payload, // Updated payload from Step 1
|
|
12037
|
+
false, // isGranting: Stopping share
|
|
12038
|
+
false, // isContent: Whiteboard
|
|
12039
|
+
USER_IDS.REMOTE_A // Beneficiary ID: Remote user A
|
|
11972
12040
|
);
|
|
11973
12041
|
|
|
11974
12042
|
// Validate the payload changes and status updates
|
|
@@ -11979,7 +12047,6 @@ describe('plugin-meetings', () => {
|
|
|
11979
12047
|
});
|
|
11980
12048
|
});
|
|
11981
12049
|
|
|
11982
|
-
|
|
11983
12050
|
describe('Whiteboard A --> Whiteboard B', () => {
|
|
11984
12051
|
it('Scenario #1: you share both whiteboards', () => {
|
|
11985
12052
|
const data1 = generateData(
|
|
@@ -12632,6 +12699,31 @@ describe('plugin-meetings', () => {
|
|
|
12632
12699
|
});
|
|
12633
12700
|
});
|
|
12634
12701
|
});
|
|
12702
|
+
|
|
12703
|
+
describe('handleShareVideoStreamMuteStateChange', () => {
|
|
12704
|
+
it('should emit MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE event with correct fields', () => {
|
|
12705
|
+
meeting.isMultistream = true;
|
|
12706
|
+
meeting.statsAnalyzer = {shareVideoEncoderImplementation: 'OpenH264'};
|
|
12707
|
+
meeting.mediaProperties.shareVideoStream = {
|
|
12708
|
+
getSettings: sinon.stub().returns({displaySurface: 'monitor', frameRate: 30}),
|
|
12709
|
+
};
|
|
12710
|
+
|
|
12711
|
+
meeting.handleShareVideoStreamMuteStateChange(true);
|
|
12712
|
+
|
|
12713
|
+
assert.calledOnceWithExactly(
|
|
12714
|
+
Metrics.sendBehavioralMetric,
|
|
12715
|
+
BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE,
|
|
12716
|
+
{
|
|
12717
|
+
correlationId: meeting.correlationId,
|
|
12718
|
+
muted: true,
|
|
12719
|
+
encoderImplementation: 'OpenH264',
|
|
12720
|
+
displaySurface: 'monitor',
|
|
12721
|
+
isMultistream: true,
|
|
12722
|
+
frameRate: 30,
|
|
12723
|
+
}
|
|
12724
|
+
);
|
|
12725
|
+
});
|
|
12726
|
+
});
|
|
12635
12727
|
});
|
|
12636
12728
|
|
|
12637
12729
|
describe('#startKeepAlive', () => {
|
|
@@ -13290,7 +13382,7 @@ describe('plugin-meetings', () => {
|
|
|
13290
13382
|
await meeting.roapMessageReceived(fakeMessage);
|
|
13291
13383
|
|
|
13292
13384
|
assert.fail('Expected MultistreamNotSupportedError to be thrown');
|
|
13293
|
-
} catch(e) {
|
|
13385
|
+
} catch (e) {
|
|
13294
13386
|
assert.isTrue(e instanceof MultistreamNotSupportedError);
|
|
13295
13387
|
}
|
|
13296
13388
|
|