@webex/plugin-meetings 3.0.0-beta.253 → 3.0.0-beta.255

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.
@@ -62,7 +62,9 @@ var BEHAVIORAL_METRICS = {
62
62
  TURN_DISCOVERY_FAILURE: 'js_sdk_turn_discovery_failure',
63
63
  MEETING_INFO_POLICY_ERROR: 'js_sdk_meeting_info_policy_error',
64
64
  LOCUS_DELTA_SYNC_FAILED: 'js_sdk_locus_delta_sync_failed',
65
- LOCUS_DELTA_OUT_OF_ORDER: 'js_sdk_locus_delta_ooo'
65
+ LOCUS_DELTA_OUT_OF_ORDER: 'js_sdk_locus_delta_ooo',
66
+ PERMISSION_TOKEN_REFRESH: 'js_sdk_permission_token_refresh',
67
+ PERMISSION_TOKEN_REFRESH_ERROR: 'js_sdk_permission_token_refresh_error'
66
68
  };
67
69
  exports.default = BEHAVIORAL_METRICS;
68
70
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BEHAVIORAL_METRICS","MEETINGS_REGISTRATION_FAILED","MEETINGS_REGISTRATION_SUCCESS","MERCURY_CONNECTION_FAILURE","MERCURY_CONNECTION_RESTORED","JOIN_SUCCESS","JOIN_FAILURE","ADD_MEDIA_SUCCESS","ADD_MEDIA_FAILURE","ROAP_MERCURY_EVENT_RECEIVED","CONNECTION_SUCCESS","CONNECTION_FAILURE","MEETING_LEAVE_FAILURE","MEETING_END_ALL_FAILURE","MEETING_END_ALL_INITIATED","GET_USER_MEDIA_FAILURE","GET_DISPLAY_MEDIA_FAILURE","JOIN_WITH_MEDIA_FAILURE","DISCONNECT_DUE_TO_INACTIVITY","MEETING_MEDIA_INACTIVE","MEETING_RECONNECT_FAILURE","MEETING_MAX_REJOIN_FAILURE","MEETING_SHARE_FAILURE","MEETING_START_WHITEBOARD_SHARE_FAILURE","MEETING_STOP_WHITEBOARD_SHARE_FAILURE","MUTE_AUDIO_FAILURE","MUTE_VIDEO_FAILURE","SET_MEETING_QUALITY_FAILURE","STOP_FLOOR_REQUEST_FAILURE","ADD_DIAL_IN_FAILURE","ADD_DIAL_OUT_FAILURE","UPDATE_MEDIA_FAILURE","UNMUTE_AUDIO_FAILURE","UNMUTE_VIDEO_FAILURE","ROAP_ANSWER_FAILURE","ROAP_GLARE_CONDITION","PEERCONNECTION_FAILURE","INVALID_ICE_CANDIDATE","UPLOAD_LOGS_FAILURE","UPLOAD_LOGS_SUCCESS","RECEIVE_TRANSCRIPTION_FAILURE","FETCH_MEETING_INFO_V1_SUCCESS","FETCH_MEETING_INFO_V1_FAILURE","ADHOC_MEETING_SUCCESS","ADHOC_MEETING_FAILURE","VERIFY_PASSWORD_SUCCESS","VERIFY_PASSWORD_ERROR","VERIFY_CAPTCHA_ERROR","MOVE_TO_SUCCESS","MOVE_TO_FAILURE","MOVE_FROM_SUCCESS","MOVE_FROM_FAILURE","TURN_DISCOVERY_FAILURE","MEETING_INFO_POLICY_ERROR","LOCUS_DELTA_SYNC_FAILED","LOCUS_DELTA_OUT_OF_ORDER"],"sources":["constants.ts"],"sourcesContent":["// Metrics constants ----------------------------------------------------------\n\nconst BEHAVIORAL_METRICS = {\n MEETINGS_REGISTRATION_FAILED: 'js_sdk_meetings_registration_failed',\n MEETINGS_REGISTRATION_SUCCESS: 'js_sdk_meetings_registration_success',\n MERCURY_CONNECTION_FAILURE: 'js_sdk_mercury_connection_failure',\n MERCURY_CONNECTION_RESTORED: 'js_sdk_mercury_connection_restored',\n JOIN_SUCCESS: 'js_sdk_join_success',\n JOIN_FAILURE: 'js_sdk_join_failures',\n ADD_MEDIA_SUCCESS: 'js_sdk_add_media_success',\n ADD_MEDIA_FAILURE: 'js_sdk_add_media_failures',\n ROAP_MERCURY_EVENT_RECEIVED: 'js_sdk_roap_mercury_received',\n CONNECTION_SUCCESS: 'js_sdk_connection_success',\n CONNECTION_FAILURE: 'js_sdk_connection_failures',\n MEETING_LEAVE_FAILURE: 'js_sdk_meeting_leave_failure',\n MEETING_END_ALL_FAILURE: 'js_sdk_meeting_end_for_all_failure',\n MEETING_END_ALL_INITIATED: 'js_sdk_meeting_end_for_all_initiated',\n GET_USER_MEDIA_FAILURE: 'js_sdk_get_user_media_failures',\n GET_DISPLAY_MEDIA_FAILURE: 'js_sdk_get_display_media_failures',\n JOIN_WITH_MEDIA_FAILURE: 'js_sdk_join_with_media_failures',\n\n DISCONNECT_DUE_TO_INACTIVITY: 'js_sdk_disconnect_due_to_inactivity',\n MEETING_MEDIA_INACTIVE: 'js_sdk_meeting_media_inactive',\n MEETING_RECONNECT_FAILURE: 'js_sdk_meeting_reconnect_failures',\n MEETING_MAX_REJOIN_FAILURE: 'js_sdk_meeting_max_rejoin_failure',\n MEETING_SHARE_FAILURE: 'js_sdk_meeting_share_failures',\n MEETING_START_WHITEBOARD_SHARE_FAILURE: 'js_sdk_meeting_start_whiteboard_share_failures',\n MEETING_STOP_WHITEBOARD_SHARE_FAILURE: 'js_sdk_meeting_stop_whiteboard_share_failures',\n MUTE_AUDIO_FAILURE: 'js_sdk_mute_audio_failures',\n MUTE_VIDEO_FAILURE: 'js_sdk_mute_video_failures',\n SET_MEETING_QUALITY_FAILURE: 'js_sdk_set_meeting_quality_failures',\n STOP_FLOOR_REQUEST_FAILURE: 'js_sdk_stop_floor_request_failures',\n ADD_DIAL_IN_FAILURE: 'js_sdk_add_dial_in_failure',\n ADD_DIAL_OUT_FAILURE: 'js_sdk_add_dial_out_failure',\n UPDATE_MEDIA_FAILURE: 'js_sdk_update_media_failures',\n UNMUTE_AUDIO_FAILURE: 'js_sdk_unmute_audio_failures',\n UNMUTE_VIDEO_FAILURE: 'js_sdk_unmute_video_failures',\n ROAP_ANSWER_FAILURE: 'js_sdk_roap_answer_failures',\n ROAP_GLARE_CONDITION: 'js_sdk_roap_glar_condition',\n PEERCONNECTION_FAILURE: 'js_sdk_peerConnection_failures',\n INVALID_ICE_CANDIDATE: 'js_sdk_invalid_ice_candidate',\n UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',\n UPLOAD_LOGS_SUCCESS: 'js_sdk_upload_logs_success',\n RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',\n FETCH_MEETING_INFO_V1_SUCCESS: 'js_sdk_fetch_meeting_info_v1_success',\n FETCH_MEETING_INFO_V1_FAILURE: 'js_sdk_fetch_meeting_info_v1_failure',\n ADHOC_MEETING_SUCCESS: 'js_sdk_adhoc_meeting_success',\n ADHOC_MEETING_FAILURE: 'js_sdk_adhoc_meeting_failure',\n VERIFY_PASSWORD_SUCCESS: 'js_sdk_verify_password_success',\n VERIFY_PASSWORD_ERROR: 'js_sdk_verify_password_error',\n VERIFY_CAPTCHA_ERROR: 'js_sdk_verify_captcha_error',\n MOVE_TO_SUCCESS: 'js_sdk_move_to_success',\n MOVE_TO_FAILURE: 'js_sdk_move_to_failure',\n MOVE_FROM_SUCCESS: 'js_sdk_move_from_success',\n MOVE_FROM_FAILURE: 'js_sdk_move_from_failure',\n TURN_DISCOVERY_FAILURE: 'js_sdk_turn_discovery_failure',\n MEETING_INFO_POLICY_ERROR: 'js_sdk_meeting_info_policy_error',\n LOCUS_DELTA_SYNC_FAILED: 'js_sdk_locus_delta_sync_failed',\n LOCUS_DELTA_OUT_OF_ORDER: 'js_sdk_locus_delta_ooo',\n};\n\nexport {BEHAVIORAL_METRICS as default};\n"],"mappings":";;;;;;;AAAA;;AAEA,IAAMA,kBAAkB,GAAG;EACzBC,4BAA4B,EAAE,qCAAqC;EACnEC,6BAA6B,EAAE,sCAAsC;EACrEC,0BAA0B,EAAE,mCAAmC;EAC/DC,2BAA2B,EAAE,oCAAoC;EACjEC,YAAY,EAAE,qBAAqB;EACnCC,YAAY,EAAE,sBAAsB;EACpCC,iBAAiB,EAAE,0BAA0B;EAC7CC,iBAAiB,EAAE,2BAA2B;EAC9CC,2BAA2B,EAAE,8BAA8B;EAC3DC,kBAAkB,EAAE,2BAA2B;EAC/CC,kBAAkB,EAAE,4BAA4B;EAChDC,qBAAqB,EAAE,8BAA8B;EACrDC,uBAAuB,EAAE,oCAAoC;EAC7DC,yBAAyB,EAAE,sCAAsC;EACjEC,sBAAsB,EAAE,gCAAgC;EACxDC,yBAAyB,EAAE,mCAAmC;EAC9DC,uBAAuB,EAAE,iCAAiC;EAE1DC,4BAA4B,EAAE,qCAAqC;EACnEC,sBAAsB,EAAE,+BAA+B;EACvDC,yBAAyB,EAAE,mCAAmC;EAC9DC,0BAA0B,EAAE,mCAAmC;EAC/DC,qBAAqB,EAAE,+BAA+B;EACtDC,sCAAsC,EAAE,gDAAgD;EACxFC,qCAAqC,EAAE,+CAA+C;EACtFC,kBAAkB,EAAE,4BAA4B;EAChDC,kBAAkB,EAAE,4BAA4B;EAChDC,2BAA2B,EAAE,qCAAqC;EAClEC,0BAA0B,EAAE,oCAAoC;EAChEC,mBAAmB,EAAE,4BAA4B;EACjDC,oBAAoB,EAAE,6BAA6B;EACnDC,oBAAoB,EAAE,8BAA8B;EACpDC,oBAAoB,EAAE,8BAA8B;EACpDC,oBAAoB,EAAE,8BAA8B;EACpDC,mBAAmB,EAAE,6BAA6B;EAClDC,oBAAoB,EAAE,4BAA4B;EAClDC,sBAAsB,EAAE,gCAAgC;EACxDC,qBAAqB,EAAE,8BAA8B;EACrDC,mBAAmB,EAAE,4BAA4B;EACjDC,mBAAmB,EAAE,4BAA4B;EACjDC,6BAA6B,EAAE,sCAAsC;EACrEC,6BAA6B,EAAE,sCAAsC;EACrEC,6BAA6B,EAAE,sCAAsC;EACrEC,qBAAqB,EAAE,8BAA8B;EACrDC,qBAAqB,EAAE,8BAA8B;EACrDC,uBAAuB,EAAE,gCAAgC;EACzDC,qBAAqB,EAAE,8BAA8B;EACrDC,oBAAoB,EAAE,6BAA6B;EACnDC,eAAe,EAAE,wBAAwB;EACzCC,eAAe,EAAE,wBAAwB;EACzCC,iBAAiB,EAAE,0BAA0B;EAC7CC,iBAAiB,EAAE,0BAA0B;EAC7CC,sBAAsB,EAAE,+BAA+B;EACvDC,yBAAyB,EAAE,kCAAkC;EAC7DC,uBAAuB,EAAE,gCAAgC;EACzDC,wBAAwB,EAAE;AAC5B,CAAC;AAAC"}
1
+ {"version":3,"names":["BEHAVIORAL_METRICS","MEETINGS_REGISTRATION_FAILED","MEETINGS_REGISTRATION_SUCCESS","MERCURY_CONNECTION_FAILURE","MERCURY_CONNECTION_RESTORED","JOIN_SUCCESS","JOIN_FAILURE","ADD_MEDIA_SUCCESS","ADD_MEDIA_FAILURE","ROAP_MERCURY_EVENT_RECEIVED","CONNECTION_SUCCESS","CONNECTION_FAILURE","MEETING_LEAVE_FAILURE","MEETING_END_ALL_FAILURE","MEETING_END_ALL_INITIATED","GET_USER_MEDIA_FAILURE","GET_DISPLAY_MEDIA_FAILURE","JOIN_WITH_MEDIA_FAILURE","DISCONNECT_DUE_TO_INACTIVITY","MEETING_MEDIA_INACTIVE","MEETING_RECONNECT_FAILURE","MEETING_MAX_REJOIN_FAILURE","MEETING_SHARE_FAILURE","MEETING_START_WHITEBOARD_SHARE_FAILURE","MEETING_STOP_WHITEBOARD_SHARE_FAILURE","MUTE_AUDIO_FAILURE","MUTE_VIDEO_FAILURE","SET_MEETING_QUALITY_FAILURE","STOP_FLOOR_REQUEST_FAILURE","ADD_DIAL_IN_FAILURE","ADD_DIAL_OUT_FAILURE","UPDATE_MEDIA_FAILURE","UNMUTE_AUDIO_FAILURE","UNMUTE_VIDEO_FAILURE","ROAP_ANSWER_FAILURE","ROAP_GLARE_CONDITION","PEERCONNECTION_FAILURE","INVALID_ICE_CANDIDATE","UPLOAD_LOGS_FAILURE","UPLOAD_LOGS_SUCCESS","RECEIVE_TRANSCRIPTION_FAILURE","FETCH_MEETING_INFO_V1_SUCCESS","FETCH_MEETING_INFO_V1_FAILURE","ADHOC_MEETING_SUCCESS","ADHOC_MEETING_FAILURE","VERIFY_PASSWORD_SUCCESS","VERIFY_PASSWORD_ERROR","VERIFY_CAPTCHA_ERROR","MOVE_TO_SUCCESS","MOVE_TO_FAILURE","MOVE_FROM_SUCCESS","MOVE_FROM_FAILURE","TURN_DISCOVERY_FAILURE","MEETING_INFO_POLICY_ERROR","LOCUS_DELTA_SYNC_FAILED","LOCUS_DELTA_OUT_OF_ORDER","PERMISSION_TOKEN_REFRESH","PERMISSION_TOKEN_REFRESH_ERROR"],"sources":["constants.ts"],"sourcesContent":["// Metrics constants ----------------------------------------------------------\n\nconst BEHAVIORAL_METRICS = {\n MEETINGS_REGISTRATION_FAILED: 'js_sdk_meetings_registration_failed',\n MEETINGS_REGISTRATION_SUCCESS: 'js_sdk_meetings_registration_success',\n MERCURY_CONNECTION_FAILURE: 'js_sdk_mercury_connection_failure',\n MERCURY_CONNECTION_RESTORED: 'js_sdk_mercury_connection_restored',\n JOIN_SUCCESS: 'js_sdk_join_success',\n JOIN_FAILURE: 'js_sdk_join_failures',\n ADD_MEDIA_SUCCESS: 'js_sdk_add_media_success',\n ADD_MEDIA_FAILURE: 'js_sdk_add_media_failures',\n ROAP_MERCURY_EVENT_RECEIVED: 'js_sdk_roap_mercury_received',\n CONNECTION_SUCCESS: 'js_sdk_connection_success',\n CONNECTION_FAILURE: 'js_sdk_connection_failures',\n MEETING_LEAVE_FAILURE: 'js_sdk_meeting_leave_failure',\n MEETING_END_ALL_FAILURE: 'js_sdk_meeting_end_for_all_failure',\n MEETING_END_ALL_INITIATED: 'js_sdk_meeting_end_for_all_initiated',\n GET_USER_MEDIA_FAILURE: 'js_sdk_get_user_media_failures',\n GET_DISPLAY_MEDIA_FAILURE: 'js_sdk_get_display_media_failures',\n JOIN_WITH_MEDIA_FAILURE: 'js_sdk_join_with_media_failures',\n\n DISCONNECT_DUE_TO_INACTIVITY: 'js_sdk_disconnect_due_to_inactivity',\n MEETING_MEDIA_INACTIVE: 'js_sdk_meeting_media_inactive',\n MEETING_RECONNECT_FAILURE: 'js_sdk_meeting_reconnect_failures',\n MEETING_MAX_REJOIN_FAILURE: 'js_sdk_meeting_max_rejoin_failure',\n MEETING_SHARE_FAILURE: 'js_sdk_meeting_share_failures',\n MEETING_START_WHITEBOARD_SHARE_FAILURE: 'js_sdk_meeting_start_whiteboard_share_failures',\n MEETING_STOP_WHITEBOARD_SHARE_FAILURE: 'js_sdk_meeting_stop_whiteboard_share_failures',\n MUTE_AUDIO_FAILURE: 'js_sdk_mute_audio_failures',\n MUTE_VIDEO_FAILURE: 'js_sdk_mute_video_failures',\n SET_MEETING_QUALITY_FAILURE: 'js_sdk_set_meeting_quality_failures',\n STOP_FLOOR_REQUEST_FAILURE: 'js_sdk_stop_floor_request_failures',\n ADD_DIAL_IN_FAILURE: 'js_sdk_add_dial_in_failure',\n ADD_DIAL_OUT_FAILURE: 'js_sdk_add_dial_out_failure',\n UPDATE_MEDIA_FAILURE: 'js_sdk_update_media_failures',\n UNMUTE_AUDIO_FAILURE: 'js_sdk_unmute_audio_failures',\n UNMUTE_VIDEO_FAILURE: 'js_sdk_unmute_video_failures',\n ROAP_ANSWER_FAILURE: 'js_sdk_roap_answer_failures',\n ROAP_GLARE_CONDITION: 'js_sdk_roap_glar_condition',\n PEERCONNECTION_FAILURE: 'js_sdk_peerConnection_failures',\n INVALID_ICE_CANDIDATE: 'js_sdk_invalid_ice_candidate',\n UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',\n UPLOAD_LOGS_SUCCESS: 'js_sdk_upload_logs_success',\n RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',\n FETCH_MEETING_INFO_V1_SUCCESS: 'js_sdk_fetch_meeting_info_v1_success',\n FETCH_MEETING_INFO_V1_FAILURE: 'js_sdk_fetch_meeting_info_v1_failure',\n ADHOC_MEETING_SUCCESS: 'js_sdk_adhoc_meeting_success',\n ADHOC_MEETING_FAILURE: 'js_sdk_adhoc_meeting_failure',\n VERIFY_PASSWORD_SUCCESS: 'js_sdk_verify_password_success',\n VERIFY_PASSWORD_ERROR: 'js_sdk_verify_password_error',\n VERIFY_CAPTCHA_ERROR: 'js_sdk_verify_captcha_error',\n MOVE_TO_SUCCESS: 'js_sdk_move_to_success',\n MOVE_TO_FAILURE: 'js_sdk_move_to_failure',\n MOVE_FROM_SUCCESS: 'js_sdk_move_from_success',\n MOVE_FROM_FAILURE: 'js_sdk_move_from_failure',\n TURN_DISCOVERY_FAILURE: 'js_sdk_turn_discovery_failure',\n MEETING_INFO_POLICY_ERROR: 'js_sdk_meeting_info_policy_error',\n LOCUS_DELTA_SYNC_FAILED: 'js_sdk_locus_delta_sync_failed',\n LOCUS_DELTA_OUT_OF_ORDER: 'js_sdk_locus_delta_ooo',\n PERMISSION_TOKEN_REFRESH: 'js_sdk_permission_token_refresh',\n PERMISSION_TOKEN_REFRESH_ERROR: 'js_sdk_permission_token_refresh_error',\n};\n\nexport {BEHAVIORAL_METRICS as default};\n"],"mappings":";;;;;;;AAAA;;AAEA,IAAMA,kBAAkB,GAAG;EACzBC,4BAA4B,EAAE,qCAAqC;EACnEC,6BAA6B,EAAE,sCAAsC;EACrEC,0BAA0B,EAAE,mCAAmC;EAC/DC,2BAA2B,EAAE,oCAAoC;EACjEC,YAAY,EAAE,qBAAqB;EACnCC,YAAY,EAAE,sBAAsB;EACpCC,iBAAiB,EAAE,0BAA0B;EAC7CC,iBAAiB,EAAE,2BAA2B;EAC9CC,2BAA2B,EAAE,8BAA8B;EAC3DC,kBAAkB,EAAE,2BAA2B;EAC/CC,kBAAkB,EAAE,4BAA4B;EAChDC,qBAAqB,EAAE,8BAA8B;EACrDC,uBAAuB,EAAE,oCAAoC;EAC7DC,yBAAyB,EAAE,sCAAsC;EACjEC,sBAAsB,EAAE,gCAAgC;EACxDC,yBAAyB,EAAE,mCAAmC;EAC9DC,uBAAuB,EAAE,iCAAiC;EAE1DC,4BAA4B,EAAE,qCAAqC;EACnEC,sBAAsB,EAAE,+BAA+B;EACvDC,yBAAyB,EAAE,mCAAmC;EAC9DC,0BAA0B,EAAE,mCAAmC;EAC/DC,qBAAqB,EAAE,+BAA+B;EACtDC,sCAAsC,EAAE,gDAAgD;EACxFC,qCAAqC,EAAE,+CAA+C;EACtFC,kBAAkB,EAAE,4BAA4B;EAChDC,kBAAkB,EAAE,4BAA4B;EAChDC,2BAA2B,EAAE,qCAAqC;EAClEC,0BAA0B,EAAE,oCAAoC;EAChEC,mBAAmB,EAAE,4BAA4B;EACjDC,oBAAoB,EAAE,6BAA6B;EACnDC,oBAAoB,EAAE,8BAA8B;EACpDC,oBAAoB,EAAE,8BAA8B;EACpDC,oBAAoB,EAAE,8BAA8B;EACpDC,mBAAmB,EAAE,6BAA6B;EAClDC,oBAAoB,EAAE,4BAA4B;EAClDC,sBAAsB,EAAE,gCAAgC;EACxDC,qBAAqB,EAAE,8BAA8B;EACrDC,mBAAmB,EAAE,4BAA4B;EACjDC,mBAAmB,EAAE,4BAA4B;EACjDC,6BAA6B,EAAE,sCAAsC;EACrEC,6BAA6B,EAAE,sCAAsC;EACrEC,6BAA6B,EAAE,sCAAsC;EACrEC,qBAAqB,EAAE,8BAA8B;EACrDC,qBAAqB,EAAE,8BAA8B;EACrDC,uBAAuB,EAAE,gCAAgC;EACzDC,qBAAqB,EAAE,8BAA8B;EACrDC,oBAAoB,EAAE,6BAA6B;EACnDC,eAAe,EAAE,wBAAwB;EACzCC,eAAe,EAAE,wBAAwB;EACzCC,iBAAiB,EAAE,0BAA0B;EAC7CC,iBAAiB,EAAE,0BAA0B;EAC7CC,sBAAsB,EAAE,+BAA+B;EACvDC,yBAAyB,EAAE,kCAAkC;EAC7DC,uBAAuB,EAAE,gCAAgC;EACzDC,wBAAwB,EAAE,wBAAwB;EAClDC,wBAAwB,EAAE,iCAAiC;EAC3DC,8BAA8B,EAAE;AAClC,CAAC;AAAC"}
@@ -355,6 +355,7 @@ export default class Meeting extends StatelessWebexPlugin {
355
355
  };
