@webex/plugin-meetings 3.8.0-next.30 → 3.8.0-next.32
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/media/index.js +3 -15
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +196 -189
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +0 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +31 -23
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js +17 -0
- package/dist/roap/types.js.map +1 -0
- package/dist/types/meeting/index.d.ts +2 -1
- package/dist/types/meeting/muteState.d.ts +0 -1
- package/dist/types/roap/index.d.ts +3 -2
- package/dist/types/roap/turnDiscovery.d.ts +1 -17
- package/dist/types/roap/types.d.ts +16 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +3 -3
- package/src/media/index.ts +5 -21
- package/src/meeting/index.ts +13 -7
- package/src/meeting/muteState.ts +0 -2
- package/src/reconnection-manager/index.ts +2 -2
- package/src/roap/index.ts +3 -7
- package/src/roap/turnDiscovery.ts +21 -35
- package/src/roap/types.ts +23 -0
- package/test/unit/spec/media/index.ts +6 -16
- package/test/unit/spec/meeting/index.js +32 -21
- package/test/unit/spec/meeting/muteState.js +0 -2
- package/test/unit/spec/reconnection-manager/index.js +4 -4
- package/test/unit/spec/roap/turnDiscovery.ts +72 -28
|
@@ -4,11 +4,11 @@ import {Defer} from '@webex/common';
|
|
|
4
4
|
import Metrics from '../metrics';
|
|
5
5
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
6
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
|
-
import {ROAP
|
|
7
|
+
import {ROAP} from '../constants';
|
|
8
8
|
|
|
9
9
|
import RoapRequest from './request';
|
|
10
10
|
import Meeting from '../meeting';
|
|
11
|
-
import
|
|
11
|
+
import {TurnDiscoverySkipReason, TurnServerInfo, TurnDiscoveryResult} from './types';
|
|
12
12
|
|
|
13
13
|
const TURN_DISCOVERY_TIMEOUT = 10; // in seconds
|
|
14
14
|
|
|
@@ -18,28 +18,6 @@ const TURN_DISCOVERY_TIMEOUT = 10; // in seconds
|
|
|
18
18
|
// and do the SDP offer with seq=1
|
|
19
19
|
const TURN_DISCOVERY_SEQ = 0;
|
|
20
20
|
|
|
21
|
-
const TurnDiscoverySkipReason = {
|
|
22
|
-
missingHttpResponse: 'missing http response', // when we asked for the TURN discovery response to be in the http response, but it wasn't there
|
|
23
|
-
reachability: 'reachability', // when udp reachability to public clusters is ok, so we don't need TURN (this doens't apply when joinWithMedia() is used)
|
|
24
|
-
alreadyInProgress: 'already in progress', // when we try to start TURN discovery while it's already in progress
|
|
25
|
-
} as const;
|
|
26
|
-
|
|
27
|
-
export type TurnDiscoverySkipReason =
|
|
28
|
-
| Enum<typeof TurnDiscoverySkipReason> // this is a kind of FYI, because in practice typescript will infer the type of TurnDiscoverySkipReason as a string
|
|
29
|
-
| string // used in case of errors, contains the error message
|
|
30
|
-
| undefined; // used when TURN discovery is not skipped
|
|
31
|
-
|
|
32
|
-
export type TurnServerInfo = {
|
|
33
|
-
url: string;
|
|
34
|
-
username: string;
|
|
35
|
-
password: string;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export type TurnDiscoveryResult = {
|
|
39
|
-
turnServerInfo?: TurnServerInfo;
|
|
40
|
-
turnDiscoverySkippedReason: TurnDiscoverySkipReason;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
21
|
/**
|
|
44
22
|
* Handles the process of finding out TURN server information from Linus.
|
|
45
23
|
* This is achieved by sending a TURN_DISCOVERY_REQUEST.
|
|
@@ -61,7 +39,7 @@ export default class TurnDiscovery {
|
|
|
61
39
|
constructor(roapRequest: RoapRequest) {
|
|
62
40
|
this.roapRequest = roapRequest;
|
|
63
41
|
this.turnInfo = {
|
|
64
|
-
|
|
42
|
+
urls: [],
|
|
65
43
|
username: '',
|
|
66
44
|
password: '',
|
|
67
45
|
};
|
|
@@ -134,21 +112,27 @@ export default class TurnDiscovery {
|
|
|
134
112
|
}
|
|
135
113
|
|
|
136
114
|
const expectedHeaders = [
|
|
137
|
-
{headerName: 'x-cisco-turn-url', field: '
|
|
138
|
-
{headerName: 'x-cisco-turn-username', field: 'username'},
|
|
139
|
-
{headerName: 'x-cisco-turn-password', field: 'password'},
|
|
115
|
+
{headerName: 'x-cisco-turn-url', field: 'urls', multipleAllowed: true},
|
|
116
|
+
{headerName: 'x-cisco-turn-username', field: 'username', multipleAllowed: false},
|
|
117
|
+
{headerName: 'x-cisco-turn-password', field: 'password', multipleAllowed: false},
|
|
140
118
|
];
|
|
141
119
|
|
|
142
|
-
|
|
120
|
+
const foundHeaders = {};
|
|
143
121
|
|
|
144
122
|
headers?.forEach((receivedHeader) => {
|
|
145
123
|
// check if it matches any of our expected headers
|
|
146
124
|
expectedHeaders.forEach((expectedHeader) => {
|
|
147
125
|
if (receivedHeader.startsWith(`${expectedHeader.headerName}=`)) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
);
|
|
151
|
-
|
|
126
|
+
foundHeaders[expectedHeader.headerName] = true;
|
|
127
|
+
|
|
128
|
+
const headerValue = receivedHeader.substring(expectedHeader.headerName.length + 1);
|
|
129
|
+
|
|
130
|
+
if (expectedHeader.multipleAllowed) {
|
|
131
|
+
this.turnInfo[expectedHeader.field].push(headerValue);
|
|
132
|
+
} else {
|
|
133
|
+
// just store the last one we find
|
|
134
|
+
this.turnInfo[expectedHeader.field] = headerValue;
|
|
135
|
+
}
|
|
152
136
|
}
|
|
153
137
|
});
|
|
154
138
|
});
|
|
@@ -156,7 +140,7 @@ export default class TurnDiscovery {
|
|
|
156
140
|
clearTimeout(this.responseTimer);
|
|
157
141
|
this.responseTimer = undefined;
|
|
158
142
|
|
|
159
|
-
if (
|
|
143
|
+
if (expectedHeaders.some((header) => !foundHeaders[header.headerName])) {
|
|
160
144
|
LoggerProxy.logger.warn(
|
|
161
145
|
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> missing some headers, received ${from}: ${JSON.stringify(
|
|
162
146
|
headers
|
|
@@ -169,9 +153,11 @@ export default class TurnDiscovery {
|
|
|
169
153
|
);
|
|
170
154
|
} else {
|
|
171
155
|
LoggerProxy.logger.info(
|
|
172
|
-
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> received a valid response ${from},
|
|
156
|
+
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> received a valid response ${from}, urls=${this.turnInfo.urls}`
|
|
173
157
|
);
|
|
174
158
|
|
|
159
|
+
this.turnInfo.urls = this.turnInfo.urls.filter((url) => url !== ''); // remove empty urls, we might get them if we land on video-mesh nodes (VMN)
|
|
160
|
+
|
|
175
161
|
this.defer.resolve({isOkRequired: !headers?.includes('noOkInTransaction')});
|
|
176
162
|
}
|
|
177
163
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {Enum} from '../constants';
|
|
2
|
+
|
|
3
|
+
export const TurnDiscoverySkipReason = {
|
|
4
|
+
missingHttpResponse: 'missing http response', // when we asked for the TURN discovery response to be in the http response, but it wasn't there
|
|
5
|
+
reachability: 'reachability', // when udp reachability to public clusters is ok, so we don't need TURN (this doens't apply when joinWithMedia() is used)
|
|
6
|
+
alreadyInProgress: 'already in progress', // when we try to start TURN discovery while it's already in progress
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export type TurnDiscoverySkipReason =
|
|
10
|
+
| Enum<typeof TurnDiscoverySkipReason> // this is a kind of FYI, because in practice typescript will infer the type of TurnDiscoverySkipReason as a string
|
|
11
|
+
| string // used in case of errors, contains the error message
|
|
12
|
+
| undefined; // used when TURN discovery is not skipped
|
|
13
|
+
|
|
14
|
+
export type TurnServerInfo = {
|
|
15
|
+
urls: string[];
|
|
16
|
+
username: string;
|
|
17
|
+
password: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type TurnDiscoveryResult = {
|
|
21
|
+
turnServerInfo?: TurnServerInfo;
|
|
22
|
+
turnDiscoverySkippedReason: TurnDiscoverySkipReason;
|
|
23
|
+
};
|
|
@@ -79,7 +79,7 @@ describe('createMediaConnection', () => {
|
|
|
79
79
|
enableRtx: ENABLE_RTX,
|
|
80
80
|
enableExtmap: ENABLE_EXTMAP,
|
|
81
81
|
turnServerInfo: {
|
|
82
|
-
url: 'turns:turn-server-url:443?transport=tcp',
|
|
82
|
+
urls: ['turns:turn-server-url-1:443?transport=tcp', 'turns:turn-server-url-2:443?transport=tcp'],
|
|
83
83
|
username: 'turn username',
|
|
84
84
|
password: 'turn password',
|
|
85
85
|
},
|
|
@@ -91,12 +91,7 @@ describe('createMediaConnection', () => {
|
|
|
91
91
|
{
|
|
92
92
|
iceServers: [
|
|
93
93
|
{
|
|
94
|
-
urls: 'turn:turn-server-url:
|
|
95
|
-
username: 'turn username',
|
|
96
|
-
credential: 'turn password',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
urls: 'turns:turn-server-url:443?transport=tcp',
|
|
94
|
+
urls: ['turns:turn-server-url-1:443?transport=tcp', 'turns:turn-server-url-2:443?transport=tcp'],
|
|
100
95
|
username: 'turn username',
|
|
101
96
|
credential: 'turn password',
|
|
102
97
|
},
|
|
@@ -159,7 +154,7 @@ describe('createMediaConnection', () => {
|
|
|
159
154
|
},
|
|
160
155
|
rtcMetrics,
|
|
161
156
|
turnServerInfo: {
|
|
162
|
-
url: 'turns:turn-server-url:443?transport=tcp',
|
|
157
|
+
urls: ['turns:turn-server-url-1:443?transport=tcp', 'turns:turn-server-url-2:443?transport=tcp'],
|
|
163
158
|
username: 'turn username',
|
|
164
159
|
password: 'turn password',
|
|
165
160
|
},
|
|
@@ -171,12 +166,7 @@ describe('createMediaConnection', () => {
|
|
|
171
166
|
{
|
|
172
167
|
iceServers: [
|
|
173
168
|
{
|
|
174
|
-
urls: 'turn:turn-server-url:
|
|
175
|
-
username: 'turn username',
|
|
176
|
-
credential: 'turn password',
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
urls: 'turns:turn-server-url:443?transport=tcp',
|
|
169
|
+
urls: ['turns:turn-server-url-1:443?transport=tcp', 'turns:turn-server-url-2:443?transport=tcp'],
|
|
180
170
|
username: 'turn username',
|
|
181
171
|
credential: 'turn password',
|
|
182
172
|
},
|
|
@@ -212,7 +202,7 @@ describe('createMediaConnection', () => {
|
|
|
212
202
|
{testCase: 'turnServerInfo is undefined', turnServerInfo: undefined},
|
|
213
203
|
{
|
|
214
204
|
testCase: 'turnServerInfo.url is empty string',
|
|
215
|
-
turnServerInfo: {
|
|
205
|
+
turnServerInfo: {urls: [], username: 'turn username', password: 'turn password'},
|
|
216
206
|
},
|
|
217
207
|
].forEach(({testCase, turnServerInfo}) => {
|
|
218
208
|
it(`passes empty ICE servers array to MultistreamRoapMediaConnection if ${testCase} (multistream enabled)`, () => {
|
|
@@ -276,7 +266,7 @@ describe('createMediaConnection', () => {
|
|
|
276
266
|
{testCase: 'turnServerInfo is undefined', turnServerInfo: undefined},
|
|
277
267
|
{
|
|
278
268
|
testCase: 'turnServerInfo.url is empty string',
|
|
279
|
-
turnServerInfo: {
|
|
269
|
+
turnServerInfo: {urls: [], username: 'turn username', password: 'turn password'},
|
|
280
270
|
},
|
|
281
271
|
].forEach(({testCase, turnServerInfo}) => {
|
|
282
272
|
it(`passes empty ICE servers array to RoapMediaConnection if ${testCase} (multistream disabled)`, () => {
|
|
@@ -2664,7 +2664,7 @@ describe('plugin-meetings', () => {
|
|
|
2664
2664
|
|
|
2665
2665
|
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
2666
2666
|
turnServerInfo: {
|
|
2667
|
-
|
|
2667
|
+
urls: [FAKE_TURN_URL],
|
|
2668
2668
|
username: FAKE_TURN_USER,
|
|
2669
2669
|
password: FAKE_TURN_PASSWORD,
|
|
2670
2670
|
},
|
|
@@ -2686,7 +2686,7 @@ describe('plugin-meetings', () => {
|
|
|
2686
2686
|
meeting.id,
|
|
2687
2687
|
sinon.match({
|
|
2688
2688
|
turnServerInfo: {
|
|
2689
|
-
|
|
2689
|
+
urls: [FAKE_TURN_URL],
|
|
2690
2690
|
username: FAKE_TURN_USER,
|
|
2691
2691
|
password: FAKE_TURN_PASSWORD,
|
|
2692
2692
|
},
|
|
@@ -2744,7 +2744,7 @@ describe('plugin-meetings', () => {
|
|
|
2744
2744
|
.onSecondCall()
|
|
2745
2745
|
.returns({
|
|
2746
2746
|
turnServerInfo: {
|
|
2747
|
-
|
|
2747
|
+
urls: [FAKE_TURN_URL],
|
|
2748
2748
|
username: FAKE_TURN_USER,
|
|
2749
2749
|
password: FAKE_TURN_PASSWORD,
|
|
2750
2750
|
},
|
|
@@ -2956,7 +2956,7 @@ describe('plugin-meetings', () => {
|
|
|
2956
2956
|
.onSecondCall()
|
|
2957
2957
|
.returns({
|
|
2958
2958
|
turnServerInfo: {
|
|
2959
|
-
|
|
2959
|
+
urls: [FAKE_TURN_URL],
|
|
2960
2960
|
username: FAKE_TURN_USER,
|
|
2961
2961
|
password: FAKE_TURN_PASSWORD,
|
|
2962
2962
|
},
|
|
@@ -3133,7 +3133,7 @@ describe('plugin-meetings', () => {
|
|
|
3133
3133
|
.onSecondCall()
|
|
3134
3134
|
.returns({
|
|
3135
3135
|
turnServerInfo: {
|
|
3136
|
-
|
|
3136
|
+
urls: [FAKE_TURN_URL],
|
|
3137
3137
|
username: FAKE_TURN_USER,
|
|
3138
3138
|
password: FAKE_TURN_PASSWORD,
|
|
3139
3139
|
},
|
|
@@ -3185,7 +3185,7 @@ describe('plugin-meetings', () => {
|
|
|
3185
3185
|
.onSecondCall()
|
|
3186
3186
|
.returns({
|
|
3187
3187
|
turnServerInfo: {
|
|
3188
|
-
|
|
3188
|
+
urls: [FAKE_TURN_URL],
|
|
3189
3189
|
username: FAKE_TURN_USER,
|
|
3190
3190
|
password: FAKE_TURN_PASSWORD,
|
|
3191
3191
|
},
|
|
@@ -3637,7 +3637,7 @@ describe('plugin-meetings', () => {
|
|
|
3637
3637
|
|
|
3638
3638
|
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
3639
3639
|
turnServerInfo: {
|
|
3640
|
-
|
|
3640
|
+
urls: [FAKE_TURN_URL],
|
|
3641
3641
|
username: FAKE_TURN_USER,
|
|
3642
3642
|
password: FAKE_TURN_PASSWORD,
|
|
3643
3643
|
},
|
|
@@ -3663,7 +3663,7 @@ describe('plugin-meetings', () => {
|
|
|
3663
3663
|
meeting.id,
|
|
3664
3664
|
sinon.match({
|
|
3665
3665
|
turnServerInfo: {
|
|
3666
|
-
|
|
3666
|
+
urls: [FAKE_TURN_URL],
|
|
3667
3667
|
username: FAKE_TURN_USER,
|
|
3668
3668
|
password: FAKE_TURN_PASSWORD,
|
|
3669
3669
|
},
|
|
@@ -3887,6 +3887,22 @@ describe('plugin-meetings', () => {
|
|
|
3887
3887
|
assert.isRejected((Promise.reject()));
|
|
3888
3888
|
}
|
|
3889
3889
|
});
|
|
3890
|
+
|
|
3891
|
+
it('updates remote mute state when brb is enabled', async () => {
|
|
3892
|
+
meeting.audio = { handleServerRemoteMuteUpdate: sinon.stub() };
|
|
3893
|
+
|
|
3894
|
+
await meeting.beRightBack(true);
|
|
3895
|
+
|
|
3896
|
+
sinon.assert.calledOnceWithExactly(meeting.audio.handleServerRemoteMuteUpdate, meeting, true);
|
|
3897
|
+
});
|
|
3898
|
+
|
|
3899
|
+
it('does not update remote mute state when brb is disabled', async () => {
|
|
3900
|
+
meeting.audio = { handleServerRemoteMuteUpdate: sinon.stub() };
|
|
3901
|
+
|
|
3902
|
+
await meeting.beRightBack(false);
|
|
3903
|
+
|
|
3904
|
+
assert.notCalled(meeting.audio.handleServerRemoteMuteUpdate);
|
|
3905
|
+
});
|
|
3890
3906
|
});
|
|
3891
3907
|
});
|
|
3892
3908
|
|
|
@@ -3940,7 +3956,7 @@ describe('plugin-meetings', () => {
|
|
|
3940
3956
|
.resolves({id: 'fake clientMediaPreferences'});
|
|
3941
3957
|
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
3942
3958
|
turnServerInfo: {
|
|
3943
|
-
|
|
3959
|
+
urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
|
|
3944
3960
|
username: 'turn user',
|
|
3945
3961
|
password: 'turn password',
|
|
3946
3962
|
},
|
|
@@ -3958,12 +3974,7 @@ describe('plugin-meetings', () => {
|
|
|
3958
3974
|
expectedMediaConnectionConfig = {
|
|
3959
3975
|
iceServers: [
|
|
3960
3976
|
{
|
|
3961
|
-
urls: 'turn:turn-server-
|
|
3962
|
-
username: 'turn user',
|
|
3963
|
-
credential: 'turn password',
|
|
3964
|
-
},
|
|
3965
|
-
{
|
|
3966
|
-
urls: 'turns:turn-server-url:443?transport=tcp',
|
|
3977
|
+
urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
|
|
3967
3978
|
username: 'turn user',
|
|
3968
3979
|
credential: 'turn password',
|
|
3969
3980
|
},
|
|
@@ -5231,7 +5242,7 @@ describe('plugin-meetings', () => {
|
|
|
5231
5242
|
// and check that when we fallback to transcoded we still do another TURN discovery
|
|
5232
5243
|
await runCheck(
|
|
5233
5244
|
{
|
|
5234
|
-
|
|
5245
|
+
urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
|
|
5235
5246
|
username: 'turn user',
|
|
5236
5247
|
password: 'turn password',
|
|
5237
5248
|
},
|
|
@@ -5245,7 +5256,7 @@ describe('plugin-meetings', () => {
|
|
|
5245
5256
|
// but doing it just for completeness
|
|
5246
5257
|
await runCheck(
|
|
5247
5258
|
{
|
|
5248
|
-
|
|
5259
|
+
urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
|
|
5249
5260
|
username: 'turn user',
|
|
5250
5261
|
password: 'turn password',
|
|
5251
5262
|
},
|
|
@@ -7527,19 +7538,19 @@ describe('plugin-meetings', () => {
|
|
|
7527
7538
|
});
|
|
7528
7539
|
});
|
|
7529
7540
|
|
|
7530
|
-
describe('#setIsoLocalClientMeetingJoinTime', () => {
|
|
7541
|
+
describe('#setIsoLocalClientMeetingJoinTime', () => {
|
|
7531
7542
|
it('should fallback to system clock ISO string when given an undefined value', () => {
|
|
7532
7543
|
const currentSystemTime = new Date().toISOString();
|
|
7533
7544
|
meeting.isoLocalClientMeetingJoinTime = undefined;
|
|
7534
7545
|
assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
|
|
7535
7546
|
});
|
|
7536
|
-
|
|
7547
|
+
|
|
7537
7548
|
it('should fallback to system clock ISO string when given an invalid value', () => {
|
|
7538
7549
|
const currentSystemTime = new Date().toISOString();
|
|
7539
7550
|
meeting.isoLocalClientMeetingJoinTime = 'invalid-date';
|
|
7540
7551
|
assert.equal(meeting.isoLocalClientMeetingJoinTime, currentSystemTime);
|
|
7541
7552
|
});
|
|
7542
|
-
|
|
7553
|
+
|
|
7543
7554
|
it('should set the isoLocalClientMeetingJoinTime correctly for a valid date string', () => {
|
|
7544
7555
|
const validDateString = 'Tue, 01 Apr 2025 13:00:36 GMT';
|
|
7545
7556
|
const expectedISOString = new Date(validDateString).toISOString();
|
|
@@ -8699,7 +8710,7 @@ describe('plugin-meetings', () => {
|
|
|
8699
8710
|
meeting.deferSDPAnswer = {
|
|
8700
8711
|
reject: sinon.stub(),
|
|
8701
8712
|
};
|
|
8702
|
-
|
|
8713
|
+
|
|
8703
8714
|
const clearTimeoutSpy = sinon.spy(clock, 'clearTimeout');
|
|
8704
8715
|
|
|
8705
8716
|
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
|
@@ -2,7 +2,6 @@ import sinon from 'sinon';
|
|
|
2
2
|
import {assert} from '@webex/test-helper-chai';
|
|
3
3
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
4
4
|
import {createMuteState, MuteState} from '@webex/plugin-meetings/src/meeting/muteState';
|
|
5
|
-
import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
|
|
6
5
|
import {AUDIO, VIDEO} from '@webex/plugin-meetings/src/constants';
|
|
7
6
|
|
|
8
7
|
import testUtils from '../../../utils/testUtils';
|
|
@@ -39,7 +38,6 @@ describe('plugin-meetings', () => {
|
|
|
39
38
|
unmuteAllowed: true,
|
|
40
39
|
remoteVideoMuted: false,
|
|
41
40
|
unmuteVideoAllowed: true,
|
|
42
|
-
|
|
43
41
|
locusInfo: {
|
|
44
42
|
handleLocusDelta: sinon.stub(),
|
|
45
43
|
},
|
|
@@ -60,7 +60,7 @@ describe('plugin-meetings', () => {
|
|
|
60
60
|
roap: {
|
|
61
61
|
doTurnDiscovery: sinon.stub().resolves({
|
|
62
62
|
turnServerInfo: {
|
|
63
|
-
|
|
63
|
+
urls: ['fake_turn_url1', 'fake_turn_url2'],
|
|
64
64
|
username: 'fake_turn_username',
|
|
65
65
|
password: 'fake_turn_password',
|
|
66
66
|
},
|
|
@@ -137,7 +137,7 @@ describe('plugin-meetings', () => {
|
|
|
137
137
|
assert.calledOnce(fakeMediaConnection.reconnect);
|
|
138
138
|
assert.calledWith(fakeMediaConnection.reconnect, [
|
|
139
139
|
{
|
|
140
|
-
urls: '
|
|
140
|
+
urls: ['fake_turn_url1', 'fake_turn_url2'],
|
|
141
141
|
username: 'fake_turn_username',
|
|
142
142
|
credential: 'fake_turn_password',
|
|
143
143
|
},
|
|
@@ -152,12 +152,12 @@ describe('plugin-meetings', () => {
|
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
// this can happen when we land on a video mesh node
|
|
155
|
-
it('does not use TURN server if TURN
|
|
155
|
+
it('does not use TURN server if TURN urls is an empty array', async () => {
|
|
156
156
|
const rm = new ReconnectionManager(fakeMeeting);
|
|
157
157
|
|
|
158
158
|
fakeMeeting.roap.doTurnDiscovery.resolves({
|
|
159
159
|
turnServerInfo: {
|
|
160
|
-
|
|
160
|
+
urls: [],
|
|
161
161
|
username: 'whatever',
|
|
162
162
|
password: 'whatever',
|
|
163
163
|
},
|