@webex/plugin-meetings 3.7.0-next.63 → 3.7.0-next.64

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.
@@ -70,6 +70,8 @@ declare const BEHAVIORAL_METRICS: {
70
70
  JOIN_WEBINAR_ERROR: string;
71
71
  GUEST_ENTERED_LOBBY: string;
72
72
  GUEST_EXITED_LOBBY: string;
73
+ VERIFY_REGISTRATION_ID_SUCCESS: string;
74
+ VERIFY_REGISTRATION_ID_ERROR: string;
73
75
  JOIN_FORBIDDEN_ERROR: string;
74
76
  };
75
77
  export { BEHAVIORAL_METRICS as default };
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.7.0-next.63"
461
+ version: "3.7.0-next.64"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.7.0-next.63",
46
+ "@webex/plugin-meetings": "3.7.0-next.64",
47
47
  "@webex/plugin-rooms": "3.7.0-next.25",
48
48
  "@webex/test-helper-chai": "3.7.0-next.18",
49
49
  "@webex/test-helper-mocha": "3.7.0-next.18",
@@ -71,7 +71,7 @@
71
71
  "@webex/internal-plugin-metrics": "3.7.0-next.18",
72
72
  "@webex/internal-plugin-support": "3.7.0-next.26",
73
73
  "@webex/internal-plugin-user": "3.7.0-next.18",
74
- "@webex/internal-plugin-voicea": "3.7.0-next.63",
74
+ "@webex/internal-plugin-voicea": "3.7.0-next.64",
75
75
  "@webex/media-helpers": "3.7.0-next.24",
76
76
  "@webex/plugin-people": "3.7.0-next.23",
77
77
  "@webex/plugin-rooms": "3.7.0-next.25",
@@ -92,5 +92,5 @@
92
92
  "//": [
93
93
  "TODO: upgrade jwt-decode when moving to node 18"
94
94
  ],
95
- "version": "3.7.0-next.63"
95
+ "version": "3.7.0-next.64"
96
96
  }
package/src/constants.ts CHANGED
@@ -202,7 +202,7 @@ export const RETRY_TIMEOUT = 3000;
202
202
  export const ICE_AND_DTLS_CONNECTION_TIMEOUT = 20000;
203
203
  export const ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT = 35000;
204
204
  export const WEBINAR_ERROR_WEBCAST = [403026];
205
- export const WEBINAR_ERROR_REGISTRATIONID = [403037, 403137];
205
+ export const WEBINAR_ERROR_REGISTRATION_ID = [403037, 403137];
206
206
  export const JOIN_BEFORE_HOST = 403003;
207
207
 
208
208
  // ******************** REGEX **********************
@@ -1331,14 +1331,22 @@ export const PASSWORD_STATUS = {
1331
1331
  VERIFIED: 'VERIFIED', // client has already provided the password and it has been verified, client can proceed to call join()
1332
1332
  };
1333
1333
 
