@webex/plugin-meetings 3.7.0-next.57 → 3.7.0-next.59
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/index.js +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/brbState.js +167 -0
- package/dist/meeting/brbState.js.map +1 -0
- package/dist/meeting/index.js +251 -254
- package/dist/meeting/index.js.map +1 -1
- package/dist/reachability/index.js +31 -3
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/meeting/brbState.d.ts +54 -0
- package/dist/types/meeting/index.d.ts +2 -0
- package/dist/types/reachability/index.d.ts +9 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/meeting/brbState.ts +169 -0
- package/src/meeting/index.ts +8 -16
- package/src/reachability/index.ts +29 -1
- package/test/unit/spec/meeting/brbState.ts +114 -0
- package/test/unit/spec/meeting/index.js +14 -25
- package/test/unit/spec/reachability/index.ts +120 -10
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {MediaType} from '@webex/internal-media-core';
|
|
2
|
+
import LoggerProxy from '../common/logs/logger-proxy';
|
|
3
|
+
import type Meeting from '.';
|
|
4
|
+
import SendSlotManager from '../multistream/sendSlotManager';
|
|
5
|
+
|
|
6
|
+
export const createBrbState = (meeting: Meeting, enabled: boolean) => {
|
|
7
|
+
LoggerProxy.logger.info(
|
|
8
|
+
`Meeting:brbState#createBrbState: creating BrbState for meeting id ${meeting?.id}`
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const brbState = new BrbState(meeting, enabled);
|
|
12
|
+
|
|
13
|
+
return brbState;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** The purpose of this class is to manage the local and remote brb state
|
|
17
|
+
* and make sure that the server state always matches the last requested state by the client.
|
|
18
|
+
*/
|
|
19
|
+
export class BrbState {
|
|
20
|
+
state: {
|
|
21
|
+
client: {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
};
|
|
24
|
+
server: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
};
|
|
27
|
+
syncToServerInProgress: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
meeting: Meeting;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Constructor
|
|
34
|
+
*
|
|
35
|
+
* @param {Meeting} meeting - the meeting object
|
|
36
|
+
* @param {boolean} enabled - whether the client audio/video is enabled at all
|
|
37
|
+
*/
|
|
38
|
+
constructor(meeting: Meeting, enabled: boolean) {
|
|
39
|
+
this.meeting = meeting;
|
|
40
|
+
this.state = {
|
|
41
|
+
client: {
|
|
42
|
+
enabled,
|
|
43
|
+
},
|
|
44
|
+
server: {
|
|
45
|
+
enabled: false,
|
|
46
|
+
},
|
|
47
|
+
syncToServerInProgress: false,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Enables/disables brb
|
|
53
|
+
*
|
|
54
|
+
* @param {boolean} enabled
|
|
55
|
+
* @param {SendSlotManager} sendSlotManager
|
|
56
|
+
* @returns {Promise}
|
|
57
|
+
*/
|
|
58
|
+
public enable(enabled: boolean, sendSlotManager: SendSlotManager) {
|
|
59
|
+
this.state.client.enabled = enabled;
|
|
60
|
+
|
|
61
|
+
return this.applyClientStateToServer(sendSlotManager);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Updates the server local and remote brb values so that they match the current client desired state.
|
|
66
|
+
*
|
|
67
|
+
* @param {SendSlotManager} sendSlotManager
|
|
68
|
+
* @returns {Promise}
|
|
69
|
+
*/
|
|
70
|
+
private applyClientStateToServer(sendSlotManager: SendSlotManager) {
|
|
71
|
+
if (this.state.syncToServerInProgress) {
|
|
72
|
+
LoggerProxy.logger.info(
|
|
73
|
+
`Meeting:brbState#applyClientStateToServer: request to server in progress, we need to wait for it to complete`
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return Promise.resolve();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const remoteBrbRequiresSync = this.state.client.enabled !== this.state.server.enabled;
|
|
80
|
+
|
|
81
|
+
LoggerProxy.logger.info(
|
|
82
|
+
`Meeting:brbState#applyClientStateToServer: remoteBrbRequiresSync: ${remoteBrbRequiresSync}`
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
if (!remoteBrbRequiresSync) {
|
|
86
|
+
LoggerProxy.logger.info(
|
|
87
|
+
`Meeting:brbState#applyClientStateToServer: client state already matching server state, nothing to do`
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.state.syncToServerInProgress = true;
|
|
94
|
+
|
|
95
|
+
return this.sendLocalBrbStateToServer(sendSlotManager)
|
|
96
|
+
.then(() => {
|
|
97
|
+
this.state.syncToServerInProgress = false;
|
|
98
|
+
LoggerProxy.logger.info(
|
|
99
|
+
`Meeting:brbState#applyClientStateToServer: sync with server completed`
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync
|
|
103
|
+
this.applyClientStateToServer(sendSlotManager);
|
|
104
|
+
})
|
|
105
|
+
.catch((e) => {
|
|
106
|
+
this.state.syncToServerInProgress = false;
|
|
107
|
+
LoggerProxy.logger.warn(`Meeting:brbState#applyClientStateToServer: error: ${e}`);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Send the local brb state to the server
|
|
113
|
+
*
|
|
114
|
+
* @param {SendSlotManager} sendSlotManager
|
|
115
|
+
* @returns {Promise}
|
|
116
|
+
*/
|
|
117
|
+
private async sendLocalBrbStateToServer(sendSlotManager: SendSlotManager) {
|
|
118
|
+
const {enabled} = this.state.client;
|
|
119
|
+
|
|
120
|
+
if (!this.meeting.isMultistream) {
|
|
121
|
+
const errorMessage = 'Meeting:brbState#sendLocalBrbStateToServer: Not a multistream meeting';
|
|
122
|
+
const error = new Error(errorMessage);
|
|
123
|
+
|
|
124
|
+
LoggerProxy.logger.error(error);
|
|
125
|
+
|
|
126
|
+
return Promise.reject(error);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!this.meeting.mediaProperties.webrtcMediaConnection) {
|
|
130
|
+
const errorMessage =
|
|
131
|
+
'Meeting:brbState#sendLocalBrbStateToServer: WebRTC media connection is not defined';
|
|
132
|
+
const error = new Error(errorMessage);
|
|
133
|
+
|
|
134
|
+
LoggerProxy.logger.error(error);
|
|
135
|
+
|
|
136
|
+
return Promise.reject(error);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// this logic should be applied only to multistream meetings
|
|
140
|
+
return this.meeting.meetingRequest
|
|
141
|
+
.setBrb({
|
|
142
|
+
enabled,
|
|
143
|
+
locusUrl: this.meeting.locusUrl,
|
|
144
|
+
deviceUrl: this.meeting.deviceUrl,
|
|
145
|
+
selfId: this.meeting.selfId,
|
|
146
|
+
})
|
|
147
|
+
.then(() => {
|
|
148
|
+
sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
|
|
149
|
+
})
|
|
150
|
+
.catch((error) => {
|
|
151
|
+
LoggerProxy.logger.error('Meeting:brbState#sendLocalBrbStateToServer: Error ', error);
|
|
152
|
+
|
|
153
|
+
return Promise.reject(error);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* This method should be called whenever the server brb state is changed
|
|
159
|
+
*
|
|
160
|
+
* @param {Boolean} [enabled] true if user has brb enabled, false otherwise
|
|
161
|
+
* @returns {undefined}
|
|
162
|
+
*/
|
|
163
|
+
public handleServerBrbUpdate(enabled?: boolean) {
|
|
164
|
+
LoggerProxy.logger.info(
|
|
165
|
+
`Meeting:brbState#handleServerBrbUpdate: updating server brb to (${enabled})`
|
|
166
|
+
);
|
|
167
|
+
this.state.server.enabled = !!enabled;
|
|
168
|
+
}
|
|
169
|
+
}
|
package/src/meeting/index.ts
CHANGED
|
@@ -163,6 +163,7 @@ import {LocusMediaRequest} from './locusMediaRequest';
|
|
|
163
163
|
import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHandler';
|
|
164
164
|
import JoinWebinarError from '../common/errors/join-webinar-error';
|
|
165
165
|
import Member from '../member';
|
|
166
|
+
import {BrbState, createBrbState} from './brbState';
|
|
166
167
|
import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
|
|
167
168
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
|
168
169
|
|
|
@@ -649,6 +650,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
649
650
|
turnServerUsed: boolean;
|
|
650
651
|
areVoiceaEventsSetup = false;
|
|
651
652
|
isMoveToInProgress = false;
|
|
653
|
+
brbState: BrbState;
|
|
652
654
|
|
|
653
655
|
voiceaListenerCallbacks: object = {
|
|
654
656
|
[VOICEAEVENTS.VOICEA_ANNOUNCEMENT]: (payload: Transcription['languageOptions']) => {
|
|
@@ -3407,6 +3409,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3407
3409
|
});
|
|
3408
3410
|
|
|
3409
3411
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED, (payload) => {
|
|
3412
|
+
this.brbState?.handleServerBrbUpdate(payload?.brb?.enabled);
|
|
3410
3413
|
Trigger.trigger(
|
|
3411
3414
|
this,
|
|
3412
3415
|
{
|
|
@@ -3650,22 +3653,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3650
3653
|
return Promise.reject(error);
|
|
3651
3654
|
}
|
|
3652
3655
|
|
|
3653
|
-
|
|
3654
|
-
return this.meetingRequest
|
|
3655
|
-
.setBrb({
|
|
3656
|
-
enabled,
|
|
3657
|
-
locusUrl: this.locusUrl,
|
|
3658
|
-
deviceUrl: this.deviceUrl,
|
|
3659
|
-
selfId: this.selfId,
|
|
3660
|
-
})
|
|
3661
|
-
.then(() => {
|
|
3662
|
-
this.sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
|
|
3663
|
-
})
|
|
3664
|
-
.catch((error) => {
|
|
3665
|
-
LoggerProxy.logger.error('Meeting:index#beRightBack --> Error ', error);
|
|
3666
|
-
|
|
3667
|
-
return Promise.reject(error);
|
|
3668
|
-
});
|
|
3656
|
+
return this.brbState.enable(enabled, this.sendSlotManager);
|
|
3669
3657
|
}
|
|
3670
3658
|
|
|
3671
3659
|
/**
|
|
@@ -6719,6 +6707,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6719
6707
|
new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
|
|
6720
6708
|
: undefined;
|
|
6721
6709
|
|
|
6710
|
+
// ongoing reachability checks slow down new media connections especially on Firefox, so we stop them
|
|
6711
|
+
this.getWebexObject().meetings.reachability.stopReachability();
|
|
6712
|
+
|
|
6722
6713
|
const mc = Media.createMediaConnection(
|
|
6723
6714
|
this.isMultistream,
|
|
6724
6715
|
this.getMediaConnectionDebugId(),
|
|
@@ -7435,6 +7426,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7435
7426
|
|
|
7436
7427
|
this.audio = createMuteState(AUDIO, this, audioEnabled);
|
|
7437
7428
|
this.video = createMuteState(VIDEO, this, videoEnabled);
|
|
7429
|
+
this.brbState = createBrbState(this, false);
|
|
7438
7430
|
|
|
7439
7431
|
try {
|
|
7440
7432
|
await this.setUpLocalStreamReferences(localStreams);
|
|
@@ -259,6 +259,32 @@ export default class Reachability extends EventsScope {
|
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Stops all reachability checks that are in progress
|
|
264
|
+
* @public
|
|
265
|
+
* @memberof Reachability
|
|
266
|
+
* @returns {void}
|
|
267
|
+
*/
|
|
268
|
+
public stopReachability() {
|
|
269
|
+
// overallTimer is always there only if there is reachability in progress
|
|
270
|
+
if (this.overallTimer) {
|
|
271
|
+
LoggerProxy.logger.log(
|
|
272
|
+
'Reachability:index#stopReachability --> stopping reachability checks'
|
|
273
|
+
);
|
|
274
|
+
this.abortCurrentChecks();
|
|
275
|
+
this.emit(
|
|
276
|
+
{
|
|
277
|
+
file: 'reachability',
|
|
278
|
+
function: 'stopReachability',
|
|
279
|
+
},
|
|
280
|
+
'reachability:stopped',
|
|
281
|
+
{}
|
|
282
|
+
);
|
|
283
|
+
this.sendMetric(true);
|
|
284
|
+
this.resolveReachabilityPromise();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
262
288
|
/**
|
|
263
289
|
* Returns statistics about last reachability results. The returned value is an object
|
|
264
290
|
* with a flat list of properties so that it can be easily sent with metrics
|
|
@@ -637,9 +663,10 @@ export default class Reachability extends EventsScope {
|
|
|
637
663
|
/**
|
|
638
664
|
* Sends a metric with all the statistics about how long reachability took
|
|
639
665
|
*
|
|
666
|
+
* @param {boolean} aborted true if the reachability checks were aborted
|
|
640
667
|
* @returns {void}
|
|
641
668
|
*/
|
|
642
|
-
protected async sendMetric() {
|
|
669
|
+
protected async sendMetric(aborted = false) {
|
|
643
670
|
const results = [];
|
|
644
671
|
|
|
645
672
|
Object.values(this.clusterReachability).forEach((clusterReachability) => {
|
|
@@ -650,6 +677,7 @@ export default class Reachability extends EventsScope {
|
|
|
650
677
|
});
|
|
651
678
|
|
|
652
679
|
const stats = {
|
|
680
|
+
aborted,
|
|
653
681
|
vmn: {
|
|
654
682
|
udp: this.getStatistics(results, 'udp', true),
|
|
655
683
|
},
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import sinon from 'sinon';
|
|
2
|
+
import {assert} from '@webex/test-helper-chai';
|
|
3
|
+
|
|
4
|
+
import testUtils from '../../../utils/testUtils';
|
|
5
|
+
import {BrbState, createBrbState} from '@webex/plugin-meetings/src/meeting/brbState';
|
|
6
|
+
|
|
7
|
+
describe('plugin-meetings', () => {
|
|
8
|
+
let meeting: any;
|
|
9
|
+
let brbState: BrbState;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
meeting = {
|
|
13
|
+
isMultistream: true,
|
|
14
|
+
locusUrl: 'locus url',
|
|
15
|
+
deviceUrl: 'device url',
|
|
16
|
+
selfId: 'self id',
|
|
17
|
+
mediaProperties: {
|
|
18
|
+
webrtcMediaConnection: true,
|
|
19
|
+
},
|
|
20
|
+
sendSlotManager: {
|
|
21
|
+
setSourceStateOverride: sinon.stub(),
|
|
22
|
+
},
|
|
23
|
+
meetingRequest: {
|
|
24
|
+
setBrb: sinon.stub().resolves(),
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
brbState = new BrbState(meeting, false);
|
|
29
|
+
await testUtils.flushPromises();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('brbState library', () => {
|
|
33
|
+
it('takes into account current status when instantiated', async () => {
|
|
34
|
+
// create a new BrbState instance
|
|
35
|
+
brbState = createBrbState(meeting, true);
|
|
36
|
+
await testUtils.flushPromises();
|
|
37
|
+
|
|
38
|
+
assert.isTrue(brbState.state.client.enabled);
|
|
39
|
+
|
|
40
|
+
// now check the opposite case
|
|
41
|
+
brbState = createBrbState(meeting, false);
|
|
42
|
+
await testUtils.flushPromises();
|
|
43
|
+
|
|
44
|
+
assert.isFalse(brbState.state.client.enabled);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('can be enabled', async () => {
|
|
48
|
+
brbState.enable(true, meeting.sendSlotManager);
|
|
49
|
+
brbState.handleServerBrbUpdate(true);
|
|
50
|
+
await testUtils.flushPromises();
|
|
51
|
+
|
|
52
|
+
assert.isTrue(brbState.state.client.enabled);
|
|
53
|
+
assert.isTrue(brbState.state.server.enabled);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('can be disabled', async () => {
|
|
57
|
+
brbState.enable(false, meeting.sendSlotManager);
|
|
58
|
+
brbState.handleServerBrbUpdate(false);
|
|
59
|
+
await testUtils.flushPromises();
|
|
60
|
+
|
|
61
|
+
assert.isFalse(brbState.state.client.enabled);
|
|
62
|
+
assert.isFalse(brbState.state.server.enabled);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('does not send local brb state to server if it is not a multistream meeting', async () => {
|
|
66
|
+
meeting.isMultistream = false;
|
|
67
|
+
brbState.enable(true, meeting.sendSlotManager);
|
|
68
|
+
brbState.handleServerBrbUpdate(true);
|
|
69
|
+
await testUtils.flushPromises();
|
|
70
|
+
|
|
71
|
+
assert.isTrue(meeting.meetingRequest.setBrb.notCalled);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('does not send local brb state to server if webrtc media connection is not defined', async () => {
|
|
75
|
+
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
|
76
|
+
brbState.enable(true, meeting.sendSlotManager);
|
|
77
|
+
brbState.handleServerBrbUpdate(true);
|
|
78
|
+
await testUtils.flushPromises();
|
|
79
|
+
|
|
80
|
+
assert.isTrue(meeting.meetingRequest.setBrb.notCalled);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('does not send request twice when in progress', async () => {
|
|
84
|
+
brbState.state.syncToServerInProgress = true;
|
|
85
|
+
brbState.enable(true, meeting.sendSlotManager);
|
|
86
|
+
await testUtils.flushPromises();
|
|
87
|
+
|
|
88
|
+
assert.isTrue(meeting.meetingRequest.setBrb.notCalled);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('syncs with server when client state does not match server state', async () => {
|
|
92
|
+
brbState.enable(true, meeting.sendSlotManager);
|
|
93
|
+
brbState.handleServerBrbUpdate(true);
|
|
94
|
+
await testUtils.flushPromises();
|
|
95
|
+
|
|
96
|
+
assert.isTrue(meeting.meetingRequest.setBrb.calledOnce);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('sets source state override when client state does not match server state', async () => {
|
|
100
|
+
brbState.enable(true, meeting.sendSlotManager);
|
|
101
|
+
brbState.handleServerBrbUpdate(true);
|
|
102
|
+
await testUtils.flushPromises();
|
|
103
|
+
|
|
104
|
+
assert.isTrue(meeting.sendSlotManager.setSourceStateOverride.calledOnce);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('handles server update', async () => {
|
|
108
|
+
brbState.handleServerBrbUpdate(true);
|
|
109
|
+
await testUtils.flushPromises();
|
|
110
|
+
|
|
111
|
+
assert.isTrue(brbState.state.server.enabled);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -114,6 +114,7 @@ import {ERROR_DESCRIPTIONS} from '@webex/internal-plugin-metrics/src/call-diagno
|
|
|
114
114
|
import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
|
|
115
115
|
|
|
116
116
|
import {EVENT_TRIGGERS as VOICEAEVENTS} from '@webex/internal-plugin-voicea';
|
|
117
|
+
import { createBrbState } from '@webex/plugin-meetings/src/meeting/brbState';
|
|
117
118
|
import JoinForbiddenError from '../../../../src/common/errors/join-forbidden-error';
|
|
118
119
|
|
|
119
120
|
describe('plugin-meetings', () => {
|
|
@@ -246,6 +247,7 @@ describe('plugin-meetings', () => {
|
|
|
246
247
|
isAnyPublicClusterReachable: sinon.stub().resolves(true),
|
|
247
248
|
getReachabilityResults: sinon.stub().resolves(undefined),
|
|
248
249
|
getReachabilityMetrics: sinon.stub().resolves({}),
|
|
250
|
+
stopReachability: sinon.stub(),
|
|
249
251
|
};
|
|
250
252
|
webex.internal.llm.on = sinon.stub();
|
|
251
253
|
webex.internal.newMetrics.callDiagnosticLatencies = new CallDiagnosticLatencies(
|
|
@@ -2095,6 +2097,7 @@ describe('plugin-meetings', () => {
|
|
|
2095
2097
|
someReachabilityMetric1: 'some value1',
|
|
2096
2098
|
someReachabilityMetric2: 'some value2',
|
|
2097
2099
|
}),
|
|
2100
|
+
stopReachability: sinon.stub(),
|
|
2098
2101
|
};
|
|
2099
2102
|
|
|
2100
2103
|
const forceRtcMetricsSend = sinon.stub().resolves();
|
|
@@ -2514,6 +2517,7 @@ describe('plugin-meetings', () => {
|
|
|
2514
2517
|
assert.calledOnce(meeting.setMercuryListener);
|
|
2515
2518
|
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
2516
2519
|
assert.equal(meeting.allowMediaInLobby, allowMediaInLobby);
|
|
2520
|
+
assert.calledOnce(webex.meetings.reachability.stopReachability);
|
|
2517
2521
|
};
|
|
2518
2522
|
|
|
2519
2523
|
it('should attach the media and return promise', async () => {
|
|
@@ -2709,6 +2713,7 @@ describe('plugin-meetings', () => {
|
|
|
2709
2713
|
webex.meetings.reachability = {
|
|
2710
2714
|
isWebexMediaBackendUnreachable: sinon.stub().resolves(false),
|
|
2711
2715
|
getReachabilityMetrics: sinon.stub().resolves(),
|
|
2716
|
+
stopReachability: sinon.stub(),
|
|
2712
2717
|
};
|
|
2713
2718
|
const MOCK_CLIENT_ERROR_CODE = 2004;
|
|
2714
2719
|
const generateClientErrorCodeForIceFailureStub = sinon
|
|
@@ -2917,6 +2922,7 @@ describe('plugin-meetings', () => {
|
|
|
2917
2922
|
.onCall(2)
|
|
2918
2923
|
.resolves(false),
|
|
2919
2924
|
getReachabilityMetrics: sinon.stub().resolves({}),
|
|
2925
|
+
stopReachability: sinon.stub(),
|
|
2920
2926
|
};
|
|
2921
2927
|
const getErrorPayloadForClientErrorCodeStub =
|
|
2922
2928
|
(webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode =
|
|
@@ -3211,6 +3217,7 @@ describe('plugin-meetings', () => {
|
|
|
3211
3217
|
someReachabilityMetric1: 'some value1',
|
|
3212
3218
|
someReachabilityMetric2: 'some value2',
|
|
3213
3219
|
}),
|
|
3220
|
+
stopReachability: sinon.stub(),
|
|
3214
3221
|
};
|
|
3215
3222
|
meeting.iceCandidatesCount = 3;
|
|
3216
3223
|
meeting.iceCandidateErrors.set('701_error', 3);
|
|
@@ -3715,6 +3722,7 @@ describe('plugin-meetings', () => {
|
|
|
3715
3722
|
|
|
3716
3723
|
webex.meetings.reachability = {
|
|
3717
3724
|
isWebexMediaBackendUnreachable: sinon.stub().resolves(unreachable || false),
|
|
3725
|
+
stopReachability: sinon.stub(),
|
|
3718
3726
|
};
|
|
3719
3727
|
|
|
3720
3728
|
const generateClientErrorCodeForIceFailureStub = sinon
|
|
@@ -3812,7 +3820,6 @@ describe('plugin-meetings', () => {
|
|
|
3812
3820
|
};
|
|
3813
3821
|
|
|
3814
3822
|
beforeEach(() => {
|
|
3815
|
-
meeting.meetingRequest.setBrb = sinon.stub().resolves({body: 'test'});
|
|
3816
3823
|
meeting.mediaProperties.webrtcMediaConnection = {createSendSlot: sinon.stub()};
|
|
3817
3824
|
meeting.sendSlotManager.createSlot(
|
|
3818
3825
|
fakeMultistreamRoapMediaConnection,
|
|
@@ -3822,6 +3829,8 @@ describe('plugin-meetings', () => {
|
|
|
3822
3829
|
meeting.locusUrl = 'locus url';
|
|
3823
3830
|
meeting.deviceUrl = 'device url';
|
|
3824
3831
|
meeting.selfId = 'self id';
|
|
3832
|
+
meeting.brbState = createBrbState(meeting, false);
|
|
3833
|
+
meeting.brbState.enable = sinon.stub().resolves();
|
|
3825
3834
|
});
|
|
3826
3835
|
|
|
3827
3836
|
afterEach(() => {
|
|
@@ -3843,7 +3852,7 @@ describe('plugin-meetings', () => {
|
|
|
3843
3852
|
|
|
3844
3853
|
await brbResult;
|
|
3845
3854
|
assert.exists(brbResult.then);
|
|
3846
|
-
assert.calledOnce(meeting.
|
|
3855
|
+
assert.calledOnce(meeting.brbState.enable);
|
|
3847
3856
|
})
|
|
3848
3857
|
|
|
3849
3858
|
it('should disable #beRightBack and return a promise', async () => {
|
|
@@ -3851,12 +3860,12 @@ describe('plugin-meetings', () => {
|
|
|
3851
3860
|
|
|
3852
3861
|
await brbResult;
|
|
3853
3862
|
assert.exists(brbResult.then);
|
|
3854
|
-
assert.calledOnce(meeting.
|
|
3863
|
+
assert.calledOnce(meeting.brbState.enable);
|
|
3855
3864
|
})
|
|
3856
3865
|
|
|
3857
3866
|
it('should throw an error and reject the promise if setBrb fails', async () => {
|
|
3858
3867
|
const error = new Error('setBrb failed');
|
|
3859
|
-
meeting.
|
|
3868
|
+
meeting.brbState.enable.rejects(error);
|
|
3860
3869
|
|
|
3861
3870
|
try {
|
|
3862
3871
|
await meeting.beRightBack(true);
|
|
@@ -3867,27 +3876,6 @@ describe('plugin-meetings', () => {
|
|
|
3867
3876
|
}
|
|
3868
3877
|
})
|
|
3869
3878
|
});
|
|
3870
|
-
|
|
3871
|
-
describe('when in a transcoded meeting', () => {
|
|
3872
|
-
|
|
3873
|
-
beforeEach(() => {
|
|
3874
|
-
meeting.isMultistream = false;
|
|
3875
|
-
});
|
|
3876
|
-
|
|
3877
|
-
it('should ignore enabling #beRightBack', async () => {
|
|
3878
|
-
meeting.beRightBack(true);
|
|
3879
|
-
|
|
3880
|
-
assert.isRejected((Promise.reject()));
|
|
3881
|
-
assert.notCalled(meeting.meetingRequest.setBrb);
|
|
3882
|
-
})
|
|
3883
|
-
|
|
3884
|
-
it('should ignore disabling #beRightBack', async () => {
|
|
3885
|
-
meeting.beRightBack(false);
|
|
3886
|
-
|
|
3887
|
-
assert.isRejected((Promise.reject()));
|
|
3888
|
-
assert.notCalled(meeting.meetingRequest.setBrb);
|
|
3889
|
-
})
|
|
3890
|
-
});
|
|
3891
3879
|
});
|
|
3892
3880
|
|
|
3893
3881
|
/* This set of tests are like semi-integration tests, they use real MuteState, Media, LocusMediaRequest and Roap classes.
|
|
@@ -9230,6 +9218,7 @@ describe('plugin-meetings', () => {
|
|
|
9230
9218
|
|
|
9231
9219
|
it('listens to the brb state changed event', () => {
|
|
9232
9220
|
const assertBrb = (enabled) => {
|
|
9221
|
+
meeting.brbState = createBrbState(meeting, false);
|
|
9233
9222
|
meeting.locusInfo.emit(
|
|
9234
9223
|
{ function: 'test', file: 'test' },
|
|
9235
9224
|
LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED,
|