@webex/plugin-meetings 3.0.0-beta.256 → 3.0.0-beta.258

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.
@@ -4,7 +4,7 @@
4
4
 
5
5
  /* eslint-disable class-methods-use-this */
6
6
  /* globals window */
7
- import _ from 'lodash';
7
+ import {uniq, mapValues, pick} from 'lodash';
8
8
 
9
9
  import LoggerProxy from '../common/logs/logger-proxy';
10
10
  import MeetingUtil from '../meeting/util';
@@ -16,7 +16,39 @@ import ReachabilityRequest from './request';
16
16
  const DEFAULT_TIMEOUT = 3000;
17
17
  const VIDEO_MESH_TIMEOUT = 1000;
18
18
 
19
- export type ICECandidateResult = {clusterId: string; elapsed?: string | null; publicIPs?: string[]};
19
+ // result for a specific transport protocol (like udp or tcp)
20
+ export type TransportResult = {
21
+ reachable: 'true' | 'false';
22
+ latencyInMilliseconds?: string;
23
+ clientMediaIPs?: string[];
24
+ untested?: 'true';
25
+ };
26
+
27
+ // reachability result for a specifc media cluster
28
+ type ReachabilityResult = {
29
+ udp: TransportResult;
30
+ tcp: TransportResult;
31
+ xtls: {
32
+ untested: 'true';
33
+ };
34
+ };
35
+ // this is the type that is required by the backend when we send them reachability results
36
+ export type ReachabilityResults = Record<string, ReachabilityResult>;
37
+
38
+ // this is the type used by Reachability class internally and stored in local storage
39
+ type InternalReachabilityResults = Record<
40
+ string,
41
+ ReachabilityResult & {
42
+ isVideoMesh?: boolean;
43
+ }
44
+ >;
45
+
46
+ export type ICECandidateResult = {
47
+ clusterId: string;
48
+ isVideoMesh: boolean;
49
+ elapsed?: string | null;
50
+ publicIPs?: string[];
51
+ };
20
52
  /**
21
53
  * @class Reachability
22
54
  * @export
@@ -61,7 +93,7 @@ export default class Reachability {
61
93
  * @async
62
94
  * @memberof Reachability
63
95
  */
