@webex/plugin-meetings 2.4.2 → 2.7.0

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.
@@ -46,7 +46,11 @@ var BEHAVIORAL_METRICS = {
46
46
  PEERCONNECTION_FAILURE: 'js_sdk_peerConnection_failures',
47
47
  INVALID_ICE_CANDIDATE: 'js_sdk_invalid_ice_candidate',
48
48
  UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',
49
- RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure'
49
+ RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',
50
+ ENABLE_BNR_SUCCESS: 'js_sdk_enable_bnr_success',
51
+ ENABLE_BNR_FAILURE: 'js_sdk_enable_bnr_failure',
52
+ DISABLE_BNR_SUCCESS: 'js_sdk_disable_bnr_success',
53
+ DISABLE_BNR_FAILURE: 'js_sdk_disable_bnr_failure'
50
54
  };
51
55
  exports.default = BEHAVIORAL_METRICS;
52
56
  //# 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","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","RECEIVE_TRANSCRIPTION_FAILURE"],"sources":["constants.js"],"sourcesContent":["\n// 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 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 RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure'\n};\n\n\nexport {BEHAVIORAL_METRICS as default};\n"],"mappings":";;;;;;;;;AACA;AAEA,IAAMA,kBAAkB,GAAG;EACzBC,4BAA4B,EAAE,qCADL;EAEzBC,6BAA6B,EAAE,sCAFN;EAGzBC,0BAA0B,EAAE,mCAHH;EAIzBC,2BAA2B,EAAE,oCAJJ;EAKzBC,YAAY,EAAE,qBALW;EAMzBC,YAAY,EAAE,sBANW;EAOzBC,iBAAiB,EAAE,0BAPM;EAQzBC,iBAAiB,EAAE,2BARM;EASzBC,kBAAkB,EAAE,2BATK;EAUzBC,kBAAkB,EAAE,4BAVK;EAWzBC,qBAAqB,EAAE,8BAXE;EAYzBC,uBAAuB,EAAE,oCAZA;EAazBC,yBAAyB,EAAE,sCAbF;EAczBC,sBAAsB,EAAE,gCAdC;EAezBC,yBAAyB,EAAE,mCAfF;EAgBzBC,uBAAuB,EAAE,iCAhBA;EAkBzBC,4BAA4B,EAAE,qCAlBL;EAmBzBC,sBAAsB,EAAE,+BAnBC;EAoBzBC,yBAAyB,EAAE,mCApBF;EAqBzBC,0BAA0B,EAAE,mCArBH;EAsBzBC,qBAAqB,EAAE,+BAtBE;EAuBzBC,sCAAsC,EAAE,gDAvBf;EAwBzBC,qCAAqC,EAAE,+CAxBd;EAyBzBC,kBAAkB,EAAE,4BAzBK;EA0BzBC,kBAAkB,EAAE,4BA1BK;EA2BzBC,2BAA2B,EAAE,qCA3BJ;EA4BzBC,0BAA0B,EAAE,oCA5BH;EA6BzBC,mBAAmB,EAAE,4BA7BI;EA8BzBC,oBAAoB,EAAE,6BA9BG;EA+BzBC,oBAAoB,EAAE,8BA/BG;EAgCzBC,oBAAoB,EAAE,8BAhCG;EAiCzBC,oBAAoB,EAAE,8BAjCG;EAkCzBC,mBAAmB,EAAE,6BAlCI;EAmCzBC,oBAAoB,EAAE,4BAnCG;EAoCzBC,sBAAsB,EAAE,gCApCC;EAqCzBC,qBAAqB,EAAE,8BArCE;EAsCzBC,mBAAmB,EAAE,4BAtCI;EAuCzBC,6BAA6B,EAAE;AAvCN,CAA3B"}
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","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","RECEIVE_TRANSCRIPTION_FAILURE","ENABLE_BNR_SUCCESS","ENABLE_BNR_FAILURE","DISABLE_BNR_SUCCESS","DISABLE_BNR_FAILURE"],"sources":["constants.js"],"sourcesContent":["\n// 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 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 RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',\n ENABLE_BNR_SUCCESS: 'js_sdk_enable_bnr_success',\n ENABLE_BNR_FAILURE: 'js_sdk_enable_bnr_failure',\n DISABLE_BNR_SUCCESS: 'js_sdk_disable_bnr_success',\n DISABLE_BNR_FAILURE: 'js_sdk_disable_bnr_failure'\n};\n\n\nexport {BEHAVIORAL_METRICS as default};\n"],"mappings":";;;;;;;;;AACA;AAEA,IAAMA,kBAAkB,GAAG;EACzBC,4BAA4B,EAAE,qCADL;EAEzBC,6BAA6B,EAAE,sCAFN;EAGzBC,0BAA0B,EAAE,mCAHH;EAIzBC,2BAA2B,EAAE,oCAJJ;EAKzBC,YAAY,EAAE,qBALW;EAMzBC,YAAY,EAAE,sBANW;EAOzBC,iBAAiB,EAAE,0BAPM;EAQzBC,iBAAiB,EAAE,2BARM;EASzBC,kBAAkB,EAAE,2BATK;EAUzBC,kBAAkB,EAAE,4BAVK;EAWzBC,qBAAqB,EAAE,8BAXE;EAYzBC,uBAAuB,EAAE,oCAZA;EAazBC,yBAAyB,EAAE,sCAbF;EAczBC,sBAAsB,EAAE,gCAdC;EAezBC,yBAAyB,EAAE,mCAfF;EAgBzBC,uBAAuB,EAAE,iCAhBA;EAkBzBC,4BAA4B,EAAE,qCAlBL;EAmBzBC,sBAAsB,EAAE,+BAnBC;EAoBzBC,yBAAyB,EAAE,mCApBF;EAqBzBC,0BAA0B,EAAE,mCArBH;EAsBzBC,qBAAqB,EAAE,+BAtBE;EAuBzBC,sCAAsC,EAAE,gDAvBf;EAwBzBC,qCAAqC,EAAE,+CAxBd;EAyBzBC,kBAAkB,EAAE,4BAzBK;EA0BzBC,kBAAkB,EAAE,4BA1BK;EA2BzBC,2BAA2B,EAAE,qCA3BJ;EA4BzBC,0BAA0B,EAAE,oCA5BH;EA6BzBC,mBAAmB,EAAE,4BA7BI;EA8BzBC,oBAAoB,EAAE,6BA9BG;EA+BzBC,oBAAoB,EAAE,8BA/BG;EAgCzBC,oBAAoB,EAAE,8BAhCG;EAiCzBC,oBAAoB,EAAE,8BAjCG;EAkCzBC,mBAAmB,EAAE,6BAlCI;EAmCzBC,oBAAoB,EAAE,4BAnCG;EAoCzBC,sBAAsB,EAAE,gCApCC;EAqCzBC,qBAAqB,EAAE,8BArCE;EAsCzBC,mBAAmB,EAAE,4BAtCI;EAuCzBC,6BAA6B,EAAE,sCAvCN;EAwCzBC,kBAAkB,EAAE,2BAxCK;EAyCzBC,kBAAkB,EAAE,2BAzCK;EA0CzBC,mBAAmB,EAAE,4BA1CI;EA2CzBC,mBAAmB,EAAE;AA3CI,CAA3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "2.4.2",
3
+ "version": "2.7.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "contributors": [
@@ -24,20 +24,21 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@babel/runtime-corejs2": "^7.14.8",
27
- "@webex/webex-core": "2.4.2",
28
- "@webex/internal-plugin-mercury": "2.4.2",
29
- "@webex/internal-plugin-conversation": "2.4.2",
27
+ "@webex/webex-core": "2.7.0",
28
+ "@webex/internal-plugin-mercury": "2.7.0",
29
+ "@webex/internal-plugin-conversation": "2.7.0",
30
30
  "webrtc-adapter": "^7.7.0",