356
356
  meetingInfoFailureReason: string;
357
357
  meetingInfoFailureCode?: number;
358
+ meetingInfoExtraParams?: Record<string, any>;
358
359
  networkQualityMonitor: NetworkQualityMonitor;
359
360
  networkStatus: string;
360
361
  passwordStatus: string;
@@ -418,6 +419,19 @@ export default class Meeting extends StatelessWebexPlugin {
418
419
  * @returns {Boolean}
419
420
  */
420
421
  isLocusCall(): boolean;
422
+ /**
423
+ * Internal method for fetching meeting info
424
+ *
425
+ * @returns {Promise}
426
+ */
427
+ private fetchMeetingInfoInternal;
428
+ /**
429
+ * Refreshes the meeting info permission token (it's required for joining meetings)
430
+ *
431
+ * @param {string} [reason] used for metrics and logging purposes (optional)
432
+ * @returns {Promise}
433
+ */
434
+ refreshPermissionToken(reason?: string): Promise<void>;
421
435
  /**
422
436
  * Fetches meeting information.
423
437
  * @param {Object} options
@@ -54,5 +54,7 @@ declare const BEHAVIORAL_METRICS: {
54
54
  MEETING_INFO_POLICY_ERROR: string;
55
55
  LOCUS_DELTA_SYNC_FAILED: string;
56
56
  LOCUS_DELTA_OUT_OF_ORDER: string;
57
+ PERMISSION_TOKEN_REFRESH: string;
58
+ PERMISSION_TOKEN_REFRESH_ERROR: string;
57
59
  };
58
60
  export { BEHAVIORAL_METRICS as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.253",
3
+ "version": "3.0.0-beta.255",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -32,12 +32,12 @@
32
32
  "build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
33
33
  },
34
34
  "devDependencies": {
35
- "@webex/plugin-meetings": "3.0.0-beta.253",
36
- "@webex/test-helper-chai": "3.0.0-beta.253",
37
- "@webex/test-helper-mocha": "3.0.0-beta.253",
38
- "@webex/test-helper-mock-webex": "3.0.0-beta.253",
39
- "@webex/test-helper-retry": "3.0.0-beta.253",
40
- "@webex/test-helper-test-users": "3.0.0-beta.253",
35
+ "@webex/plugin-meetings": "3.0.0-beta.255",
36
+ "@webex/test-helper-chai": "3.0.0-beta.255",
37
+ "@webex/test-helper-mocha": "3.0.0-beta.255",
38
+ "@webex/test-helper-mock-webex": "3.0.0-beta.255",
39
+ "@webex/test-helper-retry": "3.0.0-beta.255",
40
+ "@webex/test-helper-test-users": "3.0.0-beta.255",
41
41
  "chai": "^4.3.4",
42
42
  "chai-as-promised": "^7.1.1",
43
43
  "jsdom-global": "3.0.2",
@@ -46,19 +46,19 @@
46
46
  "typescript": "^4.7.4"
47
47
  },
48
48
  "dependencies": {
49
- "@webex/common": "3.0.0-beta.253",
49
+ "@webex/common": "3.0.0-beta.255",
50
50
  "@webex/internal-media-core": "2.0.3",
51
- "@webex/internal-plugin-conversation": "3.0.0-beta.253",
52
- "@webex/internal-plugin-device": "3.0.0-beta.253",
53
- "@webex/internal-plugin-llm": "3.0.0-beta.253",
54
- "@webex/internal-plugin-mercury": "3.0.0-beta.253",
55
- "@webex/internal-plugin-metrics": "3.0.0-beta.253",
56
- "@webex/internal-plugin-support": "3.0.0-beta.253",
57
- "@webex/internal-plugin-user": "3.0.0-beta.253",
58
- "@webex/media-helpers": "3.0.0-beta.253",
59
- "@webex/plugin-people": "3.0.0-beta.253",
60
- "@webex/plugin-rooms": "3.0.0-beta.253",
61
- "@webex/webex-core": "3.0.0-beta.253",
51
+ "@webex/internal-plugin-conversation": "3.0.0-beta.255",
52
+ "@webex/internal-plugin-device": "3.0.0-beta.255",
53
+ "@webex/internal-plugin-llm": "3.0.0-beta.255",
54
+ "@webex/internal-plugin-mercury": "3.0.0-beta.255",
55
+ "@webex/internal-plugin-metrics": "3.0.0-beta.255",
56
+ "@webex/internal-plugin-support": "3.0.0-beta.255",
57
+ "@webex/internal-plugin-user": "3.0.0-beta.255",
58
+ "@webex/media-helpers": "3.0.0-beta.255",
59
+ "@webex/plugin-people": "3.0.0-beta.255",
60
+ "@webex/plugin-rooms": "3.0.0-beta.255",
61
+ "@webex/webex-core": "3.0.0-beta.255",
62
62
  "ampersand-collection": "^2.0.2",
63
63
  "bowser": "^2.11.0",
64
64
  "btoa": "^1.2.1",
@@ -62,8 +62,10 @@ import ReconnectionError from '../common/errors/reconnection';
62
62
  import ReconnectInProgress from '../common/errors/reconnection-in-progress';
63
63
  import {
64
64
  _CALL_,
65
+ _CONVERSATION_URL_,
65
66
  _INCOMING_,
66
67
  _JOIN_,
68
+ _MEETING_LINK_,
67
69
  AUDIO,
68
70
  CONTENT,
69
71
  DISPLAY_HINTS,
@@ -514,6 +516,7 @@ export default class Meeting extends StatelessWebexPlugin {
514
516
 
515
517
  meetingInfoFailureReason: string;
516
518
  meetingInfoFailureCode?: number;
519
+ meetingInfoExtraParams?: Record<string, any>;
517
520
  networkQualityMonitor: NetworkQualityMonitor;
518
521
  networkStatus: string;
519
522
  passwordStatus: string;
@@ -1279,54 +1282,26 @@ export default class Meeting extends StatelessWebexPlugin {
1279
1282
  }
1280
1283
 
1281
1284
  /**
1282
- * Fetches meeting information.
1283
- * @param {Object} options
1284
- * @param {String} [options.password] optional
1285
- * @param {String} [options.captchaCode] optional
1286
- * @param {Boolean} [options.sendCAevents] optional - Whether to submit Call Analyzer events or not. Default: false.
1287
- * @public
1288
- * @memberof Meeting
1285
+ * Internal method for fetching meeting info
1286
+ *
1289
1287
  * @returns {Promise}
1290
1288
  */
1291
- public async fetchMeetingInfo({
1289
+ private async fetchMeetingInfoInternal({
1290
+ destination,
1291
+ destinationType,
1292
1292
  password = null,
1293
1293
  captchaCode = null,
1294
1294
  extraParams = {},
1295
1295
  sendCAevents = false,
1296
- }: {
1297
- password?: string;
1298
- captchaCode?: string;
1299
- extraParams?: Record<string, any>;
1300
- sendCAevents?: boolean;
1301
- }) {
1302
- // when fetch meeting info is called directly by the client, we want to clear out the random timer for sdk to do it
1303
- if (this.fetchMeetingInfoTimeoutId) {
1304
- clearTimeout(this.fetchMeetingInfoTimeoutId);
1305
- this.fetchMeetingInfoTimeoutId = undefined;
1306
- }
1307
- if (captchaCode && !this.requiredCaptcha) {
1308
- return Promise.reject(
1309
- new Error('fetchMeetingInfo() called with captchaCode when captcha was not required')
1310
- );
1311
- }
1312
- if (
1313
- password &&
1314
- this.passwordStatus !== PASSWORD_STATUS.REQUIRED &&
1315
- this.passwordStatus !== PASSWORD_STATUS.UNKNOWN
1316
- ) {
1317
- return Promise.reject(
1318
- new Error('fetchMeetingInfo() called with password when password was not required')
1319
- );
1320
- }
1321
-
1296
+ }): Promise<void> {
1322
1297
  try {
1323
1298
  const captchaInfo = captchaCode
1324
1299
  ? {code: captchaCode, id: this.requiredCaptcha.captchaId}
1325
1300
  : null;
1326
1301
 
1327
1302
  const info = await this.attrs.meetingInfoProvider.fetchMeetingInfo(
1328
- this.destination,
1329
- this.destinationType,
1303
+ destination,
1304
+ destinationType,
1330
1305
  password,
1331
1306
  captchaInfo,
1332
1307
  // @ts-ignore - config coming from registerPlugin
@@ -1420,6 +1395,125 @@ export default class Meeting extends StatelessWebexPlugin {
1420
1395
  }
1421
1396
  }
1422
1397
 
1398
+ /**
1399
+ * Refreshes the meeting info permission token (it's required for joining meetings)
1400
+ *
1401
+ * @param {string} [reason] used for metrics and logging purposes (optional)
1402
+ * @returns {Promise}
1403
+ */
1404
+ public async refreshPermissionToken(reason?: string): Promise<void> {
1405
+ if (!this.meetingInfo?.permissionToken) {
1406
+ LoggerProxy.logger.info(
1407
+ `Meeting:index#refreshPermissionToken --> cannot refresh the permission token, because we don't have it (reason=${reason})`
1408
+ );
1409
+
1410
+ return;
1411
+ }
1412
+
1413
+ const isStartingSpaceInstantV2Meeting =
1414
+ this.destinationType === _CONVERSATION_URL_ &&
1415
+ // @ts-ignore - config coming from registerPlugin
1416
+ this.config.experimental.enableAdhocMeetings &&
1417
+ // @ts-ignore
1418
+ this.webex.meetings.preferredWebexSite;
1419
+
1420
+ const destination = isStartingSpaceInstantV2Meeting
1421
+ ? this.meetingInfo.meetingJoinUrl
1422
+ : this.destination;
1423
+ const destinationType = isStartingSpaceInstantV2Meeting ? _MEETING_LINK_ : this.destinationType;
1424
+
1425
+ const timeLeft = this.getPermissionTokenTimeLeftInSec();
1426
+
1427
+ LoggerProxy.logger.info(
1428
+ `Meeting:index#refreshPermissionToken --> refreshing permission token, destinationType=${destinationType}, timeLeft=${timeLeft}, reason=${reason}`
1429
+ );
1430
+
1431
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
1432
+ correlationId: this.correlationId,
1433
+ timeLeft,
1434
+ reason,
1435
+ destinationType,
1436
+ });
1437
+
1438
+ try {
1439
+ await this.fetchMeetingInfoInternal({
1440
+ destination,
1441
+ destinationType,
1442
+ extraParams: {
1443
+ ...this.meetingInfoExtraParams,
1444
+ permissionToken: this.meetingInfo.permissionToken,
1445
+ },
1446
+ sendCAevents: true, // because if we're refreshing the permissionToken, it means that user is intending to join that meeting, so we want CA events
1447
+ });
1448
+ } catch (error) {
1449
+ LoggerProxy.logger.info(
1450
+ 'Meeting:index#refreshPermissionToken --> failed to refresh the permission token:',
1451
+ error
1452
+ );
1453
+
1454
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH_ERROR, {
1455
+ correlationId: this.correlationId,
1456
+ reason: error.message,
1457
+ stack: error.stack,
1458
+ });
1459
+
1460
+ throw error;
1461
+ }
1462
+ }
1463
+
1464
+ /**
1465
+ * Fetches meeting information.
1466
+ * @param {Object} options
1467
+ * @param {String} [options.password] optional
1468
+ * @param {String} [options.captchaCode] optional
1469
+ * @param {Boolean} [options.sendCAevents] optional - Whether to submit Call Analyzer events or not. Default: false.
1470
+ * @public
1471
+ * @memberof Meeting
1472
+ * @returns {Promise}
1473
+ */
1474
+ public async fetchMeetingInfo({
1475
+ password = null,
1476
+ captchaCode = null,
1477
+ extraParams = {},
1478
+ sendCAevents = false,
1479
+ }: {
1480
+ password?: string;
1481
+ captchaCode?: string;
1482
+ extraParams?: Record<string, any>;
1483
+ sendCAevents?: boolean;
1484
+ }) {
1485
+ // when fetch meeting info is called directly by the client, we want to clear out the random timer for sdk to do it
1486
+ if (this.fetchMeetingInfoTimeoutId) {
1487
+ clearTimeout(this.fetchMeetingInfoTimeoutId);
1488
+ this.fetchMeetingInfoTimeoutId = undefined;
1489
+ }
1490
+ if (captchaCode && !this.requiredCaptcha) {
1491
+ return Promise.reject(
1492
+ new Error('fetchMeetingInfo() called with captchaCode when captcha was not required')
1493
+ );
1494
+ }
1495
+ if (
1496
+ password &&
1497
+ this.passwordStatus !== PASSWORD_STATUS.REQUIRED &&
1498
+ this.passwordStatus !== PASSWORD_STATUS.UNKNOWN
1499
+ ) {
1500
+ return Promise.reject(
1501
+ new Error('fetchMeetingInfo() called with password when password was not required')
1502
+ );
1503
+ }
1504
+
1505
+ this.meetingInfoExtraParams = cloneDeep(extraParams);
1506
+
1507
+ return this.fetchMeetingInfoInternal({
1508
+ destination: this.destination,
1509
+ destinationType: this.destinationType,
1510
+ password,
1511
+ captchaCode,
1512
+ extraParams,
1513
+ sendCAevents,
1514
+ });
1515
+ }
1516
+
1423
1517
  /**
1424
1518
  * Checks if the supplied password/host key is correct. It returns a promise with information whether the
1425
1519
  * password and captcha code were correct or not.
@@ -57,6 +57,8 @@ const BEHAVIORAL_METRICS = {
57
57
  MEETING_INFO_POLICY_ERROR: 'js_sdk_meeting_info_policy_error',
58
58
  LOCUS_DELTA_SYNC_FAILED: 'js_sdk_locus_delta_sync_failed',
59
59
  LOCUS_DELTA_OUT_OF_ORDER: 'js_sdk_locus_delta_ooo',
60
+ PERMISSION_TOKEN_REFRESH: 'js_sdk_permission_token_refresh',
61
+ PERMISSION_TOKEN_REFRESH_ERROR: 'js_sdk_permission_token_refresh_error',
60
62
  };
61
63
 
62
64
  export {BEHAVIORAL_METRICS as default};
@@ -3484,6 +3484,219 @@ describe('plugin-meetings', () => {
3484
3484
  });
3485
3485
  });
3486
3486
 
3487
+ describe('#refreshPermissionToken', () => {
3488
+ const FAKE_MEETING_INFO = {
3489
+ conversationUrl: 'some_convo_url',
3490
+ locusUrl: 'some_locus_url',
3491
+ sipUrl: 'some_sip_url',
3492
+ meetingNumber: '123456',
3493
+ hostId: 'some_host_id',
3494
+ };
3495
+ const FAKE_MEETING_INFO_LOOKUP_URL = 'meetingLookupUrl';
3496
+ const FAKE_PERMISSION_TOKEN = {someField: 'some value'};
3497
+ const FAKE_TTL = 13;
3498
+
3499
+ beforeEach(() => {
3500
+ meeting.locusId = 'locus-id';
3501
+ meeting.id = 'meeting-id';
3502
+ meeting.config.installedOrgID = 'fake-installed-org-id';
3503
+ meeting.meetingInfo.permissionToken = FAKE_PERMISSION_TOKEN;
3504
+ meeting.destination = 'meeting-destination';
3505
+ meeting.destinationType = 'meeting-destination-type';
3506
+ meeting.updateMeetingActions = sinon.stub().returns(undefined);
3507
+ meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(FAKE_TTL);
3508
+ meeting.meetingInfoExtraParams = {
3509
+ extraParam1: 'value1'
3510
+ };
3511
+ meeting.attrs.meetingInfoProvider = {
3512
+ fetchMeetingInfo: sinon
3513
+ .stub()
3514
+ .resolves({body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL}),
3515
+ };
3516
+ });
3517
+
3518
+ it('resolves without doing anything if there is no permission token', async () => {
3519
+ meeting.meetingInfo.permissionToken = undefined;
3520
+
3521
+ await meeting.refreshPermissionToken();
3522
+
3523
+ assert.notCalled(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
3524
+ assert.notCalled(Metrics.sendBehavioralMetric);
3525
+ });
3526
+
3527
+ it('calls meetingInfoProvider.fetchMeetingInfo() with the right params', async () => {
3528
+ await meeting.refreshPermissionToken('fake reason');
3529
+
3530
+ assert.calledOnceWithExactly(
3531
+ meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
3532
+ 'meeting-destination',
3533
+ 'meeting-destination-type',
3534
+ null,
3535
+ null,
3536
+ 'fake-installed-org-id',
3537
+ 'locus-id',
3538
+ {extraParam1: 'value1', permissionToken: FAKE_PERMISSION_TOKEN},
3539
+ {meetingId: meeting.id, sendCAevents: true}
3540
+ );
3541
+ assert.deepEqual(meeting.meetingInfo, {
3542
+ ...FAKE_MEETING_INFO,
3543
+ meetingLookupUrl: FAKE_MEETING_INFO_LOOKUP_URL
3544
+ });
3545
+ assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
3546
+ assert.equal(meeting.requiredCaptcha, null);
3547
+ assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
3548
+
3549
+ assert.calledWith(
3550
+ TriggerProxy.trigger,
3551
+ meeting,
3552
+ {file: 'meetings', function: 'fetchMeetingInfo'},
3553
+ 'meeting:meetingInfoAvailable'
3554
+ );
3555
+ assert.calledWith(meeting.updateMeetingActions);
3556
+
3557
+ assert.calledWith(
3558
+ Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
3559
+ correlationId: meeting.correlationId,
3560
+ timeLeft: FAKE_TTL,
3561
+ reason: 'fake reason',
3562
+ destinationType: 'meeting-destination-type',
3563
+ }
3564
+ );
3565
+ });
3566
+
3567
+ it('calls meetingInfoProvider.fetchMeetingInfo() with the right params when we are starting an instant space meeting', async () => {
3568
+ meeting.destination = 'some-convo-url';
3569
+ meeting.destinationType = 'CONVERSATION_URL';
3570
+ meeting.config.experimental = {enableAdhocMeetings: true};
3571
+ meeting.meetingInfo.meetingJoinUrl = 'meeting-join-url';
3572
+ meeting.webex.meetings.preferredWebexSite = 'preferredWebexSite';
3573
+
3574
+ await meeting.refreshPermissionToken('some reason');
3575
+
3576
+ assert.calledOnceWithExactly(
3577
+ meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
3578
+ 'meeting-join-url',
3579
+ 'MEETING_LINK',
3580
+ null,
3581
+ null,
3582
+ 'fake-installed-org-id',
3583
+ 'locus-id',
3584
+ {
3585
+ extraParam1: 'value1',
3586
+ permissionToken: FAKE_PERMISSION_TOKEN
3587
+ },
3588
+ {meetingId: meeting.id, sendCAevents: true}
3589
+ );
3590
+ assert.deepEqual(meeting.meetingInfo, {
3591
+ ...FAKE_MEETING_INFO,
3592
+ meetingLookupUrl: FAKE_MEETING_INFO_LOOKUP_URL
3593
+ });
3594
+ assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
3595
+ assert.equal(meeting.requiredCaptcha, null);
3596
+ assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
3597
+
3598
+ assert.calledWith(
3599
+ TriggerProxy.trigger,
3600
+ meeting,
3601
+ {file: 'meetings', function: 'fetchMeetingInfo'},
3602
+ 'meeting:meetingInfoAvailable'
3603
+ );
3604
+ assert.calledWith(meeting.updateMeetingActions);
3605
+
3606
+ assert.calledWith(
3607
+ Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
3608
+ correlationId: meeting.correlationId,
3609
+ timeLeft: FAKE_TTL,
3610
+ reason: 'some reason',
3611
+ destinationType: 'MEETING_LINK',
3612
+ }
3613
+ );
3614
+ });
3615
+
3616
+ it('throws PermissionError if policy error is encountered', async () => {
3617
+ meeting.attrs.meetingInfoProvider = {
3618
+ fetchMeetingInfo: sinon
3619
+ .stub()
3620
+ .throws(new MeetingInfoV2PolicyError(123456, FAKE_MEETING_INFO, 'a message')),
3621
+ };
3622
+
3623
+ await assert.isRejected(meeting.refreshPermissionToken());
3624
+
3625
+ assert.calledOnce(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
3626
+ assert.deepEqual(meeting.meetingInfo, {
3627
+ ...FAKE_MEETING_INFO,
3628
+ });
3629
+ assert.equal(meeting.meetingInfoFailureCode, 123456);
3630
+ assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.POLICY);
3631
+ assert.calledWith(meeting.updateMeetingActions);
3632
+
3633
+ assert.calledWith(
3634
+ Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH_ERROR, {
3635
+ correlationId: meeting.correlationId,
3636
+ reason: 'Not allowed to execute the function, some properties on server, or local client state do not allow you to complete this action.',
3637
+ stack: sinon.match.any,
3638
+ }
3639
+ );
3640
+ });
3641
+
3642
+ it('throws PasswordError if password is required', async () => {
3643
+ meeting.attrs.meetingInfoProvider = {
3644
+ fetchMeetingInfo: sinon
3645
+ .stub()
3646
+ .throws(new MeetingInfoV2PasswordError(403004, FAKE_MEETING_INFO)),
3647
+ };
3648
+
3649
+ await assert.isRejected(meeting.refreshPermissionToken());
3650
+
3651
+ assert.calledOnce(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
3652
+ assert.deepEqual(meeting.meetingInfo, {
3653
+ ...FAKE_MEETING_INFO,
3654
+ });
3655
+ assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD);
3656
+ assert.equal(meeting.requiredCaptcha, null);
3657
+ assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
3658
+ assert.calledWith(meeting.updateMeetingActions);
3659
+
3660
+ assert.calledWith(
3661
+ Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH_ERROR, {
3662
+ correlationId: meeting.correlationId,
3663
+ reason: 'Password is required, please use verifyPassword()',
3664
+ stack: sinon.match.any,
3665
+ }
3666
+ );
3667
+ });
3668
+
3669
+ it('throws CaptchaError if captcha is required', async () => {
3670
+ const FAKE_SDK_CAPTCHA_INFO = {
3671
+ captchaId: 'FAKE_CAPTCHA_ID',
3672
+ verificationImageURL: 'FAKE_CAPTCHA_IMAGE_URL',
3673
+ verificationAudioURL: 'FAKE_CAPTCHA_AUDIO_URL',
3674
+ refreshURL: 'FAKE_CAPTCHA_REFRESH_URL',
3675
+ };
3676
+ meeting.attrs.meetingInfoProvider = {
3677
+ fetchMeetingInfo: sinon
3678
+ .stub()
3679
+ .throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
3680
+ };
3681
+
3682
+ await assert.isRejected(meeting.refreshPermissionToken());
3683
+
3684
+ assert.calledOnce(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
3685
+ assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD);
3686
+ assert.equal(meeting.requiredCaptcha, FAKE_SDK_CAPTCHA_INFO);
3687
+ assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
3688
+ assert.calledWith(meeting.updateMeetingActions);
3689
+
3690
+ assert.calledWith(
3691
+ Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH_ERROR, {
3692
+ correlationId: meeting.correlationId,
3693
+ reason: 'Captcha is required.',
3694
+ stack: sinon.match.any,
3695
+ }
3696
+ );
3697
+ });
3698
+ });
3699
+
3487
3700
  describe('#refreshCaptcha', () => {
3488
3701
  it('fails if no captcha required', async () => {
3489
3702
  assert.isRejected(meeting.refreshCaptcha(), Error);