@webex/plugin-meetings 3.0.0-beta.35 → 3.0.0-beta.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/edit-lock-error.js +52 -0
- package/dist/breakouts/edit-lock-error.js.map +1 -0
- package/dist/breakouts/index.js +86 -2
- package/dist/breakouts/index.js.map +1 -1
- package/dist/constants.js +12 -1
- package/dist/constants.js.map +1 -1
- package/dist/media/index.js +4 -18
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +3 -3
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +194 -306
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +7 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/util.js +2 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/metrics/constants.js +0 -4
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reconnection-manager/index.js +1 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/types/constants.d.ts +11 -0
- package/dist/types/media/properties.d.ts +7 -6
- package/dist/types/meeting/index.d.ts +11 -36
- package/dist/types/metrics/constants.d.ts +0 -4
- package/package.json +19 -19
- package/src/breakouts/README.md +8 -2
- package/src/breakouts/edit-lock-error.ts +25 -0
- package/src/breakouts/index.ts +73 -0
- package/src/constants.ts +11 -0
- package/src/media/index.ts +14 -24
- package/src/media/properties.ts +16 -10
- package/src/meeting/index.ts +122 -204
- package/src/meeting/muteState.ts +5 -5
- package/src/meeting/util.ts +5 -4
- package/src/metrics/constants.ts +0 -4
- package/src/reconnection-manager/index.ts +1 -1
- package/test/integration/spec/converged-space-meetings.js +3 -3
- package/test/integration/spec/journey.js +3 -3
- package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
- package/test/unit/spec/breakouts/index.ts +92 -1
- package/test/unit/spec/media/index.ts +8 -6
- package/test/unit/spec/meeting/index.js +87 -114
- package/test/unit/spec/meeting/muteState.js +21 -22
- package/test/unit/spec/meeting/utils.js +3 -1
- package/test/utils/testUtils.js +30 -25
- package/dist/meeting/effectsState.js +0 -262
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/types/meeting/effectsState.d.ts +0 -42
- package/src/meeting/effectsState.ts +0 -211
- package/test/unit/spec/meeting/effectsState.js +0 -285
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-param-reassign */
|
|
2
|
-
import {Media as WebRTCMedia} from '@webex/internal-media-core';
|
|
3
|
-
|
|
4
|
-
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
5
|
-
import Metrics from '../metrics';
|
|
6
|
-
import MediaUtil from '../media/util';
|
|
7
|
-
import LoggerProxy from '../common/logs/logger-proxy';
|
|
8
|
-
import {BNR_STATUS} from '../constants';
|
|
9
|
-
|
|
10
|
-
const createEffectsState = (type: any) => {
|
|
11
|
-
LoggerProxy.logger.info(
|
|
12
|
-
`Meeting:effectState#createEffectsState --> creating effectsState for effect ${type}`
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
return new EffectsState(type);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/* The purpose of this class is to manage the effects state(for eg., BNR).
|
|
19
|
-
*/
|
|
20
|
-
class EffectsState {
|
|
21
|
-
effectType: any;
|
|
22
|
-
pendingPromiseReject: any;
|
|
23
|
-
pendingPromiseResolve: any;
|
|
24
|
-
state: any;
|
|
25
|
-
|
|
26
|
-
constructor(type: any) {
|
|
27
|
-
this.effectType = type;
|
|
28
|
-
this.state = {
|
|
29
|
-
bnr: {
|
|
30
|
-
enabled: BNR_STATUS.NOT_ENABLED,
|
|
31
|
-
},
|
|
32
|
-
callToWebrtcBNRInProgress: false,
|
|
33
|
-
};
|
|
34
|
-
// these 2 hold the resolve, reject methods for the promise we returned to the client in last handleClientRequest() call
|
|
35
|
-
this.pendingPromiseResolve = null;
|
|
36
|
-
this.pendingPromiseReject = null;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @memberof EffectsState
|
|
41
|
-
* @param {Boolean} [isEnable] true for enableBNR, false for disableBNR request
|
|
42
|
-
* @param {Object} [meeting] the meeting object
|
|
43
|
-
* @returns {Promise}
|
|
44
|
-
*/
|
|
45
|
-
async handleClientRequest(isEnable?: boolean, meeting?: object) {
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
if (this.pendingPromiseResolve) {
|
|
48
|
-
// resolve the last promise we returned to the client as the client has issued a new request that has superseded the previous one
|
|
49
|
-
this.pendingPromiseResolve();
|
|
50
|
-
}
|
|
51
|
-
this.pendingPromiseResolve = resolve;
|
|
52
|
-
this.pendingPromiseReject = reject;
|
|
53
|
-
|
|
54
|
-
if (isEnable) this.enableBNR(meeting);
|
|
55
|
-
else this.disableBNR(meeting);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Internal API to return status of BNR
|
|
61
|
-
* @memberof EffectsState
|
|
62
|
-
* @returns {Boolean}
|
|
63
|
-
* @public
|
|
64
|
-
* @memberof Meeting
|
|
65
|
-
*/
|
|
66
|
-
public isBnrEnabled() {
|
|
67
|
-
return this.state.bnr.enabled === BNR_STATUS.ENABLED;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
resolvePromise() {
|
|
71
|
-
if (this.pendingPromiseResolve) {
|
|
72
|
-
this.pendingPromiseResolve(true);
|
|
73
|
-
}
|
|
74
|
-
this.pendingPromiseResolve = null;
|
|
75
|
-
this.pendingPromiseReject = null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
rejectPromise(e) {
|
|
79
|
-
if (this.pendingPromiseReject) {
|
|
80
|
-
this.pendingPromiseReject(e);
|
|
81
|
-
}
|
|
82
|
-
this.pendingPromiseResolve = null;
|
|
83
|
-
this.pendingPromiseReject = null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* enableBNR API
|
|
88
|
-
* @param {Object} meeting the meeting object
|
|
89
|
-
* @returns {Promise<Boolean>}
|
|
90
|
-
* @public
|
|
91
|
-
* @memberof EffectsState
|
|
92
|
-
*/
|
|
93
|
-
public async enableBNR(meeting: any) {
|
|
94
|
-
LoggerProxy.logger.info('Meeting:effectState#enableBNR. Enable BNR called');
|
|
95
|
-
|
|
96
|
-
if (this.isBnrEnabled()) {
|
|
97
|
-
LoggerProxy.logger.warn('Meeting:index#enableBNR. BNR is already enabled');
|
|
98
|
-
|
|
99
|
-
return this.resolvePromise();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (this.state.callToWebrtcBNRInProgress) {
|
|
103
|
-
LoggerProxy.logger.warn(
|
|
104
|
-
'Meeting:effectState#enableBNR. Call to WebRTC in progress, we need to wait for it to complete'
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
return this.resolvePromise();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const {bnr} = this.state;
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
bnr.enabled = BNR_STATUS.SHOULD_ENABLE;
|
|
114
|
-
this.state.callToWebrtcBNRInProgress = true;
|
|
115
|
-
const audioStream = MediaUtil.createMediaStream([meeting.mediaProperties.audioTrack]);
|
|
116
|
-
|
|
117
|
-
LoggerProxy.logger.info(
|
|
118
|
-
'Meeting:effectState#enableBNR. MediaStream created from meeting & sent to updateAudio'
|
|
119
|
-
);
|
|
120
|
-
await meeting.updateAudio({
|
|
121
|
-
sendAudio: true,
|
|
122
|
-
receiveAudio: meeting.mediaProperties.mediaDirection.receiveAudio,
|
|
123
|
-
stream: audioStream,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
LoggerProxy.logger.info(
|
|
127
|
-
'Meeting:effectState#enableBNR. Updated meeting audio with bnr enabled track'
|
|
128
|
-
);
|
|
129
|
-
bnr.enabled = BNR_STATUS.ENABLED;
|
|
130
|
-
this.state.callToWebrtcBNRInProgress = false;
|
|
131
|
-
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ENABLE_BNR_SUCCESS);
|
|
132
|
-
} catch (error) {
|
|
133
|
-
bnr.enabled = BNR_STATUS.NOT_ENABLED;
|
|
134
|
-
this.state.callToWebrtcBNRInProgress = false;
|
|
135
|
-
LoggerProxy.logger.error('Meeting:index#enableBNR.', error);
|
|
136
|
-
|
|
137
|
-
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ENABLE_BNR_FAILURE, {
|
|
138
|
-
reason: error.message,
|
|
139
|
-
stack: error.stack,
|
|
140
|
-
});
|
|
141
|
-
this.rejectPromise(error);
|
|
142
|
-
|
|
143
|
-
throw error;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return this.resolvePromise();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* disableBNR API
|
|
151
|
-
* @param {Object} meeting the meeting object
|
|
152
|
-
* @returns {Promise<Boolean>}
|
|
153
|
-
* @public
|
|
154
|
-
* @memberof EffectsState
|
|
155
|
-
*/
|
|
156
|
-
public async disableBNR(meeting: any) {
|
|
157
|
-
LoggerProxy.logger.info('Meeting:effectState#disableBNR. Disable BNR called');
|
|
158
|
-
|
|
159
|
-
const {bnr} = this.state;
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
if (this.state.callToWebrtcBNRInProgress) {
|
|
163
|
-
LoggerProxy.logger.info(
|
|
164
|
-
'Meeting:effectState#disableBNR. Call to WebRTC in progress, we need to wait for it to complete'
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
return this.resolvePromise();
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
bnr.enabled = BNR_STATUS.SHOULD_DISABLE;
|
|
171
|
-
this.state.callToWebrtcBNRInProgress = true;
|
|
172
|
-
|
|
173
|
-
// @ts-ignore - disableBNR does not expect an argument
|
|
174
|
-
const audioTrack = WebRTCMedia.Effects.BNR.disableBNR(meeting.mediaProperties.audioTrack);
|
|
175
|
-
|
|
176
|
-
const audioStream = MediaUtil.createMediaStream([audioTrack]);
|
|
177
|
-
|
|
178
|
-
LoggerProxy.logger.info(
|
|
179
|
-
'Meeting:effectState#disableBNR. Raw media track obtained from WebRTC & sent to updateAudio'
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
await meeting.updateAudio({
|
|
183
|
-
sendAudio: true,
|
|
184
|
-
receiveAudio: meeting.mediaProperties.mediaDirection.receiveAudio,
|
|
185
|
-
stream: audioStream,
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
bnr.enabled = BNR_STATUS.NOT_ENABLED;
|
|
189
|
-
|
|
190
|
-
this.state.callToWebrtcBNRInProgress = false;
|
|
191
|
-
|
|
192
|
-
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.DISABLE_BNR_SUCCESS);
|
|
193
|
-
} catch (error) {
|
|
194
|
-
bnr.enabled = BNR_STATUS.ENABLED;
|
|
195
|
-
this.state.callToWebrtcBNRInProgress = false;
|
|
196
|
-
LoggerProxy.logger.error(`Meeting:index#disableBNR. ${error}`);
|
|
197
|
-
|
|
198
|
-
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.DISABLE_BNR_FAILURE, {
|
|
199
|
-
reason: error.message,
|
|
200
|
-
stack: error.stack,
|
|
201
|
-
});
|
|
202
|
-
this.rejectPromise(error);
|
|
203
|
-
|
|
204
|
-
throw error;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return this.resolvePromise();
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export default createEffectsState;
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
|
-
import {assert} from '@webex/test-helper-chai';
|
|
3
|
-
import sinon from 'sinon';
|
|
4
|
-
import MockWebex from '@webex/test-helper-mock-webex';
|
|
5
|
-
import {BNR_STATUS} from '@webex/plugin-meetings/src/constants';
|
|
6
|
-
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
7
|
-
import Meeting from '@webex/plugin-meetings/src/meeting';
|
|
8
|
-
import Meetings from '@webex/plugin-meetings';
|
|
9
|
-
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
10
|
-
import MediaUtil from '@webex/plugin-meetings/src/media/util';
|
|
11
|
-
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
12
|
-
import createEffectsState from '@webex/plugin-meetings/src/meeting/effectsState';
|
|
13
|
-
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
14
|
-
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
15
|
-
import LLM from '@webex/internal-plugin-llm';
|
|
16
|
-
import Mercury from '@webex/internal-plugin-mercury';
|
|
17
|
-
|
|
18
|
-
describe('plugin-meetings', () => {
|
|
19
|
-
const logger = {
|
|
20
|
-
info: () => {},
|
|
21
|
-
log: () => {},
|
|
22
|
-
error: () => {},
|
|
23
|
-
warn: () => {},
|
|
24
|
-
trace: () => {},
|
|
25
|
-
debug: () => {},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
sinon.stub(Metrics, 'sendBehavioralMetric');
|
|
30
|
-
});
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
sinon.restore();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
Object.defineProperty(global.window.navigator, 'mediaDevices', {
|
|
36
|
-
writable: true,
|
|
37
|
-
value: {
|
|
38
|
-
getSupportedConstraints: sinon.stub().returns({
|
|
39
|
-
sampleRate: true,
|
|
40
|
-
}),
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
LoggerConfig.set({verboseEvents: true, enable: false});
|
|
44
|
-
LoggerProxy.set(logger);
|
|
45
|
-
|
|
46
|
-
let webex;
|
|
47
|
-
let meeting;
|
|
48
|
-
let uuid1;
|
|
49
|
-
|
|
50
|
-
const fakeMediaTrack = () => ({
|
|
51
|
-
id: Date.now().toString(),
|
|
52
|
-
stop: () => {},
|
|
53
|
-
readyState: 'live',
|
|
54
|
-
enabled: true,
|
|
55
|
-
getSettings: () => ({
|
|
56
|
-
sampleRate: 48000,
|
|
57
|
-
}),
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
class FakeMediaStream {
|
|
61
|
-
constructor(tracks) {
|
|
62
|
-
this.active = false;
|
|
63
|
-
this.id = '5146425f-c240-48cc-b86b-27d422988fb7';
|
|
64
|
-
this.tracks = tracks;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
addTrack = () => undefined;
|
|
68
|
-
|
|
69
|
-
getAudioTracks = () => this.tracks;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
class FakeAudioContext {
|
|
73
|
-
constructor() {
|
|
74
|
-
this.state = 'running';
|
|
75
|
-
this.baseLatency = 0.005333333333333333;
|
|
76
|
-
this.currentTime = 2.7946666666666666;
|
|
77
|
-
this.sampleRate = 48000;
|
|
78
|
-
this.audioWorklet = {
|
|
79
|
-
addModule: async () => undefined,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
onstatechange = null;
|
|
84
|
-
|
|
85
|
-
createMediaStreamSource() {
|
|
86
|
-
return {
|
|
87
|
-
connect: () => undefined,
|
|
88
|
-
mediaStream: {
|
|
89
|
-
getAudioTracks() {
|
|
90
|
-
// eslint-disable-next-line no-undef
|
|
91
|
-
return [new MediaStreamTrack()];
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
createMediaStreamDestination() {
|
|
98
|
-
return {
|
|
99
|
-
stream: {
|
|
100
|
-
getAudioTracks() {
|
|
101
|
-
// eslint-disable-next-line no-undef
|
|
102
|
-
return [new MediaStreamTrack()];
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
class FakeAudioWorkletNode {
|
|
110
|
-
constructor() {
|
|
111
|
-
this.port = {
|
|
112
|
-
postMessage: () => undefined,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
connect() {
|
|
117
|
-
/* placeholder method */
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
class FakeMediaStreamTrack {
|
|
122
|
-
constructor() {
|
|
123
|
-
this.kind = 'audio';
|
|
124
|
-
this.enabled = true;
|
|
125
|
-
this.label = 'Default - MacBook Pro Microphone (Built-in)';
|
|
126
|
-
this.muted = false;
|
|
127
|
-
this.readyState = 'live';
|
|
128
|
-
this.contentHint = '';
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
getSettings() {
|
|
132
|
-
return {
|
|
133
|
-
sampleRate: 48000,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
Object.defineProperty(global, 'MediaStream', {
|
|
138
|
-
writable: true,
|
|
139
|
-
value: FakeMediaStream,
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
Object.defineProperty(global, 'AudioContext', {
|
|
143
|
-
writable: true,
|
|
144
|
-
value: FakeAudioContext,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
Object.defineProperty(global, 'AudioWorkletNode', {
|
|
148
|
-
writable: true,
|
|
149
|
-
value: FakeAudioWorkletNode,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
Object.defineProperty(global, 'MediaStreamTrack', {
|
|
153
|
-
writable: true,
|
|
154
|
-
value: FakeMediaStreamTrack,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
let effects;
|
|
158
|
-
|
|
159
|
-
beforeEach(() => {
|
|
160
|
-
webex = new MockWebex({
|
|
161
|
-
children: {
|
|
162
|
-
meetings: Meetings,
|
|
163
|
-
llm: LLM,
|
|
164
|
-
mercury: Mercury,
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
meeting = new Meeting(
|
|
168
|
-
{
|
|
169
|
-
userId: uuid1,
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
parent: webex,
|
|
173
|
-
}
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
effects = createEffectsState('BNR');
|
|
177
|
-
meeting.canUpdateMedia = sinon.stub().returns(true);
|
|
178
|
-
MeetingUtil.validateOptions = sinon.stub().returns(Promise.resolve());
|
|
179
|
-
|
|
180
|
-
meeting.addMedia = sinon.stub().returns(Promise.resolve());
|
|
181
|
-
meeting.getMediaStreams = sinon.stub().returns(Promise.resolve());
|
|
182
|
-
sinon.stub(meeting, 'effects').value(effects);
|
|
183
|
-
sinon.replace(meeting, 'addMedia', () => {
|
|
184
|
-
sinon.stub(meeting.mediaProperties, 'audioTrack').value(fakeMediaTrack());
|
|
185
|
-
sinon.stub(meeting.mediaProperties, 'mediaDirection').value({
|
|
186
|
-
receiveAudio: true,
|
|
187
|
-
});
|
|
188
|
-
sinon
|
|
189
|
-
.stub(meeting.mediaProperties, 'webrtcMediaConnection')
|
|
190
|
-
.value({updateSendReceiveOptions: sinon.stub()});
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
describe('bnr effect library', () => {
|
|
195
|
-
beforeEach(async () => {
|
|
196
|
-
await meeting.getMediaStreams();
|
|
197
|
-
await meeting.addMedia();
|
|
198
|
-
});
|
|
199
|
-
describe('#enableBNR', () => {
|
|
200
|
-
it('should have #enableBnr', () => {
|
|
201
|
-
assert.exists(effects.enableBNR);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('does bnr effect enable on audio track', async () => {
|
|
205
|
-
assert.isTrue(await effects.handleClientRequest(true, meeting));
|
|
206
|
-
assert.equal(effects.state.bnr.enabled, BNR_STATUS.ENABLED);
|
|
207
|
-
|
|
208
|
-
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
209
|
-
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ENABLE_BNR_SUCCESS);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('does resolve request if bnr is already enabled', async () => {
|
|
213
|
-
effects.state.bnr.enabled = BNR_STATUS.ENABLED;
|
|
214
|
-
assert.isTrue(await effects.handleClientRequest(true, meeting));
|
|
215
|
-
assert.equal(effects.state.bnr.enabled, BNR_STATUS.ENABLED);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it('if called twice, does bnr effect enable on audio track for the first request and resolves second', async () => {
|
|
219
|
-
Promise.all([
|
|
220
|
-
effects.handleClientRequest(true, meeting),
|
|
221
|
-
effects.handleClientRequest(true, meeting),
|
|
222
|
-
]).then((resolveFirst, resolveSecond) => {
|
|
223
|
-
assert.isTrue(resolveFirst);
|
|
224
|
-
assert.isTrue(resolveSecond);
|
|
225
|
-
assert.calledOnce(MediaUtil.createMediaStream);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('should throw error for inappropriate sample rate and send error metrics', async () => {
|
|
230
|
-
const fakeMediaTrack1 = () => ({
|
|
231
|
-
id: Date.now().toString(),
|
|
232
|
-
stop: () => {},
|
|
233
|
-
readyState: 'live',
|
|
234
|
-
getSettings: () => ({
|
|
235
|
-
sampleRate: 49000,
|
|
236
|
-
}),
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
sinon.stub(meeting.mediaProperties, 'audioTrack').value(fakeMediaTrack1());
|
|
240
|
-
|
|
241
|
-
// eslint-disable-next-line no-undef
|
|
242
|
-
MediaUtil.createMediaStream = sinon.stub().returns(new MediaStream([fakeMediaTrack1()]));
|
|
243
|
-
try {
|
|
244
|
-
await effects.handleClientRequest(true, meeting);
|
|
245
|
-
} catch (err) {
|
|
246
|
-
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
247
|
-
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ENABLE_BNR_FAILURE, {
|
|
248
|
-
reason: err.message,
|
|
249
|
-
stack: err.stack,
|
|
250
|
-
});
|
|
251
|
-
assert.equal(err.message, 'Sample rate of 49000 is not supported.');
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
describe('#disableBNR', () => {
|
|
257
|
-
beforeEach(() => {
|
|
258
|
-
effects.state.bnr.enabled = BNR_STATUS.ENABLED;
|
|
259
|
-
});
|
|
260
|
-
it('should have #disableBnr', () => {
|
|
261
|
-
assert.exists(effects.disableBNR);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('does bnr disable on audio track', async () => {
|
|
265
|
-
assert.isTrue(await effects.handleClientRequest(false, meeting));
|
|
266
|
-
assert.equal(effects.state.bnr.enabled, BNR_STATUS.NOT_ENABLED);
|
|
267
|
-
|
|
268
|
-
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
269
|
-
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.DISABLE_BNR_SUCCESS);
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('reject request for disable bnr if not enabled', async () => {
|
|
273
|
-
try {
|
|
274
|
-
await effects.handleClientRequest(false, meeting);
|
|
275
|
-
} catch (e) {
|
|
276
|
-
assert.equal(e.message, 'Can not disable as BNR is not enabled');
|
|
277
|
-
assert.equal(effects.state.bnr.enabled, BNR_STATUS.ENABLED);
|
|
278
|
-
|
|
279
|
-
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
280
|
-
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.DISABLE_BNR_FAILURE);
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
});
|
|
285
|
-
});
|