31
31
  "lodash": "^4.17.21",
32
32
  "uuid": "^3.3.2",
33
33
  "global": "^4.4.0",
34
34
  "ip-anonymize": "^0.1.0",
35
- "@webex/common": "2.4.2",
35
+ "@webex/common": "2.7.0",
36
36
  "bowser": "^2.11.0",
37
37
  "sdp-transform": "^2.12.0",
38
38
  "readable-stream": "^3.6.0",
39
- "@webex/common-timers": "2.4.2",
39
+ "@webex/common-timers": "2.7.0",
40
40
  "btoa": "^1.2.1",
41
+ "@webex/internal-media-core": "^0.0.4-beta",
41
42
  "javascript-state-machine": "^3.1.0",
42
43
  "envify": "^4.1.0"
43
44
  }
@@ -1,6 +1,7 @@
1
1
  import uuid from 'uuid';
2
2
  import {cloneDeep, isEqual, pick} from 'lodash';
3
3
  import {StatelessWebexPlugin} from '@webex/webex-core';
4
+ import {Media as WebRTCMedia} from '@webex/internal-media-core';
4
5
 
5
6
  import {
6
7
  MeetingNotActiveError, createMeetingsError, UserInLobbyError,
@@ -83,6 +84,7 @@ import RoapCollection from '../roap/collection';
83
84
 
84
85
  import InMeetingActions from './in-meeting-actions';
85
86
 
87
+
86
88
  const {isBrowser} = BrowserDetection();
87
89
 
88
90
  const logRequest = (request, {header = '', success = '', failure = ''}) => {
@@ -5739,4 +5741,97 @@ export default class Meeting extends StatelessWebexPlugin {
5739
5741
  this.transcription = undefined;
5740
5742
  }
5741
5743
  };
5744
+
5745
+ /**
5746
+ * enableBNR API
5747
+ * @returns {Promise<Boolean>}
5748
+ * @public
5749
+ * @memberof Meeting
5750
+ */
5751
+ async enableBNR() {
5752
+ LoggerProxy.logger.info('Meeting:index#enableBNR. Enable BNR called');
5753
+ let isSuccess = false;
5754
+
5755
+ try {
5756
+ if (typeof this.mediaProperties === 'undefined' || typeof this.mediaProperties.audioTrack === 'undefined') {
5757
+ throw new Error("Meeting doesn't have an audioTrack attached");
5758
+ }
5759
+ this.mediaProperties.audioTrack = await WebRTCMedia.Effects.BNR.enableBNR(this.mediaProperties.audioTrack);
5760
+ const audioStream = MediaUtil.createMediaStream([this.mediaProperties.audioTrack]);
5761
+
5762
+ LoggerProxy.logger.info('Meeting:index#enableBNR. BNR enabled track obtained from WebRTC & sent to updateAudio');
5763
+ await this.updateAudio({
5764
+ sendAudio: true,
5765
+ receiveAudio: true,
5766
+ stream: audioStream
5767
+ });
5768
+ this.isBnrEnabled = true;
5769
+ isSuccess = true;
5770
+ Metrics.sendBehavioralMetric(
5771
+ BEHAVIORAL_METRICS.ENABLE_BNR_SUCCESS,
5772
+ );
5773
+ }
5774
+ catch (error) {
5775
+ LoggerProxy.logger.error(`Meeting:index#enableBNR. ${error}`);
5776
+
5777
+ Metrics.sendBehavioralMetric(
5778
+ BEHAVIORAL_METRICS.ENABLE_BNR_FAILURE,
5779
+ {
5780
+ reason: error.message,
5781
+ stack: error.stack
5782
+ }
5783
+ );
5784
+
5785
+ throw error;
5786
+ }
5787
+
5788
+ return isSuccess;
5789
+ }
5790
+
5791
+ /**
5792
+ * disableBNR API
5793
+ * @returns {Promise<Boolean>}
5794
+ * @public
5795
+ * @memberof Meeting
5796
+ */
5797
+ async disableBNR() {
5798
+ LoggerProxy.logger.info('Meeting:index#disableBNR. Disable BNR called');
5799
+ let isSuccess = false;
5800
+
5801
+ try {
5802
+ if (typeof this.mediaProperties === 'undefined' || typeof this.mediaProperties.audioTrack === 'undefined') {
5803
+ throw new Error("Meeting doesn't have an audioTrack attached");
5804
+ }
5805
+ this.mediaProperties.audioTrack = WebRTCMedia.Effects.BNR.disableBNR(this.mediaProperties.audioTrack);
5806
+ const audioStream = MediaUtil.createMediaStream([this.mediaProperties.audioTrack]);
5807
+
5808
+ LoggerProxy.logger.info('Meeting:index#disableBNR. Raw media track obtained from WebRTC & sent to updateAudio');
5809
+ await this.updateAudio({
5810
+ sendAudio: true,
5811
+ receiveAudio: true,
5812
+ stream: audioStream
5813
+ });
5814
+ this.isBnrEnabled = false;
5815
+ isSuccess = true;
5816
+
5817
+ Metrics.sendBehavioralMetric(
5818
+ BEHAVIORAL_METRICS.DISABLE_BNR_SUCCESS
5819
+ );
5820
+ }
5821
+ catch (error) {
5822
+ LoggerProxy.logger.error(`Meeting:index#disableBNR. ${error}`);
5823
+
5824
+ Metrics.sendBehavioralMetric(
5825
+ BEHAVIORAL_METRICS.DISABLE_BNR_FAILURE,
5826
+ {
5827
+ reason: error.message,
5828
+ stack: error.stack
5829
+ }
5830
+ );
5831
+
5832
+ throw error;
5833
+ }
5834
+
5835
+ return isSuccess;
5836
+ }
5742
5837
  }
