@webex/plugin-meetings 3.7.0 → 3.8.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/annotation/index.js +17 -0
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/join-forbidden-error.js +52 -0
- package/dist/common/errors/join-forbidden-error.js.map +1 -0
- package/dist/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
- package/dist/common/errors/join-webinar-error.js.map +1 -0
- package/dist/common/errors/multistream-not-supported-error.js +53 -0
- package/dist/common/errors/multistream-not-supported-error.js.map +1 -0
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +69 -6
- package/dist/constants.js.map +1 -1
- package/dist/index.js +16 -11
- package/dist/index.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/index.js +14 -3
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +35 -17
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +1 -0
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +30 -16
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/brbState.js +167 -0
- package/dist/meeting/brbState.js.map +1 -0
- package/dist/meeting/in-meeting-actions.js +13 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1373 -1052
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +32 -11
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +1 -6
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +51 -29
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +103 -67
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +115 -45
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/utilv2.js +6 -2
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +107 -55
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +2 -0
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/util.js +1 -1
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +39 -28
- package/dist/member/util.js.map +1 -1
- package/dist/members/util.js +4 -2
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +6 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMedia.js +30 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +40 -8
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +24 -0
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +12 -15
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +471 -140
- package/dist/reachability/index.js.map +1 -1
- package/dist/{rtcMetrics/constants.js → reachability/reachability.types.js} +1 -5
- package/dist/reachability/reachability.types.js.map +1 -0
- package/dist/reachability/request.js +21 -8
- package/dist/reachability/request.js.map +1 -1
- package/dist/recording-controller/enums.js +8 -4
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +18 -9
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +13 -9
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +15 -15
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +45 -79
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +3 -6
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/types/annotation/index.d.ts +5 -0
- package/dist/types/common/errors/join-forbidden-error.d.ts +15 -0
- package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
- package/dist/types/common/errors/multistream-not-supported-error.d.ts +17 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/constants.d.ts +54 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/locus-info/index.d.ts +2 -1
- package/dist/types/meeting/brbState.d.ts +54 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +12 -0
- package/dist/types/meeting/index.d.ts +86 -14
- package/dist/types/meeting/locusMediaRequest.d.ts +6 -3
- package/dist/types/meeting/request.d.ts +14 -3
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +3 -3
- package/dist/types/meeting-info/meeting-info-v2.d.ts +30 -5
- package/dist/types/meetings/index.d.ts +20 -2
- package/dist/types/meetings/meetings.types.d.ts +8 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/types.d.ts +7 -0
- package/dist/types/members/util.d.ts +2 -0
- package/dist/types/metrics/constants.d.ts +6 -1
- package/dist/types/multistream/remoteMediaManager.d.ts +10 -1
- package/dist/types/multistream/sendSlotManager.d.ts +8 -1
- package/dist/types/reachability/clusterReachability.d.ts +1 -10
- package/dist/types/reachability/index.d.ts +83 -36
- package/dist/types/reachability/reachability.types.d.ts +64 -0
- package/dist/types/reachability/request.d.ts +5 -1
- package/dist/types/recording-controller/enums.d.ts +5 -2
- package/dist/types/recording-controller/index.d.ts +1 -0
- package/dist/types/recording-controller/util.d.ts +2 -1
- package/dist/types/roap/request.d.ts +1 -13
- package/dist/webinar/index.js +390 -7
- package/dist/webinar/index.js.map +1 -1
- package/package.json +23 -22
- package/src/annotation/index.ts +16 -0
- package/src/common/errors/join-forbidden-error.ts +26 -0
- package/src/common/errors/join-webinar-error.ts +24 -0
- package/src/common/errors/multistream-not-supported-error.ts +30 -0
- package/src/config.ts +2 -0
- package/src/constants.ts +62 -3
- package/src/index.ts +5 -3
- package/src/interpretation/index.ts +3 -3
- package/src/locus-info/index.ts +20 -3
- package/src/locus-info/selfUtils.ts +24 -6
- package/src/media/MediaConnectionAwaiter.ts +2 -0
- package/src/media/properties.ts +34 -13
- package/src/meeting/brbState.ts +169 -0
- package/src/meeting/in-meeting-actions.ts +25 -0
- package/src/meeting/index.ts +485 -88
- package/src/meeting/locusMediaRequest.ts +38 -12
- package/src/meeting/muteState.ts +1 -6
- package/src/meeting/request.ts +30 -12
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +32 -13
- package/src/meeting-info/meeting-info-v2.ts +83 -12
- package/src/meeting-info/utilv2.ts +17 -3
- package/src/meetings/index.ts +79 -20
- package/src/meetings/meetings.types.ts +10 -0
- package/src/meetings/util.ts +2 -1
- package/src/member/index.ts +9 -0
- package/src/member/types.ts +8 -0
- package/src/member/util.ts +34 -24
- package/src/members/util.ts +1 -0
- package/src/metrics/constants.ts +6 -1
- package/src/multistream/remoteMedia.ts +28 -15
- package/src/multistream/remoteMediaManager.ts +32 -10
- package/src/multistream/sendSlotManager.ts +31 -0
- package/src/reachability/clusterReachability.ts +5 -15
- package/src/reachability/index.ts +315 -75
- package/src/reachability/reachability.types.ts +85 -0
- package/src/reachability/request.ts +55 -31
- package/src/recording-controller/enums.ts +5 -2
- package/src/recording-controller/index.ts +17 -4
- package/src/recording-controller/util.ts +28 -9
- package/src/roap/index.ts +14 -13
- package/src/roap/request.ts +30 -44
- package/src/roap/turnDiscovery.ts +2 -4
- package/src/webinar/index.ts +235 -9
- package/test/unit/spec/annotation/index.ts +46 -1
- package/test/unit/spec/interpretation/index.ts +39 -1
- package/test/unit/spec/locus-info/index.js +292 -60
- package/test/unit/spec/locus-info/selfConstant.js +7 -0
- package/test/unit/spec/locus-info/selfUtils.js +101 -1
- package/test/unit/spec/media/properties.ts +15 -0
- package/test/unit/spec/meeting/brbState.ts +114 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +15 -1
- package/test/unit/spec/meeting/index.js +908 -124
- package/test/unit/spec/meeting/locusMediaRequest.ts +111 -66
- package/test/unit/spec/meeting/muteState.js +0 -24
- package/test/unit/spec/meeting/request.js +3 -26
- package/test/unit/spec/meeting/utils.js +73 -28
- package/test/unit/spec/meeting-info/meetinginfov2.js +46 -4
- package/test/unit/spec/meeting-info/utilv2.js +26 -0
- package/test/unit/spec/meetings/index.js +172 -18
- package/test/unit/spec/meetings/utils.js +10 -0
- package/test/unit/spec/member/util.js +52 -11
- package/test/unit/spec/members/utils.js +95 -0
- package/test/unit/spec/multistream/remoteMedia.ts +11 -7
- package/test/unit/spec/multistream/remoteMediaManager.ts +397 -118
- package/test/unit/spec/reachability/clusterReachability.ts +7 -0
- package/test/unit/spec/reachability/index.ts +391 -9
- package/test/unit/spec/reachability/request.js +48 -12
- package/test/unit/spec/recording-controller/index.js +61 -5
- package/test/unit/spec/recording-controller/util.js +39 -3
- package/test/unit/spec/roap/index.ts +48 -1
- package/test/unit/spec/roap/request.ts +51 -109
- package/test/unit/spec/roap/turnDiscovery.ts +202 -147
- package/test/unit/spec/webinar/index.ts +509 -0
- package/dist/common/errors/webinar-registration-error.js.map +0 -1
- package/dist/networkQualityMonitor/index.js +0 -227
- package/dist/networkQualityMonitor/index.js.map +0 -1
- package/dist/rtcMetrics/constants.js.map +0 -1
- package/dist/rtcMetrics/index.js +0 -197
- package/dist/rtcMetrics/index.js.map +0 -1
- package/dist/types/networkQualityMonitor/index.d.ts +0 -70
- package/dist/types/rtcMetrics/constants.d.ts +0 -4
- package/dist/types/rtcMetrics/index.d.ts +0 -71
- package/src/common/errors/webinar-registration-error.ts +0 -27
|
@@ -18,7 +18,8 @@ import MeetingInfo, {
|
|
|
18
18
|
MeetingInfoV2CaptchaError,
|
|
19
19
|
MeetingInfoV2AdhocMeetingError,
|
|
20
20
|
MeetingInfoV2PolicyError,
|
|
21
|
-
|
|
21
|
+
MeetingInfoV2JoinWebinarError,
|
|
22
|
+
MeetingInfoV2JoinForbiddenError,
|
|
22
23
|
} from '@webex/plugin-meetings/src/meeting-info/meeting-info-v2';
|
|
23
24
|
import MeetingInfoUtil from '@webex/plugin-meetings/src/meeting-info/utilv2';
|
|
24
25
|
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
@@ -895,9 +896,14 @@ describe('plugin-meetings', () => {
|
|
|
895
896
|
{errorCode: 403021},
|
|
896
897
|
{errorCode: 403022},
|
|
897
898
|
{errorCode: 403024},
|
|
899
|
+
{errorCode: 403137},
|
|
900
|
+
{errorCode: 423007},
|
|
901
|
+
{errorCode: 403026},
|
|
902
|
+
{errorCode: 403037},
|
|
903
|
+
{errorCode: 403137},
|
|
898
904
|
],
|
|
899
905
|
({errorCode}) => {
|
|
900
|
-
it(`should throw a
|
|
906
|
+
it(`should throw a MeetingInfoV2JoinWebinarError for error code ${errorCode}`, async () => {
|
|
901
907
|
const message = 'a message';
|
|
902
908
|
const meetingInfoData = {meetingInfo: {registrationUrl: 'registrationUrl'}};
|
|
903
909
|
|
|
@@ -909,7 +915,7 @@ describe('plugin-meetings', () => {
|
|
|
909
915
|
await meetingInfo.createAdhocSpaceMeeting(conversationUrl, installedOrgID);
|
|
910
916
|
assert.fail('createAdhocSpaceMeeting should have thrown, but has not done that');
|
|
911
917
|
} catch (err) {
|
|
912
|
-
assert.instanceOf(err,
|
|
918
|
+
assert.instanceOf(err, MeetingInfoV2JoinWebinarError);
|
|
913
919
|
assert.deepEqual(err.message, `${message}, code=${errorCode}`);
|
|
914
920
|
assert.equal(err.wbxAppApiCode, errorCode);
|
|
915
921
|
assert.deepEqual(err.meetingInfo, meetingInfoData);
|
|
@@ -917,7 +923,43 @@ describe('plugin-meetings', () => {
|
|
|
917
923
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
918
924
|
assert.calledWith(
|
|
919
925
|
Metrics.sendBehavioralMetric,
|
|
920
|
-
BEHAVIORAL_METRICS.
|
|
926
|
+
BEHAVIORAL_METRICS.JOIN_WEBINAR_ERROR,
|
|
927
|
+
{code: errorCode}
|
|
928
|
+
);
|
|
929
|
+
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
|
|
935
|
+
forEach(
|
|
936
|
+
[
|
|
937
|
+
{errorCode: 403003},
|
|
938
|
+
],
|
|
939
|
+
({errorCode}) => {
|
|
940
|
+
it(`should throw a MeetingInfoV2JoinForbiddenError for error code ${errorCode}`, async () => {
|
|
941
|
+
const message = 'a message';
|
|
942
|
+
const meetingInfoData = 'meeting info';
|
|
943
|
+
|
|
944
|
+
webex.request = sinon.stub().rejects({
|
|
945
|
+
statusCode: 403,
|
|
946
|
+
body: {message, code: errorCode, data: {meetingInfo: meetingInfoData}},
|
|
947
|
+
});
|
|
948
|
+
try {
|
|
949
|
+
await meetingInfo.fetchMeetingInfo('1234323', DESTINATION_TYPE.MEETING_ID, 'abc', {
|
|
950
|
+
id: '999',
|
|
951
|
+
code: 'aabbcc11',
|
|
952
|
+
});
|
|
953
|
+
} catch (err) {
|
|
954
|
+
assert.instanceOf(err, MeetingInfoV2JoinForbiddenError);
|
|
955
|
+
assert.deepEqual(err.message, `${message}, code=${errorCode}`);
|
|
956
|
+
assert.equal(err.wbxAppApiCode, errorCode);
|
|
957
|
+
assert.deepEqual(err.meetingInfo, meetingInfoData);
|
|
958
|
+
|
|
959
|
+
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
960
|
+
assert.calledWith(
|
|
961
|
+
Metrics.sendBehavioralMetric,
|
|
962
|
+
BEHAVIORAL_METRICS.JOIN_FORBIDDEN_ERROR,
|
|
921
963
|
{code: errorCode}
|
|
922
964
|
);
|
|
923
965
|
|
|
@@ -192,6 +192,15 @@ describe('plugin-meetings', () => {
|
|
|
192
192
|
assert.equal(res.meetingUUID, 'xsddsdsdsdssdsdsdsdsd');
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
+
it('for registrationId', () => {
|
|
196
|
+
const res = MeetingInfoUtil.getRequestBody({
|
|
197
|
+
type: DESTINATION_TYPE.MEETING_UUID,
|
|
198
|
+
registrationId: 'registrationId',
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
assert.equal(res.registrationId, 'registrationId');
|
|
202
|
+
});
|
|
203
|
+
|
|
195
204
|
it('for DESTINATION_TYPE.LOCUS_ID', () => {
|
|
196
205
|
const res = MeetingInfoUtil.getRequestBody({
|
|
197
206
|
type: DESTINATION_TYPE.LOCUS_ID,
|
|
@@ -345,5 +354,22 @@ describe('plugin-meetings', () => {
|
|
|
345
354
|
);
|
|
346
355
|
});
|
|
347
356
|
});
|
|
357
|
+
|
|
358
|
+
describe('#isMeetingLink', () => {
|
|
359
|
+
it('should return true for valid join meeting link with MTID', () => {
|
|
360
|
+
const result = MeetingInfoUtil.isMeetingLink('https://cisco.webex.com/cisco/j.php?MTID=m9fe0afd8c435e892afcce9ea25b97046');
|
|
361
|
+
expect(result).to.be.true;
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('should return true for valid join meeting link without cisco domain', () => {
|
|
365
|
+
const result = MeetingInfoUtil.isMeetingLink('https://test.webex.com/test/j.php?MTID=m9fe0afd8c435e892afcce9ea25b97046');
|
|
366
|
+
expect(result).to.be.true;
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('should return false for an invalid meeting link', () => {
|
|
370
|
+
const result = MeetingInfoUtil.isMeetingLink('https://test.webex.com/test/j.php?MiD=m9fe0afd8c435e892afcce9ea25b97046');
|
|
371
|
+
expect(result).to.be.false;
|
|
372
|
+
});
|
|
373
|
+
});
|
|
348
374
|
});
|
|
349
375
|
});
|
|
@@ -37,11 +37,13 @@ import {
|
|
|
37
37
|
LOCUSINFO,
|
|
38
38
|
EVENT_TRIGGERS,
|
|
39
39
|
DESTINATION_TYPE,
|
|
40
|
+
INITIAL_REGISTRATION_STATUS,
|
|
40
41
|
} from '../../../../src/constants';
|
|
41
42
|
import CaptchaError from '@webex/plugin-meetings/src/common/errors/captcha-error';
|
|
42
43
|
import {forEach} from 'lodash';
|
|
43
44
|
import PasswordError from '@webex/plugin-meetings/src/common/errors/password-error';
|
|
44
45
|
import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
|
|
46
|
+
import JoinForbiddenError from '@webex/plugin-meetings/src/common/errors/join-forbidden-error';
|
|
45
47
|
import {NoiseReductionEffect, VirtualBackgroundEffect} from '@webex/media-helpers';
|
|
46
48
|
import NoMeetingInfoError from '../../../../src/common/errors/no-meeting-info';
|
|
47
49
|
|
|
@@ -131,9 +133,9 @@ describe('plugin-meetings', () => {
|
|
|
131
133
|
logger,
|
|
132
134
|
people: {
|
|
133
135
|
_getMe: sinon.stub().resolves({
|
|
134
|
-
type: 'validuser',
|
|
136
|
+
type: 'validuser',
|
|
135
137
|
}),
|
|
136
|
-
}
|
|
138
|
+
},
|
|
137
139
|
});
|
|
138
140
|
|
|
139
141
|
startReachabilityStub = sinon.stub(webex.meetings, 'startReachability').resolves();
|
|
@@ -267,6 +269,33 @@ describe('plugin-meetings', () => {
|
|
|
267
269
|
});
|
|
268
270
|
});
|
|
269
271
|
|
|
272
|
+
describe('#_setLogUploadIntervalMultiplicationFactor', () => {
|
|
273
|
+
it('should have _setLogUploadIntervalMultiplicationFactor', () => {
|
|
274
|
+
assert.equal(typeof webex.meetings._setLogUploadIntervalMultiplicationFactor, 'function');
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe('success', () => {
|
|
278
|
+
it('should update the config', () => {
|
|
279
|
+
const someValue = 1.23;
|
|
280
|
+
|
|
281
|
+
webex.meetings._setLogUploadIntervalMultiplicationFactor(someValue);
|
|
282
|
+
assert.equal(webex.meetings.config.logUploadIntervalMultiplicationFactor, someValue);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
describe('failure', () => {
|
|
287
|
+
it('should not accept non-number input', () => {
|
|
288
|
+
const logUploadIntervalMultiplicationFactor = webex.meetings.config.logUploadIntervalMultiplicationFactor;
|
|
289
|
+
|
|
290
|
+
webex.meetings._setLogUploadIntervalMultiplicationFactor('test');
|
|
291
|
+
assert.equal(
|
|
292
|
+
webex.meetings.config.logUploadIntervalMultiplicationFactor,
|
|
293
|
+
logUploadIntervalMultiplicationFactor
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
270
299
|
describe('#_toggleUnifiedMeetings', () => {
|
|
271
300
|
it('should have toggleUnifiedMeetings', () => {
|
|
272
301
|
assert.equal(typeof webex.meetings._toggleUnifiedMeetings, 'function');
|
|
@@ -375,21 +404,21 @@ describe('plugin-meetings', () => {
|
|
|
375
404
|
assert.isTrue(webex.meetings.registered);
|
|
376
405
|
});
|
|
377
406
|
|
|
378
|
-
it('rejects when SDK canAuthorize is false', () => {
|
|
407
|
+
it('rejects when SDK canAuthorize is false', async () => {
|
|
379
408
|
webex.canAuthorize = false;
|
|
380
|
-
assert.isRejected(webex.meetings.register());
|
|
409
|
+
await assert.isRejected(webex.meetings.register());
|
|
381
410
|
});
|
|
382
411
|
|
|
383
|
-
it('rejects when device.register fails', () => {
|
|
412
|
+
it('rejects when device.register fails', async () => {
|
|
384
413
|
webex.canAuthorize = true;
|
|
385
414
|
webex.internal.device.register = sinon.stub().returns(Promise.reject());
|
|
386
|
-
assert.isRejected(webex.meetings.register());
|
|
415
|
+
await assert.isRejected(webex.meetings.register());
|
|
387
416
|
});
|
|
388
417
|
|
|
389
|
-
it('rejects when mercury.connect fails', () => {
|
|
418
|
+
it('rejects when mercury.connect fails', async () => {
|
|
390
419
|
webex.canAuthorize = true;
|
|
391
420
|
webex.internal.mercury.connect = sinon.stub().returns(Promise.reject());
|
|
392
|
-
assert.isRejected(webex.meetings.register());
|
|
421
|
+
await assert.isRejected(webex.meetings.register());
|
|
393
422
|
});
|
|
394
423
|
|
|
395
424
|
it('resolves immediately if already registered', async () => {
|
|
@@ -412,6 +441,19 @@ describe('plugin-meetings', () => {
|
|
|
412
441
|
assert.isTrue(webex.meetings.registered);
|
|
413
442
|
});
|
|
414
443
|
|
|
444
|
+
it('resolves even if startReachability() rejects', async () => {
|
|
445
|
+
webex.canAuthorize = true;
|
|
446
|
+
webex.meetings.registered = false;
|
|
447
|
+
webex.meetings.startReachability = sinon.stub().rejects(new Error('fake error'));
|
|
448
|
+
|
|
449
|
+
await webex.meetings.register();
|
|
450
|
+
assert.calledOnceWithExactly(webex.internal.device.register, undefined);
|
|
451
|
+
assert.called(webex.internal.services.getMeetingPreferences);
|
|
452
|
+
assert.called(webex.internal.services.fetchClientRegionInfo);
|
|
453
|
+
assert.called(webex.internal.mercury.connect);
|
|
454
|
+
assert.isTrue(webex.meetings.registered);
|
|
455
|
+
});
|
|
456
|
+
|
|
415
457
|
it('passes on the device registration options', async () => {
|
|
416
458
|
webex.canAuthorize = true;
|
|
417
459
|
webex.meetings.registered = false;
|
|
@@ -420,6 +462,100 @@ describe('plugin-meetings', () => {
|
|
|
420
462
|
includeDetails: CatalogDetails.features,
|
|
421
463
|
});
|
|
422
464
|
});
|
|
465
|
+
|
|
466
|
+
it('updates registration status as expected', async () => {
|
|
467
|
+
const clock = sinon.useFakeTimers();
|
|
468
|
+
|
|
469
|
+
const delay = (secs) => () =>
|
|
470
|
+
new Promise((resolve) => {
|
|
471
|
+
setTimeout(resolve, secs * 1000);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
let i = 1;
|
|
475
|
+
sinon.stub(webex.meetings, 'fetchUserPreferredWebexSite').callsFake(delay(i++));
|
|
476
|
+
MeetingsUtil.checkH264Support.callsFake(delay(i++));
|
|
477
|
+
webex.meetings.startReachability.callsFake(delay(i++));
|
|
478
|
+
webex.internal.device.register.callsFake(delay(i++));
|
|
479
|
+
sinon.stub(webex.meetings, 'getGeoHint').callsFake(delay(i++));
|
|
480
|
+
webex.internal.mercury.connect.callsFake(delay(i++));
|
|
481
|
+
|
|
482
|
+
webex.canAuthorize = true;
|
|
483
|
+
webex.meetings.registered = false;
|
|
484
|
+
|
|
485
|
+
const registerPromise = webex.meetings.register({
|
|
486
|
+
includeDetails: CatalogDetails.features,
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
await clock.tick(1000);
|
|
490
|
+
await webex.meetings.fetchUserPreferredWebexSite;
|
|
491
|
+
assert.deepEqual(webex.meetings.registrationStatus, {
|
|
492
|
+
fetchWebexSite: true,
|
|
493
|
+
getGeoHint: false,
|
|
494
|
+
startReachability: false,
|
|
495
|
+
deviceRegister: false,
|
|
496
|
+
mercuryConnect: false,
|
|
497
|
+
checkH264Support: false,
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
await clock.tick(1000);
|
|
501
|
+
await MeetingsUtil.checkH264Support;
|
|
502
|
+
assert.deepEqual(webex.meetings.registrationStatus, {
|
|
503
|
+
fetchWebexSite: true,
|
|
504
|
+
getGeoHint: false,
|
|
505
|
+
startReachability: false,
|
|
506
|
+
deviceRegister: false,
|
|
507
|
+
mercuryConnect: false,
|
|
508
|
+
checkH264Support: true,
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
await clock.tick(1000);
|
|
512
|
+
await webex.meetings.startReachability;
|
|
513
|
+
assert.deepEqual(webex.meetings.registrationStatus, {
|
|
514
|
+
fetchWebexSite: true,
|
|
515
|
+
getGeoHint: false,
|
|
516
|
+
startReachability: true,
|
|
517
|
+
deviceRegister: false,
|
|
518
|
+
mercuryConnect: false,
|
|
519
|
+
checkH264Support: true,
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
await clock.tick(1000);
|
|
523
|
+
await webex.internal.device.register;
|
|
524
|
+
assert.deepEqual(webex.meetings.registrationStatus, {
|
|
525
|
+
fetchWebexSite: true,
|
|
526
|
+
getGeoHint: false,
|
|
527
|
+
startReachability: true,
|
|
528
|
+
deviceRegister: true,
|
|
529
|
+
mercuryConnect: false,
|
|
530
|
+
checkH264Support: true,
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
await clock.tick(1000);
|
|
534
|
+
await webex.meetings.getGeoHint;
|
|
535
|
+
assert.deepEqual(webex.meetings.registrationStatus, {
|
|
536
|
+
fetchWebexSite: true,
|
|
537
|
+
getGeoHint: true,
|
|
538
|
+
startReachability: true,
|
|
539
|
+
deviceRegister: true,
|
|
540
|
+
mercuryConnect: false,
|
|
541
|
+
checkH264Support: true,
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
await clock.tick(6000);
|
|
545
|
+
await webex.internal.mercury.connect;
|
|
546
|
+
assert.deepEqual(webex.meetings.registrationStatus, {
|
|
547
|
+
fetchWebexSite: true,
|
|
548
|
+
getGeoHint: true,
|
|
549
|
+
startReachability: true,
|
|
550
|
+
deviceRegister: true,
|
|
551
|
+
mercuryConnect: true,
|
|
552
|
+
checkH264Support: true,
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
await registerPromise;
|
|
556
|
+
|
|
557
|
+
clock.restore();
|
|
558
|
+
});
|
|
423
559
|
});
|
|
424
560
|
|
|
425
561
|
describe('#unregister', () => {
|
|
@@ -440,27 +576,36 @@ describe('plugin-meetings', () => {
|
|
|
440
576
|
});
|
|
441
577
|
});
|
|
442
578
|
|
|
443
|
-
it('rejects when device.unregister fails', () => {
|
|
579
|
+
it('rejects when device.unregister fails', async () => {
|
|
444
580
|
webex.meetings.registered = true;
|
|
445
581
|
webex.internal.device.unregister = sinon.stub().returns(Promise.reject());
|
|
446
|
-
assert.isRejected(webex.meetings.unregister());
|
|
582
|
+
await assert.isRejected(webex.meetings.unregister());
|
|
447
583
|
});
|
|
448
584
|
|
|
449
|
-
it('rejects when mercury.disconnect fails', () => {
|
|
585
|
+
it('rejects when mercury.disconnect fails', async () => {
|
|
450
586
|
webex.meetings.registered = true;
|
|
451
587
|
webex.internal.mercury.disconnect = sinon.stub().returns(Promise.reject());
|
|
452
|
-
assert.isRejected(webex.meetings.unregister());
|
|
588
|
+
await assert.isRejected(webex.meetings.unregister());
|
|
453
589
|
});
|
|
454
590
|
|
|
455
|
-
it('resolves immediately if
|
|
591
|
+
it('resolves immediately if not registered', (done) => {
|
|
456
592
|
webex.meetings.registered = false;
|
|
457
593
|
webex.meetings.unregister().then(() => {
|
|
458
|
-
assert.notCalled(webex.internal.device.
|
|
459
|
-
assert.notCalled(webex.internal.mercury.
|
|
594
|
+
assert.notCalled(webex.internal.device.unregister);
|
|
595
|
+
assert.notCalled(webex.internal.mercury.disconnect);
|
|
460
596
|
assert.isFalse(webex.meetings.registered);
|
|
461
597
|
done();
|
|
462
598
|
});
|
|
463
599
|
});
|
|
600
|
+
|
|
601
|
+
it('resets registration status', (done) => {
|
|
602
|
+
webex.meetings.registered = true;
|
|
603
|
+
webex.meetings.registrationStatus = {foo: 'bar'};
|
|
604
|
+
webex.meetings.unregister().then(() => {
|
|
605
|
+
assert.deepEqual(webex.meetings.registrationStatus, INITIAL_REGISTRATION_STATUS);
|
|
606
|
+
done();
|
|
607
|
+
});
|
|
608
|
+
});
|
|
464
609
|
});
|
|
465
610
|
|
|
466
611
|
describe('virtual background effect', () => {
|
|
@@ -1921,6 +2066,11 @@ describe('plugin-meetings', () => {
|
|
|
1921
2066
|
debugLogMessage:
|
|
1922
2067
|
'Meetings:index#createMeeting --> Debug PermissionError: Not allowed to execute the function, some properties on server, or local client state do not allow you to complete this action. fetching /meetingInfo for creation.',
|
|
1923
2068
|
},
|
|
2069
|
+
{
|
|
2070
|
+
error: new JoinForbiddenError(),
|
|
2071
|
+
debugLogMessage:
|
|
2072
|
+
'Meetings:index#createMeeting --> Debug JoinForbiddenError: Meeting join forbidden. fetching /meetingInfo for creation.',
|
|
2073
|
+
},
|
|
1924
2074
|
{
|
|
1925
2075
|
error: new Error(),
|
|
1926
2076
|
infoLogMessage: true,
|
|
@@ -1985,6 +2135,8 @@ describe('plugin-meetings', () => {
|
|
|
1985
2135
|
const meetingIds = {
|
|
1986
2136
|
meetingId: meeting.id,
|
|
1987
2137
|
correlationId: meeting.correlationId,
|
|
2138
|
+
roles: meeting.roles,
|
|
2139
|
+
callStateForMetrics: meeting.callStateForMetrics,
|
|
1988
2140
|
};
|
|
1989
2141
|
|
|
1990
2142
|
webex.meetings.destroy(meeting, test1);
|
|
@@ -2021,6 +2173,8 @@ describe('plugin-meetings', () => {
|
|
|
2021
2173
|
|
|
2022
2174
|
assert.equal(deletedMeetingInfo.id, meetingIds.meetingId);
|
|
2023
2175
|
assert.equal(deletedMeetingInfo.correlationId, meetingIds.correlationId);
|
|
2176
|
+
assert.equal(deletedMeetingInfo.roles, meetingIds.roles);
|
|
2177
|
+
assert.equal(deletedMeetingInfo.callStateForMetrics, meetingIds.callStateForMetrics);
|
|
2024
2178
|
});
|
|
2025
2179
|
});
|
|
2026
2180
|
|
|
@@ -2092,7 +2246,7 @@ describe('plugin-meetings', () => {
|
|
|
2092
2246
|
);
|
|
2093
2247
|
});
|
|
2094
2248
|
|
|
2095
|
-
const setup = ({me = {
|
|
2249
|
+
const setup = ({me = {type: 'validuser'}, user} = {}) => {
|
|
2096
2250
|
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
2097
2251
|
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
2098
2252
|
|
|
@@ -2113,9 +2267,9 @@ describe('plugin-meetings', () => {
|
|
|
2113
2267
|
|
|
2114
2268
|
it('should not call request.getMeetingPreferences if user is a guest', async () => {
|
|
2115
2269
|
setup({me: {type: 'appuser'}});
|
|
2116
|
-
|
|
2270
|
+
|
|
2117
2271
|
await webex.meetings.fetchUserPreferredWebexSite();
|
|
2118
|
-
|
|
2272
|
+
|
|
2119
2273
|
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
2120
2274
|
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
2121
2275
|
assert.notCalled(webex.internal.services.getMeetingPreferences);
|
|
@@ -290,4 +290,14 @@ describe('plugin-meetings', () => {
|
|
|
290
290
|
assert.equal(MeetingsUtil.isValidBreakoutLocus(newLocus), true);
|
|
291
291
|
});
|
|
292
292
|
});
|
|
293
|
+
|
|
294
|
+
describe('#getMediaServer', () => {
|
|
295
|
+
it('returns the contents of o-line lower cased', () => {
|
|
296
|
+
const sdp1 = 'v=0\r\no=homer 0 1 IN IP4 23.89.67.81\r\ns=-\r\nc=IN IP4 23.89.67.81\r\nb=TIAS:128000\r\nt=0 0\r\na=ice-lite\r\n'
|
|
297
|
+
assert.equal(MeetingsUtil.getMediaServer(sdp1), 'homer');
|
|
298
|
+
|
|
299
|
+
const sdp2 = 'v=0\r\no=HOMER 0 1 IN IP4 23.89.67.81\r\ns=-\r\nc=IN IP4 23.89.67.81\r\nb=TIAS:128000\r\nt=0 0\r\na=ice-lite\r\n'
|
|
300
|
+
assert.equal(MeetingsUtil.getMediaServer(sdp2), 'homer');
|
|
301
|
+
});
|
|
302
|
+
})
|
|
293
303
|
});
|
|
@@ -5,13 +5,13 @@ import {_SEND_RECEIVE_, _RECEIVE_ONLY_} from '../../../../src/constants';
|
|
|
5
5
|
|
|
6
6
|
describe('plugin-meetings', () => {
|
|
7
7
|
describe('isHandRaised', () => {
|
|
8
|
-
it('throws error when there is no participant', () => {
|
|
8
|
+
it('throws an error when there is no participant', () => {
|
|
9
9
|
assert.throws(() => {
|
|
10
10
|
MemberUtil.isHandRaised();
|
|
11
11
|
}, 'Raise hand could not be processed, participant is undefined.');
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
it('returns false when controls
|
|
14
|
+
it('returns false when controls are not present', () => {
|
|
15
15
|
const participant = {};
|
|
16
16
|
|
|
17
17
|
assert.isFalse(MemberUtil.isHandRaised(participant));
|
|
@@ -51,7 +51,7 @@ describe('plugin-meetings', () => {
|
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
describe('MemberUtil.canReclaimHost', () => {
|
|
54
|
-
it('throws error when there is no participant', () => {
|
|
54
|
+
it('throws an error when there is no participant', () => {
|
|
55
55
|
assert.throws(() => {
|
|
56
56
|
MemberUtil.canReclaimHost();
|
|
57
57
|
}, 'canReclaimHostRole could not be processed, participant is undefined.');
|
|
@@ -352,8 +352,49 @@ describe('plugin-meetings', () => {
|
|
|
352
352
|
});
|
|
353
353
|
});
|
|
354
354
|
|
|
355
|
+
describe('MemberUtil.isBrb', () => {
|
|
356
|
+
it('returns true when brb is enabled', () => {
|
|
357
|
+
const participant = {
|
|
358
|
+
controls: {
|
|
359
|
+
brb: {
|
|
360
|
+
enabled: true,
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
assert.isTrue(MemberUtil.isBrb(participant));
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('returns false when brb is disabled', () => {
|
|
369
|
+
const participant = {
|
|
370
|
+
controls: {
|
|
371
|
+
brb: {
|
|
372
|
+
enabled: false,
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
assert.isFalse(MemberUtil.isBrb(participant));
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
it('returns false when brb is not present', () => {
|
|
382
|
+
const participant = {
|
|
383
|
+
controls: {},
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
assert.isFalse(MemberUtil.isBrb(participant));
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('returns false when controls is not present', () => {
|
|
390
|
+
const participant = {};
|
|
391
|
+
|
|
392
|
+
assert.isFalse(MemberUtil.isBrb(participant));
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
355
396
|
describe('MemberUtil.isBreakoutsSupported', () => {
|
|
356
|
-
it('throws error when there is no participant', () => {
|
|
397
|
+
it('throws an error when there is no participant', () => {
|
|
357
398
|
assert.throws(() => {
|
|
358
399
|
MemberUtil.isBreakoutsSupported();
|
|
359
400
|
}, 'Breakout support could not be processed, participant is undefined.');
|
|
@@ -377,7 +418,7 @@ describe('plugin-meetings', () => {
|
|
|
377
418
|
});
|
|
378
419
|
|
|
379
420
|
describe('MemberUtil.isLiveAnnotationSupported', () => {
|
|
380
|
-
it('throws error when there is no participant', () => {
|
|
421
|
+
it('throws an error when there is no participant', () => {
|
|
381
422
|
assert.throws(() => {
|
|
382
423
|
MemberUtil.isLiveAnnotationSupported();
|
|
383
424
|
}, 'LiveAnnotation support could not be processed, participant is undefined.');
|
|
@@ -401,7 +442,7 @@ describe('plugin-meetings', () => {
|
|
|
401
442
|
});
|
|
402
443
|
|
|
403
444
|
describe('MemberUtil.isInterpretationSupported', () => {
|
|
404
|
-
it('throws error when there is no participant', () => {
|
|
445
|
+
it('throws an error when there is no participant', () => {
|
|
405
446
|
assert.throws(() => {
|
|
406
447
|
MemberUtil.isInterpretationSupported();
|
|
407
448
|
}, 'Interpretation support could not be processed, participant is undefined.');
|
|
@@ -432,7 +473,7 @@ describe('plugin-meetings', () => {
|
|
|
432
473
|
};
|
|
433
474
|
|
|
434
475
|
describe('MemberUtil.isAudioMuted', () => {
|
|
435
|
-
it('throws error when there is no participant', () => {
|
|
476
|
+
it('throws an error when there is no participant', () => {
|
|
436
477
|
assert.throws(() => {
|
|
437
478
|
MemberUtil.isAudioMuted();
|
|
438
479
|
}, 'Audio could not be processed, participant is undefined.');
|
|
@@ -475,7 +516,7 @@ describe('plugin-meetings', () => {
|
|
|
475
516
|
});
|
|
476
517
|
|
|
477
518
|
describe('MemberUtil.isVideoMuted', () => {
|
|
478
|
-
it('throws error when there is no participant', () => {
|
|
519
|
+
it('throws an error when there is no participant', () => {
|
|
479
520
|
assert.throws(() => {
|
|
480
521
|
MemberUtil.isVideoMuted();
|
|
481
522
|
}, 'Video could not be processed, participant is undefined.');
|
|
@@ -519,7 +560,7 @@ describe('plugin-meetings', () => {
|
|
|
519
560
|
});
|
|
520
561
|
|
|
521
562
|
describe('extractMediaStatus', () => {
|
|
522
|
-
it('throws error when there is no participant', () => {
|
|
563
|
+
it('throws an error when there is no participant', () => {
|
|
523
564
|
assert.throws(() => {
|
|
524
565
|
MemberUtil.extractMediaStatus()
|
|
525
566
|
}, 'Media status could not be extracted, participant is undefined.');
|
|
@@ -529,7 +570,7 @@ describe('extractMediaStatus', () => {
|
|
|
529
570
|
const participant = {
|
|
530
571
|
status: {}
|
|
531
572
|
};
|
|
532
|
-
|
|
573
|
+
|
|
533
574
|
const mediaStatus = MemberUtil.extractMediaStatus(participant)
|
|
534
575
|
|
|
535
576
|
assert.deepEqual(mediaStatus, {audio: undefined, video: undefined});
|
|
@@ -542,7 +583,7 @@ describe('extractMediaStatus', () => {
|
|
|
542
583
|
videoStatus: 'SENDRECV'
|
|
543
584
|
}
|
|
544
585
|
};
|
|
545
|
-
|
|
586
|
+
|
|
546
587
|
const mediaStatus = MemberUtil.extractMediaStatus(participant)
|
|
547
588
|
|
|
548
589
|
assert.deepEqual(mediaStatus, {audio: 'RECVONLY', video: 'SENDRECV'});
|
|
@@ -262,5 +262,100 @@ describe('plugin-meetings', () => {
|
|
|
262
262
|
testParams(false);
|
|
263
263
|
});
|
|
264
264
|
});
|
|
265
|
+
|
|
266
|
+
describe('#getAddMemberBody', () => {
|
|
267
|
+
it('returns the correct body with email address and roles', () => {
|
|
268
|
+
const options = {
|
|
269
|
+
invitee: {
|
|
270
|
+
emailAddress: 'test@example.com',
|
|
271
|
+
roles: ['role1', 'role2'],
|
|
272
|
+
},
|
|
273
|
+
alertIfActive: true,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
277
|
+
invitees: [
|
|
278
|
+
{
|
|
279
|
+
address: 'test@example.com',
|
|
280
|
+
roles: ['role1', 'role2'],
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
alertIfActive: true,
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('returns the correct body with phone number and no roles', () => {
|
|
288
|
+
const options = {
|
|
289
|
+
invitee: {
|
|
290
|
+
phoneNumber: '1234567890',
|
|
291
|
+
},
|
|
292
|
+
alertIfActive: false,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
296
|
+
invitees: [
|
|
297
|
+
{
|
|
298
|
+
address: '1234567890',
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
alertIfActive: false,
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('returns the correct body with fallback to email', () => {
|
|
306
|
+
const options = {
|
|
307
|
+
invitee: {
|
|
308
|
+
email: 'fallback@example.com',
|
|
309
|
+
},
|
|
310
|
+
alertIfActive: true,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
314
|
+
invitees: [
|
|
315
|
+
{
|
|
316
|
+
address: 'fallback@example.com',
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
alertIfActive: true,
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('handles missing `alertIfActive` gracefully', () => {
|
|
324
|
+
const options = {
|
|
325
|
+
invitee: {
|
|
326
|
+
emailAddress: 'test@example.com',
|
|
327
|
+
roles: ['role1'],
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
332
|
+
invitees: [
|
|
333
|
+
{
|
|
334
|
+
address: 'test@example.com',
|
|
335
|
+
roles: ['role1'],
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
alertIfActive: undefined,
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('ignores roles if not provided', () => {
|
|
343
|
+
const options = {
|
|
344
|
+
invitee: {
|
|
345
|
+
emailAddress: 'test@example.com',
|
|
346
|
+
},
|
|
347
|
+
alertIfActive: false,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
assert.deepEqual(MembersUtil.getAddMemberBody(options), {
|
|
351
|
+
invitees: [
|
|
352
|
+
{
|
|
353
|
+
address: 'test@example.com',
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
alertIfActive: false,
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
});
|
|
265
360
|
});
|
|
266
361
|
});
|