@webex/plugin-meetings 3.6.0-next.1 → 3.6.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/webinar-registration-error.js +50 -0
- package/dist/common/errors/webinar-registration-error.js.map +1 -0
- package/dist/constants.js +7 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/parser.js +5 -1
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/meeting/index.js +146 -99
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +5 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +68 -17
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +2 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMedia.js +4 -0
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/types/common/errors/webinar-registration-error.d.ts +14 -0
- package/dist/types/constants.d.ts +6 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/meeting/muteState.d.ts +2 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +23 -0
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/remoteMedia.d.ts +1 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +21 -21
- package/src/common/errors/webinar-registration-error.ts +27 -0
- package/src/constants.ts +6 -0
- package/src/index.ts +2 -0
- package/src/locus-info/parser.ts +8 -1
- package/src/meeting/index.ts +40 -11
- package/src/meeting/muteState.ts +6 -2
- package/src/meeting-info/meeting-info-v2.ts +51 -0
- package/src/meetings/index.ts +3 -1
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/remoteMedia.ts +5 -0
- package/test/unit/spec/locus-info/index.js +29 -0
- package/test/unit/spec/meeting/index.js +60 -1
- package/test/unit/spec/meeting/muteState.js +8 -4
- package/test/unit/spec/meeting-info/meetinginfov2.js +37 -0
- package/test/unit/spec/multistream/remoteMedia.ts +16 -2
|
@@ -1807,6 +1807,35 @@ describe('plugin-meetings', () => {
|
|
|
1807
1807
|
assert.calledWith(locusInfo.applyLocusDeltaData, action, parsedLoci, fakeMeeting);
|
|
1808
1808
|
});
|
|
1809
1809
|
|
|
1810
|
+
it('catches errors thrown by onDeltaAction and is able to process next Locus delta', () => {
|
|
1811
|
+
const fakeLocusDelta = {
|
|
1812
|
+
sequence: {
|
|
1813
|
+
rangeStart: 0,
|
|
1814
|
+
rangeEnd: 0,
|
|
1815
|
+
},
|
|
1816
|
+
};
|
|
1817
|
+
locusInfo.locusParser.workingCopy = {
|
|
1818
|
+
sequence: {
|
|
1819
|
+
rangeStart: 0,
|
|
1820
|
+
rangeEnd: 0,
|
|
1821
|
+
},
|
|
1822
|
+
};
|
|
1823
|
+
const testMeeting = {locusInfo: {onDeltaLocus: sinon.stub()}};
|
|
1824
|
+
|
|
1825
|
+
locusParser.onDeltaAction = sandbox
|
|
1826
|
+
.stub()
|
|
1827
|
+
.onCall(0)
|
|
1828
|
+
.callsFake(() => {
|
|
1829
|
+
throw new Error('fake error');
|
|
1830
|
+
});
|
|
1831
|
+
|
|
1832
|
+
// simulate first locus delta coming - it will trigger an error thrown by onDeltaAction
|
|
1833
|
+
locusInfo.handleLocusDelta(fakeLocusDelta, testMeeting);
|
|
1834
|
+
|
|
1835
|
+
// simulate a second locus delta coming - it should be processed without errors
|
|
1836
|
+
locusInfo.handleLocusDelta(fakeLocusDelta, testMeeting);
|
|
1837
|
+
});
|
|
1838
|
+
|
|
1810
1839
|
it('applyLocusDeltaData handles USE_INCOMING action correctly', () => {
|
|
1811
1840
|
const {USE_INCOMING} = LocusDeltaParser.loci;
|
|
1812
1841
|
const meeting = {
|
|
@@ -90,13 +90,15 @@ 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
|
|
93
|
+
import PermissionError from '../../../../src/common/errors/permission';
|
|
94
|
+
import WebinarRegistrationError from '../../../../src/common/errors/webinar-registration-error';
|
|
94
95
|
import IntentToJoinError from '../../../../src/common/errors/intent-to-join';
|
|
95
96
|
import testUtils from '../../../utils/testUtils';
|
|
96
97
|
import {
|
|
97
98
|
MeetingInfoV2CaptchaError,
|
|
98
99
|
MeetingInfoV2PasswordError,
|
|
99
100
|
MeetingInfoV2PolicyError,
|
|
101
|
+
MeetingInfoV2WebinarRegistrationError,
|
|
100
102
|
} from '../../../../src/meeting-info/meeting-info-v2';
|
|
101
103
|
import {
|
|
102
104
|
DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
@@ -3991,6 +3993,7 @@ describe('plugin-meetings', () => {
|
|
|
3991
3993
|
assert.notCalled(
|
|
3992
3994
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream
|
|
3993
3995
|
);
|
|
3996
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish microphone stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
3994
3997
|
} else {
|
|
3995
3998
|
assert.calledOnceWithExactly(
|
|
3996
3999
|
meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream,
|
|
@@ -4003,6 +4006,7 @@ describe('plugin-meetings', () => {
|
|
|
4003
4006
|
assert.notCalled(
|
|
4004
4007
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream
|
|
4005
4008
|
);
|
|
4009
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish camera stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
4006
4010
|
} else {
|
|
4007
4011
|
assert.calledOnceWithExactly(
|
|
4008
4012
|
meeting.sendSlotManager.getSlot(MediaType.VideoMain).publishStream,
|
|
@@ -4015,6 +4019,7 @@ describe('plugin-meetings', () => {
|
|
|
4015
4019
|
assert.notCalled(
|
|
4016
4020
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream
|
|
4017
4021
|
);
|
|
4022
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish screenShare audio stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
4018
4023
|
} else {
|
|
4019
4024
|
assert.calledOnceWithExactly(
|
|
4020
4025
|
meeting.sendSlotManager.getSlot(MediaType.AudioSlides).publishStream,
|
|
@@ -4027,6 +4032,7 @@ describe('plugin-meetings', () => {
|
|
|
4027
4032
|
assert.notCalled(
|
|
4028
4033
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream
|
|
4029
4034
|
);
|
|
4035
|
+
assert.throws(meeting.publishStreams(localStreams), `Attempted to publish screenShare video stream with ended readyState, correlationId=${meeting.correlationId}`);
|
|
4030
4036
|
} else {
|
|
4031
4037
|
assert.calledOnceWithExactly(
|
|
4032
4038
|
meeting.sendSlotManager.getSlot(MediaType.VideoSlides).publishStream,
|
|
@@ -6250,6 +6256,22 @@ describe('plugin-meetings', () => {
|
|
|
6250
6256
|
|
|
6251
6257
|
assert.equal(meeting.fetchMeetingInfoTimeoutId, undefined);
|
|
6252
6258
|
});
|
|
6259
|
+
|
|
6260
|
+
it('handles meetingInfoProvider webinar need registration error', async () => {
|
|
6261
|
+
meeting.destination = FAKE_DESTINATION;
|
|
6262
|
+
meeting.destinationType = FAKE_TYPE;
|
|
6263
|
+
meeting.attrs.meetingInfoProvider = {
|
|
6264
|
+
fetchMeetingInfo: sinon
|
|
6265
|
+
.stub()
|
|
6266
|
+
.throws(new MeetingInfoV2WebinarRegistrationError(403021, FAKE_MEETING_INFO, 'a message')),
|
|
6267
|
+
};
|
|
6268
|
+
|
|
6269
|
+
await assert.isRejected(meeting.fetchMeetingInfo({sendCAevents: true}), WebinarRegistrationError);
|
|
6270
|
+
|
|
6271
|
+
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
6272
|
+
assert.equal(meeting.meetingInfoFailureCode, 403021);
|
|
6273
|
+
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION);
|
|
6274
|
+
});
|
|
6253
6275
|
});
|
|
6254
6276
|
|
|
6255
6277
|
describe('#refreshPermissionToken', () => {
|
|
@@ -12178,6 +12200,43 @@ describe('plugin-meetings', () => {
|
|
|
12178
12200
|
await testEmit(false);
|
|
12179
12201
|
});
|
|
12180
12202
|
});
|
|
12203
|
+
|
|
12204
|
+
describe('LOCAL_UNMUTE_REQUIRED locus event', () => {
|
|
12205
|
+
const testEmit = async (unmuteAllowed) => {
|
|
12206
|
+
meeting.audio = {
|
|
12207
|
+
handleServerLocalUnmuteRequired: sinon.stub(),
|
|
12208
|
+
}
|
|
12209
|
+
await meeting.locusInfo.emitScoped(
|
|
12210
|
+
{},
|
|
12211
|
+
LOCUSINFO.EVENTS.LOCAL_UNMUTE_REQUIRED,
|
|
12212
|
+
{
|
|
12213
|
+
unmuteAllowed,
|
|
12214
|
+
}
|
|
12215
|
+
);
|
|
12216
|
+
|
|
12217
|
+
assert.calledWith(
|
|
12218
|
+
TriggerProxy.trigger,
|
|
12219
|
+
sinon.match.instanceOf(Meeting),
|
|
12220
|
+
{
|
|
12221
|
+
file: 'meeting/index',
|
|
12222
|
+
function: 'setUpLocusInfoSelfListener',
|
|
12223
|
+
},
|
|
12224
|
+
EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
|
|
12225
|
+
{
|
|
12226
|
+
payload: {
|
|
12227
|
+
unmuteAllowed,
|
|
12228
|
+
},
|
|
12229
|
+
}
|
|
12230
|
+
);
|
|
12231
|
+
assert.calledOnceWithExactly(meeting.audio.handleServerLocalUnmuteRequired, meeting, unmuteAllowed)
|
|
12232
|
+
};
|
|
12233
|
+
|
|
12234
|
+
[true, false].forEach((unmuteAllowed) => {
|
|
12235
|
+
it(`emits the expected event and calls handleServerLocalUnmuteRequired() when unmuteAllowed=${unmuteAllowed}`, async () => {
|
|
12236
|
+
await testEmit(unmuteAllowed);
|
|
12237
|
+
});
|
|
12238
|
+
});
|
|
12239
|
+
});
|
|
12181
12240
|
});
|
|
12182
12241
|
});
|
|
12183
12242
|
|
|
@@ -151,7 +151,7 @@ describe('plugin-meetings', () => {
|
|
|
151
151
|
meeting.mediaProperties.audioStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
152
152
|
meeting.mediaProperties.audioStream.userMuted = muted;
|
|
153
153
|
});
|
|
154
|
-
audio.handleServerLocalUnmuteRequired(meeting);
|
|
154
|
+
audio.handleServerLocalUnmuteRequired(meeting, true);
|
|
155
155
|
|
|
156
156
|
await testUtils.flushPromises();
|
|
157
157
|
|
|
@@ -161,6 +161,8 @@ describe('plugin-meetings', () => {
|
|
|
161
161
|
false,
|
|
162
162
|
'localUnmuteRequired'
|
|
163
163
|
);
|
|
164
|
+
// and unmuteAllowed was updated
|
|
165
|
+
assert.calledWith(meeting.mediaProperties.audioStream.setUnmuteAllowed, true);
|
|
164
166
|
|
|
165
167
|
// and local unmute was sent to server
|
|
166
168
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
@@ -184,7 +186,7 @@ describe('plugin-meetings', () => {
|
|
|
184
186
|
meeting.mediaProperties.audioStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
185
187
|
meeting.mediaProperties.audioStream.userMuted = muted;
|
|
186
188
|
});
|
|
187
|
-
audio.handleServerLocalUnmuteRequired(meeting);
|
|
189
|
+
audio.handleServerLocalUnmuteRequired(meeting, true);
|
|
188
190
|
|
|
189
191
|
await testUtils.flushPromises();
|
|
190
192
|
|
|
@@ -215,7 +217,7 @@ describe('plugin-meetings', () => {
|
|
|
215
217
|
meeting.mediaProperties.videoStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
216
218
|
meeting.mediaProperties.videoStream.userMuted = muted;
|
|
217
219
|
});
|
|
218
|
-
video.handleServerLocalUnmuteRequired(meeting);
|
|
220
|
+
video.handleServerLocalUnmuteRequired(meeting, true);
|
|
219
221
|
|
|
220
222
|
await testUtils.flushPromises();
|
|
221
223
|
|
|
@@ -225,6 +227,8 @@ describe('plugin-meetings', () => {
|
|
|
225
227
|
false,
|
|
226
228
|
'localUnmuteRequired'
|
|
227
229
|
);
|
|
230
|
+
// and unmuteAllowed was updated
|
|
231
|
+
assert.calledWith(meeting.mediaProperties.videoStream.setUnmuteAllowed, true);
|
|
228
232
|
|
|
229
233
|
// and local unmute was sent to server
|
|
230
234
|
assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
|
|
@@ -248,7 +252,7 @@ describe('plugin-meetings', () => {
|
|
|
248
252
|
meeting.mediaProperties.videoStream.setServerMuted = sinon.stub().callsFake((muted) => {
|
|
249
253
|
meeting.mediaProperties.videoStream.userMuted = muted;
|
|
250
254
|
});
|
|
251
|
-
video.handleServerLocalUnmuteRequired(meeting);
|
|
255
|
+
video.handleServerLocalUnmuteRequired(meeting, true);
|
|
252
256
|
|
|
253
257
|
await testUtils.flushPromises();
|
|
254
258
|
|
|
@@ -18,6 +18,7 @@ import MeetingInfo, {
|
|
|
18
18
|
MeetingInfoV2CaptchaError,
|
|
19
19
|
MeetingInfoV2AdhocMeetingError,
|
|
20
20
|
MeetingInfoV2PolicyError,
|
|
21
|
+
MeetingInfoV2WebinarRegistrationError,
|
|
21
22
|
} from '@webex/plugin-meetings/src/meeting-info/meeting-info-v2';
|
|
22
23
|
import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
|
|
23
24
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
@@ -888,6 +889,42 @@ describe('plugin-meetings', () => {
|
|
|
888
889
|
});
|
|
889
890
|
}
|
|
890
891
|
);
|
|
892
|
+
|
|
893
|
+
forEach(
|
|
894
|
+
[
|
|
895
|
+
{errorCode: 403021},
|
|
896
|
+
{errorCode: 403022},
|
|
897
|
+
{errorCode: 403024},
|
|
898
|
+
],
|
|
899
|
+
({errorCode}) => {
|
|
900
|
+
it(`should throw a MeetingInfoV2WebinarRegistrationError for error code ${errorCode}`, async () => {
|
|
901
|
+
const message = 'a message';
|
|
902
|
+
const meetingInfoData = {meetingInfo: {registrationUrl: 'registrationUrl'}};
|
|
903
|
+
|
|
904
|
+
webex.request = sinon.stub().rejects({
|
|
905
|
+
statusCode: 403,
|
|
906
|
+
body: {message, code: errorCode, data: {meetingInfo: meetingInfoData}},
|
|
907
|
+
});
|
|
908
|
+
try {
|
|
909
|
+
await meetingInfo.createAdhocSpaceMeeting(conversationUrl, installedOrgID);
|
|
910
|
+
assert.fail('createAdhocSpaceMeeting should have thrown, but has not done that');
|
|
911
|
+
} catch (err) {
|
|
912
|
+
assert.instanceOf(err, MeetingInfoV2WebinarRegistrationError);
|
|
913
|
+
assert.deepEqual(err.message, `${message}, code=${errorCode}`);
|
|
914
|
+
assert.equal(err.wbxAppApiCode, errorCode);
|
|
915
|
+
assert.deepEqual(err.meetingInfo, meetingInfoData);
|
|
916
|
+
|
|
917
|
+
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
918
|
+
assert.calledWith(
|
|
919
|
+
Metrics.sendBehavioralMetric,
|
|
920
|
+
BEHAVIORAL_METRICS.WEBINAR_REGISTRATION_ERROR,
|
|
921
|
+
{code: errorCode}
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
}
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
);
|
|
891
928
|
});
|
|
892
929
|
});
|
|
893
930
|
});
|
|
@@ -7,7 +7,7 @@ import {RemoteMedia, RemoteMediaEvents} from '@webex/plugin-meetings/src/multist
|
|
|
7
7
|
import {ReceiveSlotEvents} from '@webex/plugin-meetings/src/multistream/receiveSlot';
|
|
8
8
|
import sinon from 'sinon';
|
|
9
9
|
import {assert} from '@webex/test-helper-chai';
|
|
10
|
-
import {
|
|
10
|
+
import {forEach} from 'lodash';
|
|
11
11
|
|
|
12
12
|
describe('RemoteMedia', () => {
|
|
13
13
|
let remoteMedia;
|
|
@@ -227,12 +227,26 @@ describe('RemoteMedia', () => {
|
|
|
227
227
|
});
|
|
228
228
|
|
|
229
229
|
describe('setSizeHint()', () => {
|
|
230
|
-
|
|
231
230
|
it('works if the receive slot is undefined', () => {
|
|
232
231
|
remoteMedia.receiveSlot = undefined;
|
|
233
232
|
remoteMedia.setSizeHint(100, 100);
|
|
234
233
|
});
|
|
235
234
|
|
|
235
|
+
forEach(
|
|
236
|
+
[
|
|
237
|
+
{width: 0, height: 0},
|
|
238
|
+
{width: 135, height: 0},
|
|
239
|
+
{width: 0, height: 240},
|
|
240
|
+
],
|
|
241
|
+
({width, height}) => {
|
|
242
|
+
it(`skip updating the max fs when applied ${width}:${height}`, () => {
|
|
243
|
+
remoteMedia.setSizeHint(width, height);
|
|
244
|
+
|
|
245
|
+
assert.notCalled(fakeReceiveSlot.setMaxFs);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
|
|
236
250
|
forEach(
|
|
237
251
|
[
|
|
238
252
|
{height: 134, fs: 60},
|