@@ -40,7 +40,11 @@ const BEHAVIORAL_METRICS = {
40
40
  PEERCONNECTION_FAILURE: 'js_sdk_peerConnection_failures',
41
41
  INVALID_ICE_CANDIDATE: 'js_sdk_invalid_ice_candidate',
42
42
  UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',
43
- RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure'
43
+ RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',
44
+ ENABLE_BNR_SUCCESS: 'js_sdk_enable_bnr_success',
45
+ ENABLE_BNR_FAILURE: 'js_sdk_enable_bnr_failure',
46
+ DISABLE_BNR_SUCCESS: 'js_sdk_disable_bnr_success',
47
+ DISABLE_BNR_FAILURE: 'js_sdk_disable_bnr_failure'
44
48
  };
45
49
 
46
50
 
@@ -74,6 +74,13 @@ describe('plugin-meetings', () => {
74
74
  debug: () => {}
75
75
  };
76
76
 
77
+ beforeEach(() => {
78
+ sinon.stub(Metrics, 'sendBehavioralMetric');
79
+ });
80
+ afterEach(() => {
81
+ sinon.restore();
82
+ });
83
+
77
84
  before(() => {
78
85
  const MediaStream = {
79
86
  getVideoTracks: () => [{
@@ -105,6 +112,9 @@ describe('plugin-meetings', () => {
105
112
  groupId: '29d9339cc77bffdd24cb69ee80f6d3200481099bcd0f29267558672de0430777',
106
113
  }
107
114
  ])),
115
+ getSupportedConstraints: sinon.stub().returns({
116
+ sampleRate: true
117
+ })
108
118
  },
109
119
  });
110
120
 
@@ -445,6 +455,194 @@ describe('plugin-meetings', () => {
445
455
  });
446
456
  });