1334
+ export const REGISTRATION_ID_STATUS = {
1335
+ NOT_REQUIRED: 'NOT_REQUIRED', // registrationId is not required to join the meeting
1336
+ REQUIRED: 'REQUIRED', // client needs to provide the registrationId by calling verifyRegistrationId() before calling join()
1337
+ UNKNOWN: 'UNKNOWN', // we are waiting for information from the backend if registrationId is required or not
1338
+ VERIFIED: 'VERIFIED', // client has already provided the registrationId and it has been verified, client can proceed to call join()
1339
+ };
1340
+
1334
1341
  export const MEETING_INFO_FAILURE_REASON = {
1335
1342
  NONE: 'NONE', // meeting info was retrieved succesfully
1336
1343
  WRONG_PASSWORD: 'WRONG_PASSWORD', // meeting requires password and no password or wrong one was provided
1337
1344
  WRONG_CAPTCHA: 'WRONG_CAPTCHA', // wbxappapi requires a captcha code or a wrong captcha code was provided
1345
+ WRONG_REGISTRATION_ID: 'WRONG_REGISTRATION_ID', // meeting requires registrationId and no registrationId or wrong one was provided
1338
1346
  POLICY: 'POLICY', // meeting info request violates some meeting policy
1339
1347
  WEBINAR_REGISTRATION: 'WEBINAR_REGISTRATION', // webinar need registration
1340
1348
  NEED_JOIN_WITH_WEBCAST: 'NEED_JOIN_WITH_WEBCAST', // webinar need using webcast join
1341
- WEBINAR_NEED_REGISTRATIONID: 'WEBINAR_NEED_REGISTRATIONID', // webinar need registrationID
1349
+ WEBINAR_NEED_REGISTRATION_ID: 'WEBINAR_NEED_REGISTRATION_ID', // webinar need registrationID
1342
1350
  NOT_REACH_JBH: 'NOT_REACH_JBH', // Meeting is not allow to access since not reach JBH (join before host) time
1343
1351
  JOIN_FORBIDDEN: 'JOIN_FORBIDDEN', // meeting is not allow join
1344
1352
  OTHER: 'OTHER', // any other error (network, etc)
@@ -122,8 +122,9 @@ import {
122
122
  ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
123
123
  NAMED_MEDIA_GROUP_TYPE_AUDIO,
124
124
  WEBINAR_ERROR_WEBCAST,
125
- WEBINAR_ERROR_REGISTRATIONID,
125
+ WEBINAR_ERROR_REGISTRATION_ID,
126
126
  JOIN_BEFORE_HOST,
127
+ REGISTRATION_ID_STATUS,
127
128
  } from '../constants';
128
129
  import BEHAVIORAL_METRICS from '../metrics/constants';
129
130
  import ParameterError from '../common/errors/parameter';
@@ -256,6 +257,7 @@ export enum ScreenShareFloorStatus {
256
257
 
257
258
  type FetchMeetingInfoParams = {
258
259
  password?: string;
260
+ registrationId?: string;
259
261
  captchaCode?: string;
260
262
  extraParams?: Record<string, any>;
261
263
  sendCAevents?: boolean;
@@ -650,6 +652,7 @@ export default class Meeting extends StatelessWebexPlugin {
650
652
  turnServerUsed: boolean;
651
653
  areVoiceaEventsSetup = false;
652
654
  isMoveToInProgress = false;
655
+ registrationIdStatus: string;
653
656
  brbState: BrbState;
654
657
 
655
658
  voiceaListenerCallbacks: object = {
@@ -1347,6 +1350,16 @@ export default class Meeting extends StatelessWebexPlugin {
1347
1350
  */
1348
1351
  this.passwordStatus = PASSWORD_STATUS.UNKNOWN;
1349
1352
 
1353
+ /**
1354
+ * registrationId status. If it's REGISTRATIONID_STATUS.REQUIRED then verifyRegistrationId() needs to be called
1355
+ * with the correct registrationId before calling join()
1356
+ * @instance
1357
+ * @type {REGISTRATION_ID_STATUS}
1358
+ * @public
1359
+ * @memberof Meeting
1360
+ */
1361
+ this.registrationIdStatus = REGISTRATION_ID_STATUS.UNKNOWN;
1362
+
1350
1363
  /**
1351
1364
  * Information about required captcha. If null, then no captcha is required. status. If it's PASSWORD_STATUS.REQUIRED then verifyPassword() needs to be called
1352
1365
  * with the correct password before calling join()
@@ -1659,6 +1672,15 @@ export default class Meeting extends StatelessWebexPlugin {
1659
1672
  this.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
1660
1673
  }
1661
1674
 
1675
+ if (
1676
+ this.registrationIdStatus === REGISTRATION_ID_STATUS.REQUIRED ||
1677
+ this.registrationIdStatus === REGISTRATION_ID_STATUS.VERIFIED
1678
+ ) {
1679
+ this.registrationIdStatus = REGISTRATION_ID_STATUS.VERIFIED;
1680
+ } else {
1681
+ this.registrationIdStatus = REGISTRATION_ID_STATUS.NOT_REQUIRED;
1682
+ }
1683
+
1662
1684
  Trigger.trigger(
1663
1685
  this,
1664
1686
  {
@@ -1702,7 +1724,12 @@ export default class Meeting extends StatelessWebexPlugin {
1702
1724
  * @private
1703
1725
  */
1704
1726
  private prepForFetchMeetingInfo(
1705
- {password = null, captchaCode = null, extraParams = {}}: FetchMeetingInfoParams,
1727
+ {
1728
+ password = null,
1729
+ registrationId = null,
1730
+ captchaCode = null,
1731
+ extraParams = {},
1732
+ }: FetchMeetingInfoParams,
1706
1733
  caller: string
1707
1734
  ): Promise<void> {
1708
1735
  // when fetch meeting info is called directly by the client, we want to clear out the random timer for sdk to do it
@@ -1742,6 +1769,7 @@ export default class Meeting extends StatelessWebexPlugin {
1742
1769
  captchaCode = null,
1743
1770
  extraParams = {},
1744
1771
  sendCAevents = false,
1772
+ registrationId = null,
1745
1773
  }): Promise<void> {
1746
1774
  try {
1747
1775
  const captchaInfo = captchaCode
@@ -1757,7 +1785,8 @@ export default class Meeting extends StatelessWebexPlugin {
1757
1785
  this.config.installedOrgID,
1758
1786
  this.locusId,
1759
1787
  extraParams,
1760
- {meetingId: this.id, sendCAevents}
1788
+ {meetingId: this.id, sendCAevents},
1789
+ registrationId
1761
1790
  );
1762
1791
 
1763
1792
  this.parseMeetingInfo(info?.body, this.destination, info?.errors);
@@ -1779,14 +1808,15 @@ export default class Meeting extends StatelessWebexPlugin {
1779
1808
  this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION;
1780
1809
  if (WEBINAR_ERROR_WEBCAST.includes(err.wbxAppApiCode)) {
1781
1810
  this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NEED_JOIN_WITH_WEBCAST;
1782
- } else if (WEBINAR_ERROR_REGISTRATIONID.includes(err.wbxAppApiCode)) {
1783
- this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATIONID;
1811
+ } else if (WEBINAR_ERROR_REGISTRATION_ID.includes(err.wbxAppApiCode)) {
1812
+ this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATION_ID;
1784
1813
  }
1785
1814
  this.meetingInfoFailureCode = err.wbxAppApiCode;
1786
1815
 
1787
1816
  if (err.meetingInfo) {
1788
1817
  this.meetingInfo = err.meetingInfo;
1789
1818
  }
1819
+ this.requiredCaptcha = null;
1790
1820
 
1791
1821
  throw new JoinWebinarError();
1792
1822
  } else if (err instanceof MeetingInfoV2JoinForbiddenError) {
@@ -1831,9 +1861,13 @@ export default class Meeting extends StatelessWebexPlugin {
1831
1861
  `Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - captcha required (code=${err?.body?.code}).`
1832
1862
  );
1833
1863
 
1834
- this.meetingInfoFailureReason = this.requiredCaptcha
1835
- ? MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA
1836
- : MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
1864
+ if (this.requiredCaptcha) {
1865
+ this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA;
1866
+ } else if (err.isRegistrationIdRequired) {
1867
+ this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_REGISTRATION_ID;
1868
+ } else {
1869
+ this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
1870
+ }
1837
1871
 
1838
1872
  this.meetingInfoFailureCode = err.wbxAppApiCode;
1839
1873
 
@@ -1841,6 +1875,10 @@ export default class Meeting extends StatelessWebexPlugin {
1841
1875
  this.passwordStatus = PASSWORD_STATUS.REQUIRED;
1842
1876
  }
1843
1877
 
1878
+ if (err.isRegistrationIdRequired) {
1879
+ this.registrationIdStatus = REGISTRATION_ID_STATUS.REQUIRED;
1880
+ }
1881
+
1844
1882
  this.requiredCaptcha = err.captchaInfo;
1845
1883
  throw new CaptchaError();
1846
1884
  } else {
@@ -1981,6 +2019,48 @@ export default class Meeting extends StatelessWebexPlugin {
1981
2019
  });
1982
2020
  }
1983
2021
 
2022
+ /**
2023
+ * Checks if the supplied registrationId is correct. It returns a promise with information whether the
2024
+ * registrationId and captcha code were correct or not.
2025
+ * @param {String | undefined} registrationId - can be undefined if only captcha was required
2026
+ * @param {String | undefined} captchaCode - can be undefined if captcha was not required by the server
2027
+ * @param {Boolean} sendCAevents - whether Call Analyzer events should be sent when fetching meeting information
2028
+ * @public
2029
+ * @memberof Meeting
2030
+ * @returns {Promise<{isRegistrationIdValid: boolean, requiredCaptcha: boolean, failureReason: MEETING_INFO_FAILURE_REASON}>}
2031
+ */
2032
+ public verifyRegistrationId(registrationId: string, captchaCode: string, sendCAevents = false) {
2033
+ return this.fetchMeetingInfo({
2034
+ registrationId,
2035
+ captchaCode,
2036
+ sendCAevents,
2037
+ })
2038
+ .then(() => {
2039
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.VERIFY_REGISTRATION_ID_SUCCESS);
2040
+
2041
+ return {
2042
+ isRegistrationIdValid: true,
2043
+ requiredCaptcha: null,
2044
+ failureReason: MEETING_INFO_FAILURE_REASON.NONE,
2045
+ };
2046
+ })
2047
+ .catch((error) => {
2048
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.VERIFY_REGISTRATION_ID_ERROR);
2049
+
2050
+ if (error instanceof JoinWebinarError || error instanceof CaptchaError) {
2051
+ return {
2052
+ isRegistrationIdValid: this.registrationIdStatus === REGISTRATION_ID_STATUS.VERIFIED,
2053
+ requiredCaptcha: this.requiredCaptcha,
2054
+ failureReason:
2055
+ error instanceof JoinWebinarError
2056
+ ? MEETING_INFO_FAILURE_REASON.WRONG_REGISTRATION_ID
2057
+ : this.meetingInfoFailureReason,
2058
+ };
2059
+ }
2060
+ throw error;
2061
+ });
2062
+ }
2063
+
1984
2064
  /**
1985
2065
  * Refreshes the captcha. As a result the meeting will have new captcha id, image and audio.
1986
2066
  * If the refresh operation fails, meeting remains with the old captcha properties.
@@ -17,6 +17,8 @@ const CAPTCHA_ERROR_DEFAULT_MESSAGE =
17
17
  const ADHOC_MEETING_DEFAULT_ERROR =
18
18
  'Failed starting the adhoc meeting, Please contact support team ';
19
19
  const CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES = [423005, 423006];
20
+ const CAPTCHA_ERROR_REQUIRES_REGISTRATION_ID_CODES = [423007];
21
+
20
22
  const POLICY_ERROR_CODES = [403049, 403104, 403103, 403048, 403102, 403101];
21
23
  const JOIN_FORBIDDEN_CODES = [403003];
22
24
  /**
@@ -113,6 +115,7 @@ export class MeetingInfoV2PolicyError extends Error {
113
115
  export class MeetingInfoV2CaptchaError extends Error {
114
116
  captchaInfo: any;
115
117
  isPasswordRequired: any;
118
+ isRegistrationIdRequired: any;
116
119
  sdkMessage: any;
117
120
  wbxAppApiCode: any;
118
121
  body: any;
@@ -134,6 +137,8 @@ export class MeetingInfoV2CaptchaError extends Error {
134
137
  this.stack = new Error().stack;
135
138
  this.wbxAppApiCode = wbxAppApiErrorCode;
136
139
  this.isPasswordRequired = CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES.includes(wbxAppApiErrorCode);
140
+ this.isRegistrationIdRequired =
141
+ CAPTCHA_ERROR_REQUIRES_REGISTRATION_ID_CODES.includes(wbxAppApiErrorCode);
137
142
  this.captchaInfo = captchaInfo;
138
143
  }
139
144
  }
@@ -370,6 +375,7 @@ export default class MeetingInfoV2 {
370
375
  * @param {String} locusId
371
376
  * @param {Object} extraParams
372
377
  * @param {Object} options
378
+ * @param {String} registrationId
373
379
  * @returns {Promise} returns a meeting info object
374
380
  * @public
375
381
  * @memberof MeetingInfo
@@ -385,7 +391,8 @@ export default class MeetingInfoV2 {
385
391
  installedOrgID = null,
386
392
  locusId = null,
387
393
  extraParams: object = {},
388
- options: {meetingId?: string; sendCAevents?: boolean} = {}
394
+ options: {meetingId?: string; sendCAevents?: boolean} = {},
395
+ registrationId: string = null
389
396
  ) {
390
397
  const {meetingId, sendCAevents} = options;
391
398
 
@@ -410,6 +417,7 @@ export default class MeetingInfoV2 {
410
417
  installedOrgID,
411
418
  locusId,
412
419
  extraParams,
420
+ registrationId,
413
421
  });
414
422
 
415
423
  // If the body only contains the default properties, we don't have enough to
@@ -228,8 +228,16 @@ export default class MeetingInfoUtil {
228
228
  * @returns {Object} returns an object with {resource, method}
229
229
  */
230
230
  static getRequestBody(options: {type: DESTINATION_TYPE; destination: object} | any) {
231
- const {type, destination, password, captchaInfo, installedOrgID, locusId, extraParams} =
232
- options;
231
+ const {
232
+ type,
233
+ destination,
234
+ password,
235
+ captchaInfo,
236
+ installedOrgID,
237
+ locusId,
238
+ extraParams,
239
+ registrationId,
240
+ } = options;
233
241
  const body: any = {
234
242
  ...DEFAULT_MEETING_INFO_REQUEST_BODY,
235
243
  ...extraParams,
@@ -271,6 +279,10 @@ export default class MeetingInfoUtil {
271
279
  body.password = password;
272
280
  }
273
281
 
282
+ if (registrationId) {
283
+ body.registrationId = registrationId;
284
+ }
285
+
274
286
  if (captchaInfo) {
275
287
  body.captchaID = captchaInfo.id;
276
288
  body.captchaVerifyCode = captchaInfo.code;
@@ -73,6 +73,8 @@ const BEHAVIORAL_METRICS = {
73
73
  JOIN_WEBINAR_ERROR: 'js_sdk_join_webinar_error',
74
74
  GUEST_ENTERED_LOBBY: 'js_sdk_guest_entered_lobby',
75
75
  GUEST_EXITED_LOBBY: 'js_sdk_guest_exited_lobby',
76
+ VERIFY_REGISTRATION_ID_SUCCESS: 'js_sdk_verify_registrationId_success',
77
+ VERIFY_REGISTRATION_ID_ERROR: 'js_sdk_verify_registrationId_error',
76
78
  JOIN_FORBIDDEN_ERROR: 'js_sdk_join_forbidden_error',
77
79
  };
78
80
 
@@ -6792,7 +6792,7 @@ describe('plugin-meetings', () => {
6792
6792
  assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
6793
6793
  assert.equal(
6794
6794
  meeting.meetingInfoFailureReason,
6795
- MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATIONID
6795
+ MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATION_ID
6796
6796
  );
6797
6797
  });
6798
6798
  });
@@ -6852,7 +6852,8 @@ describe('plugin-meetings', () => {
6852
6852
  'fake-installed-org-id',
6853
6853
  'locus-id',
6854
6854
  {extraParam1: 'value1', permissionToken: FAKE_PERMISSION_TOKEN},
6855
- {meetingId: meeting.id, sendCAevents: true}
6855
+ {meetingId: meeting.id, sendCAevents: true},
6856
+ null
6856
6857
  );
6857
6858
  assert.deepEqual(meeting.meetingInfo, {
6858
6859
  ...FAKE_MEETING_INFO,
@@ -6897,7 +6898,8 @@ describe('plugin-meetings', () => {
6897
6898
  'fake-installed-org-id',
6898
6899
  'locus-id',
6899
6900
  {extraParam1: 'value1', permissionToken: FAKE_PERMISSION_TOKEN},
6900
- {meetingId: meeting.id, sendCAevents: true}
6901
+ {meetingId: meeting.id, sendCAevents: true},
6902
+ null
6901
6903
  );
6902
6904
  assert.deepEqual(meeting.meetingInfo, {
6903
6905
  ...FAKE_MEETING_INFO,
@@ -6951,7 +6953,8 @@ describe('plugin-meetings', () => {
6951
6953
  extraParam1: 'value1',
6952
6954
  permissionToken: FAKE_PERMISSION_TOKEN,
6953
6955
  },
6954
- {meetingId: meeting.id, sendCAevents: true}
6956
+ {meetingId: meeting.id, sendCAevents: true},
6957
+ null
6955
6958
  );
6956
6959
  assert.deepEqual(meeting.meetingInfo, {
6957
6960
  ...FAKE_MEETING_INFO,
@@ -13309,4 +13312,53 @@ describe('plugin-meetings', () => {
13309
13312
  assert.equal(meeting.mediaProperties.webrtcMediaConnection.mediaServer, 'linus'); // check that it hasn't been overwritten
13310
13313
  });
13311
13314
  });
13315
+
13316
+ describe('#verifyRegistrationId', () => {
13317
+ it('calls fetchMeetingInfo() with the passed registrationId and captcha code', async () => {
13318
+ // simulate successful case
13319
+ meeting.fetchMeetingInfo = sinon.stub().resolves();
13320
+ const result = await meeting.verifyRegistrationId('registrationId', 'captcha id');
13321
+
13322
+ assert(Metrics.sendBehavioralMetric.calledOnce);
13323
+ assert.calledWith(
13324
+ Metrics.sendBehavioralMetric,
13325
+ BEHAVIORAL_METRICS.VERIFY_REGISTRATION_ID_SUCCESS
13326
+ );
13327
+ assert.equal(result.isRegistrationIdValid, true);
13328
+ assert.equal(result.requiredCaptcha, null);
13329
+ assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.NONE);
13330
+ assert.calledWith(meeting.fetchMeetingInfo, {
13331
+ registrationId: 'registrationId',
13332
+ captchaCode: 'captcha id',
13333
+ sendCAevents: false,
13334
+ });
13335
+ });
13336
+ it('handles registrationIdError returned by fetchMeetingInfo', async () => {
13337
+ meeting.fetchMeetingInfo = sinon.stub().callsFake(() => {
13338
+ meeting.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_REGISTRATIONID;
13339
+
13340
+ return Promise.reject(new JoinWebinarError());
13341
+ });
13342
+ const result = await meeting.verifyRegistrationId('registrationId', 'captcha id');
13343
+
13344
+ assert.equal(result.isRegistrationIdValid, false);
13345
+ assert.equal(result.requiredCaptcha, null);
13346
+ assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_REGISTRATION_ID);
13347
+ });
13348
+ it('handles CaptchaError returned by fetchMeetingInfo', async () => {
13349
+ const FAKE_CAPTCHA = {captchaId: 'some catcha id...'};
13350
+
13351
+ meeting.fetchMeetingInfo = sinon.stub().callsFake(() => {
13352
+ meeting.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA;
13353
+ meeting.requiredCaptcha = FAKE_CAPTCHA;
13354
+
13355
+ return Promise.reject(new CaptchaError());
13356
+ });
13357
+ const result = await meeting.verifyRegistrationId('registrationId', 'captcha id');
13358
+
13359
+ assert.equal(result.isRegistrationIdValid, false);
13360
+ assert.deepEqual(result.requiredCaptcha, FAKE_CAPTCHA);
13361
+ assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
13362
+ });
13363
+ });
13312
13364
  });
@@ -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,