64
- public async gatherReachability() {
96
+ public async gatherReachability(): Promise<InternalReachabilityResults> {
65
97
  this.setup();
66
98
 
67
99
  // Remove stored reachability results to ensure no stale data
@@ -106,13 +138,45 @@ export default class Reachability {
106
138
  }
107
139
  }
108
140
 
141
+ /**
142
+ * Reachability results as an object in the format that backend expects
143
+ *
144
+ * @returns {any} reachability results that need to be sent to the backend
145
+ */
146
+ async getReachabilityResults(): Promise<ReachabilityResults | undefined> {
147
+ let results: ReachabilityResults;
148
+
149
+ // these are the only props that backend needs in the reachability results:
150
+ const reachabilityResultsProps: Array<keyof ReachabilityResult> = ['udp', 'tcp', 'xtls'];
151
+
152
+ try {
153
+ // @ts-ignore
154
+ const resultsJson = await this.webex.boundedStorage.get(
155
+ REACHABILITY.namespace,
156
+ REACHABILITY.localStorageResult
157
+ );
158
+
159
+ const internalResults: InternalReachabilityResults = JSON.parse(resultsJson);
160
+
161
+ results = mapValues(internalResults, (result) => pick(result, reachabilityResultsProps));
162
+ } catch (e) {
163
+ // empty storage, that's ok
164
+ LoggerProxy.logger.warn(
165
+ 'Roap:request#attachReachabilityData --> Error parsing reachability data: ',
166
+ e
167
+ );
168
+ }
169
+
170
+ return results;
171
+ }
172
+
109
173
  /**
110
174
  * fetches reachability data and checks for cluster reachability
111
175
  * @returns {boolean}
112
176
  * @public
113
177
  * @memberof Reachability
114
178
  */
115
- async isAnyClusterReachable() {
179
+ async isAnyPublicClusterReachable() {
116
180
  let reachable = false;
117
181
  // @ts-ignore
118
182
  const reachabilityData = await this.webex.boundedStorage
@@ -121,10 +185,12 @@ export default class Reachability {
121
185
 
122
186
  if (reachabilityData) {
123
187
  try {
124
- const reachabilityResults = JSON.parse(reachabilityData);
188
+ const reachabilityResults: InternalReachabilityResults = JSON.parse(reachabilityData);
125
189
 
126
190
  reachable = Object.values(reachabilityResults).some(
127
- (result: any) => result.udp?.reachable === 'true' || result.tcp?.reachable === 'true'
191
+ (result) =>
192
+ !result.isVideoMesh &&
193
+ (result.udp?.reachable === 'true' || result.tcp?.reachable === 'true')
128
194
  );
129
195
  } catch (e) {
130
196
  LoggerProxy.logger.error(
@@ -144,7 +210,7 @@ export default class Reachability {
144
210
  * @memberof Reachability
145
211
  */
146
212
  private buildPeerConnectionConfig(cluster: any) {
147
- const iceServers = _.uniq(cluster.udp).map((url) => ({
213
+ const iceServers = uniq(cluster.udp).map((url) => ({
148
214
  username: '',
149
215
  credential: '',
150
216
  urls: [url],
@@ -205,7 +271,7 @@ export default class Reachability {
205
271
  * @private
206
272
  * @memberof Reachability
207
273
  */
208
- private getLocalSDPForClusters(clusterList: object) {
274
+ private getLocalSDPForClusters(clusterList: object): Promise<InternalReachabilityResults> {
209
275
  let clusters: any[] = [...Object.keys(clusterList)];
210
276
 
211
277
  clusters = clusters.map(async (key) => {
@@ -218,18 +284,17 @@ export default class Reachability {
218
284
  peerConnection.begin = Date.now();
219
285
  peerConnection.setLocalDescription(description);
220
286
 
221
- return this.iceGatheringState(
222
- peerConnection,
223
- cluster.isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT
224
- ).catch((iceGatheringStateError) => {
225
- LoggerProxy.logger.log(
226
- `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`
227
- );
228
- });
287
+ return this.iceGatheringState(peerConnection, cluster.isVideoMesh).catch(
288
+ (iceGatheringStateError) => {
289
+ LoggerProxy.logger.log(
290
+ `Reachability:index#getLocalSDPForClusters --> Error in getLocalSDP : ${iceGatheringStateError}`
291
+ );
292
+ }
293
+ );
229
294
  });
230
295
 
231
296
  return Promise.all(clusters)
232
- .then(this.parseIceResultsToReachabilityResults)
297
+ .then(this.parseIceResultsToInternalReachabilityResults)
233
298
  .then((reachabilityLatencyResults) => {
234
299
  this.logUnreachableClusters();
235
300
 
@@ -318,12 +383,14 @@ export default class Reachability {
318
383
  * speed.
319
384
  * @private
320
385
  * @param {RTCPeerConnection} peerConnection
321
- * @param {number} timeout
386
+ * @param {boolean} isVideoMesh
322
387
  * @returns {Promise}
323
388
  */
324
- private iceGatheringState(peerConnection: RTCPeerConnection, timeout: number) {
389
+ private iceGatheringState(peerConnection: RTCPeerConnection, isVideoMesh: boolean) {
325
390
  const ELAPSED = 'elapsed';
326
391
 
392
+ const timeout = isVideoMesh ? VIDEO_MESH_TIMEOUT : DEFAULT_TIMEOUT;
393
+
327
394
  return new Promise<ICECandidateResult>((resolve) => {
328
395
  const peerConnectionProxy = new window.Proxy(peerConnection, {
329
396
  // eslint-disable-next-line require-jsdoc
@@ -339,8 +406,14 @@ export default class Reachability {
339
406
  set: (target, property, value) => {
340
407
  // only intercept elapsed property
341
408
  if (property === ELAPSED) {
342
- // @ts-ignore
343
- resolve({clusterId: peerConnection.key, publicIPs: target.publicIPs, elapsed: value});
409
+ resolve({
410
+ // @ts-ignore
411
+ clusterId: peerConnection.key,
412
+ isVideoMesh,
413
+ // @ts-ignore
414
+ publicIPs: target.publicIPs,
415
+ elapsed: value,
416
+ });
344
417
 
345
418
  return true;
346
419
  }
@@ -392,10 +465,12 @@ export default class Reachability {
392
465
  * @protected
393
466
  * @memberof Reachability
394
467
  */
395
- protected parseIceResultsToReachabilityResults(iceResults: Array<ICECandidateResult>) {
468
+ protected parseIceResultsToInternalReachabilityResults(
469
+ iceResults: Array<ICECandidateResult>
470
+ ): InternalReachabilityResults {
396
471
  const reachabilityMap = {};
397
472
 
398
- iceResults.forEach(({clusterId, elapsed, publicIPs}) => {
473
+ iceResults.forEach(({clusterId, isVideoMesh, elapsed, publicIPs}) => {
399
474
  const latencyResult = {};
400
475
 
401
476
  if (!elapsed) {
@@ -417,6 +492,7 @@ export default class Reachability {
417
492
  udp: latencyResult,
418
493
  tcp: {untested: 'true'},
419
494
  xtls: {untested: 'true'},
495
+ isVideoMesh,
420
496
  };
421
497
  });
422
498
 
@@ -426,11 +502,11 @@ export default class Reachability {
426
502
  /**
427
503
  * fetches reachability data
428
504
  * @param {object} clusterList
429
- * @returns {Promise<localSDPData>} reachability check results
505
+ * @returns {Promise<InternalReachabilityResults>} reachability check results
430
506
  * @private
431
507
  * @memberof Reachability
432
508
  */
433
- private performReachabilityCheck(clusterList: object) {
509
+ private performReachabilityCheck(clusterList: object): Promise<InternalReachabilityResults> {
434
510
  if (!clusterList || !Object.keys(clusterList).length) {
435
511
  return Promise.resolve({});
436
512
  }
@@ -49,7 +49,7 @@ class ReachabilityRequest {
49
49
  const {clusters, joinCookie} = res.body;
50
50
 
51
51
  Object.keys(clusters).forEach((key) => {
52
- clusters[key].isVideoMesh = res.body.clusterClasses?.hybridMedia?.includes(key);
52
+ clusters[key].isVideoMesh = !!res.body.clusterClasses?.hybridMedia?.includes(key);
53
53
  });
54
54
 
55
55
  LoggerProxy.logger.log(
@@ -18,23 +18,10 @@ export default class RoapRequest extends StatelessWebexPlugin {
18
18
  let joinCookie;
19
19
 
20
20
  // @ts-ignore
21
- const reachabilityData = await this.webex.boundedStorage
22
- .get(REACHABILITY.namespace, REACHABILITY.localStorageResult)
23
- .catch(() => {});
24
-
25
- if (reachabilityData) {
26
- try {
27
- const reachabilityResult = JSON.parse(reachabilityData);
21
+ const reachabilityResult = await this.webex.meetings.reachability.getReachabilityResults();
28
22
 
29
- /* istanbul ignore else */
30
- if (reachabilityResult && Object.keys(reachabilityResult).length) {
31
- localSdp.reachability = reachabilityResult;
32
- }
33
- } catch (e) {
34
- LoggerProxy.logger.error(
35
- `Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`
36
- );
37
- }
23
+ if (reachabilityResult && Object.keys(reachabilityResult).length) {
24
+ localSdp.reachability = reachabilityResult;
38
25
  }
39
26
 
40
27
  // @ts-ignore
@@ -225,10 +225,11 @@ export default class TurnDiscovery {
225
225
  * @returns {Promise<string>} Promise with empty string if reachability is not skipped or a reason if it is skipped
226
226
  */
227
227
  private async getSkipReason(meeting: Meeting): Promise<string> {
228
- // @ts-ignore - fix type
229
- const isAnyClusterReachable = await meeting.webex.meetings.reachability.isAnyClusterReachable();
228
+ const isAnyPublicClusterReachable =
229
+ // @ts-ignore - fix type
230
+ await meeting.webex.meetings.reachability.isAnyPublicClusterReachable();
230
231
 
231
- if (isAnyClusterReachable) {
232
+ if (isAnyPublicClusterReachable) {
232
233
  LoggerProxy.logger.info(
233
234
  'Roap:turnDiscovery#getSkipReason --> reachability has not failed, skipping TURN discovery'
234
235
  );
@@ -1722,7 +1722,8 @@ describe('plugin-meetings', () => {
1722
1722
  meeting.locusInfo.onFullLocus = sinon.stub();
1723
1723
  meeting.webex.meetings.geoHintInfo = {regionCode: 'EU', countryCode: 'UK'};
1724
1724
  meeting.webex.meetings.reachability = {
1725
- isAnyClusterReachable: sinon.stub().resolves(true),
1725
+ isAnyPublicClusterReachable: sinon.stub().resolves(true),
1726
+ getReachabilityResults: sinon.stub().resolves(undefined),
1726
1727
  };
1727
1728
  meeting.roap.doTurnDiscovery = sinon
1728
1729
  .stub()
@@ -1,12 +1,12 @@
1
1
  import {assert} from '@webex/test-helper-chai';
2
2
  import MockWebex from '@webex/test-helper-mock-webex';
3
3
  import sinon from 'sinon';
4
- import Reachability, {ICECandidateResult} from '@webex/plugin-meetings/src/reachability/';
4
+ import Reachability, {ICECandidateResult, ReachabilityResults} from '@webex/plugin-meetings/src/reachability/';
5
5
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
6
6
 
7
7
  import { IP_VERSION } from '@webex/plugin-meetings/src/constants';
8
8
 
9
- describe('isAnyClusterReachable', () => {
9
+ describe('isAnyPublicClusterReachable', () => {
10
10
  let webex;
11
11
 
12
12
  beforeEach(() => {
@@ -29,7 +29,7 @@ describe('isAnyClusterReachable', () => {
29
29
  }
30
30
  const reachability = new Reachability(webex);
31
31
 
32
- const result = await reachability.isAnyClusterReachable();
32
+ const result = await reachability.isAnyPublicClusterReachable();
33
33
 
34
34
  assert.equal(result, expectedValue);
35
35
  };
@@ -57,6 +57,63 @@ describe('isAnyClusterReachable', () => {
57
57
  it('returns false when reachability.result item is not there', async () => {
58
58
  await checkIsClusterReachable(undefined, false);
59
59
  });
60
+
61
+ describe('ignores video mesh reachability', () => {
62
+ it('returns false if there are no public cluster results, only video mesh', async () => {
63
+ await checkIsClusterReachable({
64
+ x: {
65
+ udp: {reachable: 'true'},
66
+ tcp: {reachable: 'true'},
67
+ isVideoMesh: true,
68
+ },
69
+ y: {
70
+ udp: {reachable: 'false'},
71
+ tcp: {reachable: 'true'},
72
+ isVideoMesh: true,
73
+ }
74
+ }, false);
75
+ });
76
+
77
+ it('returns false if there public cluster reachability failed, only video mesh succeeded', async () => {
78
+ await checkIsClusterReachable({
79
+ x: {
80
+ udp: {reachable: 'false'},
81
+ tcp: {reachable: 'true'},
82
+ isVideoMesh: true,
83
+ },
84
+ y: {
85
+ udp: {reachable: 'true'},
86
+ tcp: {reachable: 'false'},
87
+ isVideoMesh: true,
88
+ },
89
+ publicOne: {
90
+ udp: {reachable: 'false'},
91
+ tcp: {reachable: 'false'},
92
+ isVideoMesh: false,
93
+ }
94
+ }, false);
95
+ });
96
+
97
+ it('returns true if there is at least 1 public cluster result, while video mesh is not reachable', async () => {
98
+ await checkIsClusterReachable({
99
+ x: {
100
+ udp: {reachable: 'true'},
101
+ tcp: {reachable: 'true'},
102
+ isVideoMesh: true,
103
+ },
104
+ y: {
105
+ udp: {reachable: 'false'},
106
+ tcp: {reachable: 'true'},
107
+ isVideoMesh: true,
108
+ },
109
+ publicOne: {
110
+ udp: {reachable: 'false'},
111
+ tcp: {reachable: 'true'},
112
+ isVideoMesh: false,
113
+ }
114
+ }, true);
115
+ });
116
+ })
60
117
  });
61
118
 
62
119
  describe('gatherReachability', () => {
@@ -160,8 +217,8 @@ describe('gatherReachability', () => {
160
217
  let testingClass: TestReachability;
161
218
 
162
219
  class TestReachability extends Reachability {
163
- public testParseIceResultsToReachabilityResults(iceResults: Array<ICECandidateResult>) {
164
- return this.parseIceResultsToReachabilityResults(iceResults);
220
+ public testParseIceResultsToInternalReachabilityResults(iceResults: Array<ICECandidateResult>) {
221
+ return this.parseIceResultsToInternalReachabilityResults(iceResults);
165
222
  }
166
223
  public testAddPublicIP(peerConnection: RTCPeerConnection, publicIP?: string | null) {
167
224
  return this.addPublicIP(peerConnection, publicIP);
@@ -171,22 +228,25 @@ describe('gatherReachability', () => {
171
228
  testingClass = new TestReachability({webex});
172
229
  });
173
230
 
174
- it('calls parseIceResultsToReachabilityResults correctly', () => {
175
- const res = testingClass.testParseIceResultsToReachabilityResults([
231
+ it('calls parseIceResultsToInternalReachabilityResults correctly', () => {
232
+ const res = testingClass.testParseIceResultsToInternalReachabilityResults([
176
233
  {
177
234
  clusterId: 'id1',
178
235
  elapsed: '12312',
179
236
  publicIPs: ['1.1.1.1'],
237
+ isVideoMesh: true,
180
238
  },
181
239
  {
182
240
  clusterId: 'id2',
183
241
  elapsed: null,
184
242
  publicIPs: ['1.1.1.1'],
243
+ isVideoMesh: false,
185
244
  },
186
245
  {
187
246
  clusterId: 'id2',
188
247
  elapsed: '14123',
189
248
  publicIPs: undefined,
249
+ isVideoMesh: false,
190
250
  },
191
251
  ]);
192
252
 
@@ -203,6 +263,7 @@ describe('gatherReachability', () => {
203
263
  latencyInMilliseconds: '12312',
204
264
  reachable: 'true',
205
265
  },
266
+ isVideoMesh: true,
206
267
  },
207
268
  id2: {
208
269
  xtls: {
@@ -215,6 +276,7 @@ describe('gatherReachability', () => {
215
276
  latencyInMilliseconds: '14123',
216
277
  reachable: 'true',
217
278
  },
279
+ isVideoMesh: false,
218
280
  },
219
281
  });
220
282
  });
@@ -260,3 +322,97 @@ describe('gatherReachability', () => {
260
322
  });
261
323
  });
262
324
  });
325
+
326
+ describe('getReachabilityResults', () => {
327
+ let webex;
328
+
329
+ beforeEach(() => {
330
+ webex = new MockWebex();
331
+
332
+ // sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
333
+ });
334
+
335
+ afterEach(() => {
336
+ sinon.restore();
337
+ });
338
+
339
+ const runCheck = async (mockStorage: any, expectedResult: ReachabilityResults) => {
340
+ if (mockStorage) {
341
+ await webex.boundedStorage.put(
342
+ 'Reachability',
343
+ 'reachability.result',
344
+ JSON.stringify(mockStorage)
345
+ );
346
+ }
347
+ const reachability = new Reachability(webex);
348
+
349
+ const result = await reachability.getReachabilityResults();
350
+
351
+ assert.deepEqual(result, expectedResult);
352
+ };
353
+
354
+ it('returns undefined if reading from local storage fails', async () => {
355
+ sinon.stub(webex.boundedStorage, 'get').rejects(new Error('fake error'));
356
+
357
+ const reachability = new Reachability(webex);
358
+
359
+ const result = await reachability.getReachabilityResults();
360
+
361
+ assert.isUndefined(result);
362
+ });
363
+
364
+ it('returns results from local storage, stripping any internal data', async () => {
365
+ await runCheck(
366
+ // mock storage:
367
+ {
368
+ cluster1: {
369
+ udp: {reachable: 'true', latencyInMilliseconds: '100'},
370
+ tcp: {reachable: 'false'},
371
+ xtls: {untested: 'true'},
372
+ },
373
+ cluster2: {
374
+ udp: {reachable: 'true', latencyInMilliseconds: '200'},
375
+ tcp: {reachable: 'false'},
376
+ xtls: {untested: 'true'},
377
+ isVideoMesh: true,
378
+ },
379
+ cluster3: {
380
+ udp: {reachable: 'false'},
381
+ tcp: {reachable: 'true', latencyInMilliseconds: '100', clientMediaIPs: ['10.10.10.10']},
382
+ xtls: {untested: 'true'},
383
+ isVideoMesh: true,
384
+ someOtherField: 'any value',
385
+ },
386
+ cluster4: {
387
+ udp: {reachable: 'false', latencyInMilliseconds: '300'},
388
+ tcp: {reachable: 'false', untested: 'true'},
389
+ xtls: {untested: 'true'},
390
+ someOtherField: 'any value',
391
+ },
392
+ },
393
+ // expected result (same as above, but with isVideoMesh and someOtherField stripped out):
394
+ {
395
+ cluster1: {
396
+ udp: {reachable: 'true', latencyInMilliseconds: '100'},
397
+ tcp: {reachable: 'false'},
398
+ xtls: {untested: 'true'},
399
+ },
400
+ cluster2: {
401
+ udp: {reachable: 'true', latencyInMilliseconds: '200'},
402
+ tcp: {reachable: 'false'},
403
+ xtls: {untested: 'true'},
404
+ },
405
+ cluster3: {
406
+ udp: {reachable: 'false'},
407
+ tcp: {reachable: 'true', latencyInMilliseconds: '100', clientMediaIPs: ['10.10.10.10']},
408
+ xtls: {untested: 'true'},
409
+ },
410
+ cluster4: {
411
+ udp: {reachable: 'false', latencyInMilliseconds: '300'},
412
+ tcp: {reachable: 'false', untested: 'true'},
413
+ xtls: {untested: 'true'},
414
+ },
415
+ }
416
+ );
417
+ });
418
+ });
@@ -64,7 +64,7 @@ describe('Roap', () => {
64
64
  setRoapSeq: sinon.stub(),
65
65
  config: {experimental: {enableTurnDiscovery: false}},
66
66
  locusMediaRequest: {fake: true},
67
- webex: { meetings: { reachability: { isAnyClusterReachable: () => true}}},
67
+ webex: { meetings: { reachability: { isAnyPublicClusterReachable: () => true}}},
68
68
  };
69
69
 
70
70
  sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
@@ -66,6 +66,7 @@ describe('plugin-meetings/roap', () => {
66
66
  JSON.stringify({
67
67
  clusterId: {
68
68
  udp: 'test',
69
+ isVideoMesh: false,
69
70
  },
70
71
  })
71
72
  );
@@ -54,7 +54,7 @@ describe('TurnDiscovery', () => {
54
54
  }),
55
55
  updateMediaConnections: sinon.stub(),
56
56
  webex: {meetings: {reachability: {
57
- isAnyClusterReachable: () => Promise.resolve(false),
57
+ isAnyPublicClusterReachable: () => Promise.resolve(false),
58
58
  }}},
59
59
  isMultistream: false,
60
60
  locusMediaRequest: { fake: true },
@@ -257,8 +257,8 @@ describe('TurnDiscovery', () => {
257
257
  });
258
258
 
259
259
  it('resolves with undefined when cluster is reachable', async () => {
260
- const prev = testMeeting.webex.meetings.reachability.isAnyClusterReachable;
261
- testMeeting.webex.meetings.reachability.isAnyClusterReachable = () => Promise.resolve(true);
260
+ const prev = testMeeting.webex.meetings.reachability.isAnyPublicClusterReachable;
261
+ testMeeting.webex.meetings.reachability.isAnyPublicClusterReachable = () => Promise.resolve(true);
262
262
  const result = await new TurnDiscovery(mockRoapRequest).doTurnDiscovery(testMeeting);
263
263
 
264
264
  const {turnServerInfo, turnDiscoverySkippedReason} = result;
@@ -267,7 +267,7 @@ describe('TurnDiscovery', () => {
267
267
  assert.equal(turnDiscoverySkippedReason, 'reachability');
268
268
  assert.notCalled(mockRoapRequest.sendRoap);
269
269
  assert.notCalled(Metrics.sendBehavioralMetric);
270
- testMeeting.webex.meetings.reachability.isAnyClusterReachable = prev;
270
+ testMeeting.webex.meetings.reachability.isAnyPublicClusterReachable = prev;
271
271
  });
272
272
 
273
273
  it("resolves with undefined if we don't get a response within 10s", async () => {
@@ -379,15 +379,15 @@ describe('TurnDiscovery', () => {
379
379
 
380
380
  describe('isSkipped', () => {
381
381
  [
382
- {enabledInConfig: true, isAnyClusterReachable: true, expectedIsSkipped: true},
383
- {enabledInConfig: true, isAnyClusterReachable: false, expectedIsSkipped: false},
384
- {enabledInConfig: false, isAnyClusterReachable: true, expectedIsSkipped: true},
385
- {enabledInConfig: false, isAnyClusterReachable: false, expectedIsSkipped: true},
386
- ].forEach(({enabledInConfig, isAnyClusterReachable, expectedIsSkipped}) => {
387
- it(`returns ${expectedIsSkipped} when TURN discovery is ${enabledInConfig ? '' : 'not '} enabled in config and isAnyClusterReachable() returns ${isAnyClusterReachable ? 'true' : 'false'}`, async () => {
382
+ {enabledInConfig: true, isAnyPublicClusterReachable: true, expectedIsSkipped: true},
383
+ {enabledInConfig: true, isAnyPublicClusterReachable: false, expectedIsSkipped: false},
384
+ {enabledInConfig: false, isAnyPublicClusterReachable: true, expectedIsSkipped: true},
385
+ {enabledInConfig: false, isAnyPublicClusterReachable: false, expectedIsSkipped: true},
386
+ ].forEach(({enabledInConfig, isAnyPublicClusterReachable, expectedIsSkipped}) => {
387
+ it(`returns ${expectedIsSkipped} when TURN discovery is ${enabledInConfig ? '' : 'not '} enabled in config and isAnyPublicClusterReachable() returns ${isAnyPublicClusterReachable ? 'true' : 'false'}`, async () => {
388
388
  testMeeting.config.experimental.enableTurnDiscovery = enabledInConfig;
389
389
 
390
- sinon.stub(testMeeting.webex.meetings.reachability, 'isAnyClusterReachable').resolves(isAnyClusterReachable);
390
+ sinon.stub(testMeeting.webex.meetings.reachability, 'isAnyPublicClusterReachable').resolves(isAnyPublicClusterReachable);
391
391
 
392
392
  const td = new TurnDiscovery(mockRoapRequest);
393
393