447
457
  });
458
+ describe('BNR', () => {
459
+ class FakeMediaStream {
460
+ constructor() {
461
+ this.active = false;
462
+ this.id = '5146425f-c240-48cc-b86b-27d422988fb7';
463
+ }
464
+
465
+ addTrack = () => undefined;
466
+ }
467
+
468
+ class FakeAudioContext {
469
+ constructor() {
470
+ this.state = 'running';
471
+ this.baseLatency = 0.005333333333333333;
472
+ this.currentTime = 2.7946666666666666;
473
+ this.sampleRate = 48000;
474
+ this.audioWorklet = {
475
+ addModule: async () => undefined,
476
+ };
477
+ }
478
+
479
+ onstatechange = null;
480
+
481
+ createMediaStreamSource() {
482
+ return {
483
+ connect: () => undefined,
484
+ mediaStream: {
485
+ getAudioTracks() {
486
+ // eslint-disable-next-line no-undef
487
+ return [new MediaStreamTrack()];
488
+ },
489
+ },
490
+ };
491
+ }
492
+
493
+ createMediaStreamDestination() {
494
+ return {
495
+ stream: {
496
+ getAudioTracks() {
497
+ // eslint-disable-next-line no-undef
498
+ return [new MediaStreamTrack()];
499
+ },
500
+ },
501
+ };
502
+ }
503
+ }
504
+
505
+ class FakeAudioWorkletNode {
506
+ constructor() {
507
+ this.port = {
508
+ postMessage: () => undefined,
509
+ };
510
+ }
511
+
512
+ connect() {
513
+ /* placeholder method */
514
+ }
515
+ }
516
+
517
+ class FakeMediaStreamTrack {
518
+ constructor() {
519
+ this.kind = 'audio';
520
+ this.enabled = true;
521
+ this.label = 'Default - MacBook Pro Microphone (Built-in)';
522
+ this.muted = false;
523
+ this.readyState = 'live';
524
+ this.contentHint = '';
525
+ }
526
+ }
527
+ Object.defineProperty(global, 'MediaStream', {
528
+ writable: true,
529
+ value: FakeMediaStream,
530
+ });
531
+
532
+ Object.defineProperty(global, 'AudioContext', {
533
+ writable: true,
534
+ value: FakeAudioContext,
535
+ });
536
+
537
+ Object.defineProperty(global, 'AudioWorkletNode', {
538
+ writable: true,
539
+ value: FakeAudioWorkletNode,
540
+ });
541
+
542
+ Object.defineProperty(global, 'MediaStreamTrack', {
543
+ writable: true,
544
+ value: FakeMediaStreamTrack,
545
+ });
546
+
547
+ beforeEach(async () => {
548
+ meeting.canUpdateMedia = sinon.stub().returns(true);
549
+ MeetingUtil.validateOptions = sinon.stub().returns(Promise.resolve());
550
+ MeetingUtil.updateTransceiver = sinon.stub();
551
+ const fakeMediaTrack = () => ({
552
+ stop: () => {},
553
+ readyState: 'live',
554
+ getSettings: () => ({
555
+ sampleRate: 48000
556
+ })
557
+ });
558
+
559
+ meeting.getMediaStreams = sinon.stub().returns(Promise.resolve());
560
+ sinon.replace(meeting, 'addMedia', () => {
561
+ sinon.stub(meeting.mediaProperties, 'audioTrack').value(fakeMediaTrack());
562
+ });
563
+ await meeting.getMediaStreams();
564
+ await meeting.addMedia();
565
+ });
566
+
567
+ describe('#enableBNR', () => {
568
+ it('should have #enableBnr', () => {
569
+ assert.exists(meeting.enableBNR);
570
+ });
571
+
572
+ describe('before audio attached to meeting', () => {
573
+ it('should throw no audio error', async () => {
574
+ await meeting.enableBNR().catch((err) => {
575
+ assert.equal(err.toString(), 'Error: Meeting doesn\'t have an audioTrack attached');
576
+ });
577
+ });
578
+ });
579
+
580
+ describe('after audio attached to meeting', () => {
581
+ it('should return true for appropriate sample rate', async () => {
582
+ const response = await meeting.enableBNR();
583
+
584
+ assert.equal(response, true);
585
+ });
586
+
587
+ it('should throw error for inappropriate sample rate and send error metrics', async () => {
588
+ const fakeMediaTrack = () => ({
589
+ stop: () => {},
590
+ readyState: 'live',
591
+ getSettings: () => ({
592
+ sampleRate: 49000
593
+ })
594
+ });
595
+
596
+ sinon.stub(meeting.mediaProperties, 'audioTrack').value(fakeMediaTrack());
597
+ await meeting.enableBNR().catch((err) => {
598
+ assert(Metrics.sendBehavioralMetric.calledOnce);
599
+ assert.calledWith(
600
+ Metrics.sendBehavioralMetric,
601
+ BEHAVIORAL_METRICS.ENABLE_BNR_FAILURE, {
602
+ reason: err.message,
603
+ stack: err.stack
604
+ }
605
+ );
606
+ assert.equal(err.message, 'Sample rate of 49000 is not supported.');
607
+ });
608
+ });
609
+
610
+ it('should send metrics for enable bnr success', async () => {
611
+ const response = await meeting.enableBNR();
612
+
613
+ assert(Metrics.sendBehavioralMetric.calledOnce);
614
+ assert.calledWith(
615
+ Metrics.sendBehavioralMetric,
616
+ BEHAVIORAL_METRICS.ENABLE_BNR_SUCCESS,
617
+ );
618
+ assert.equal(response, true);
619
+ });
620
+ });
621
+ });
622
+
623
+ describe('#disableBNR', () => {
624
+ it('should have #disableBnr', () => {
625
+ assert.exists(meeting.disableBNR);
626
+ });
627
+
628
+ it('should return true if bnr is disabled on bnr enabled track', async () => {
629
+ const response = await meeting.disableBNR();
630
+
631
+ assert.equal(response, true);
632
+ });
633
+
634
+ it('should throw error if bnr is not enabled before disabling and send error metrics', async () => {
635
+ await meeting.disableBNR().catch((err) => {
636
+ assert(Metrics.sendBehavioralMetric.calledOnce);
637
+ assert.calledWith(
638
+ Metrics.sendBehavioralMetric,
639
+ BEHAVIORAL_METRICS.DISABLE_BNR_FAILURE,
640
+ );
641
+ assert.equal(err.message, 'Can not disable as BNR is not enabled');
642
+ });
643
+ });
644
+ });
645
+ });
448
646
  describe('#muteVideo', () => {
449
647
  it('should have #muteVideo', () => {
450
648
  assert.exists(meeting.muteVideo);
@@ -2606,7 +2804,6 @@ describe('plugin-meetings', () => {
2606
2804
  });
2607
2805
 
2608
2806
  it('should send metrics on reconnect failure', async () => {
2609
- sandbox.stub(Metrics, 'sendBehavioralMetric');
2610
2807
  await assert.isRejected(meeting.reconnect());
2611
2808
  assert(Metrics.sendBehavioralMetric.calledOnce);
2612
2809
  assert.calledWith(