@webex/plugin-meetings 3.3.0 → 3.3.1
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/constants.js +4 -2
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/mediaQualityMetrics/config.js +10 -10
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/index.js +21 -8
- package/dist/meeting/index.js.map +1 -1
- package/dist/meetings/index.js +6 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +82 -9
- package/dist/reachability/index.js.map +1 -1
- package/dist/statsAnalyzer/index.js +4 -2
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +14 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/constants.d.ts +2 -1
- package/dist/types/mediaQualityMetrics/config.d.ts +8 -2
- package/dist/types/meeting/index.d.ts +8 -0
- package/dist/types/reachability/index.d.ts +11 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/constants.ts +2 -1
- package/src/mediaQualityMetrics/config.ts +13 -7
- package/src/meeting/index.ts +23 -9
- package/src/meetings/index.ts +7 -2
- package/src/reachability/index.ts +57 -0
- package/src/statsAnalyzer/index.ts +6 -3
- package/src/statsAnalyzer/mqaUtil.ts +18 -0
- package/test/unit/spec/meeting/index.js +28 -8
- package/test/unit/spec/meetings/index.js +38 -15
- package/test/unit/spec/reachability/index.ts +266 -0
- package/test/unit/spec/stats-analyzer/index.js +89 -8
|
@@ -998,12 +998,11 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
998
998
|
result.qualityLimitationReason;
|
|
999
999
|
this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges =
|
|
1000
1000
|
result.qualityLimitationResolutionChanges;
|
|
1001
|
-
this.statsResults[mediaType][sendrecvType].
|
|
1001
|
+
this.statsResults[mediaType][sendrecvType].totalRtxPacketsSent =
|
|
1002
1002
|
result.retransmittedPacketsSent;
|
|
1003
|
+
this.statsResults[mediaType][sendrecvType].totalRtxBytesSent = result.retransmittedBytesSent;
|
|
1003
1004
|
this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;
|
|
1004
1005
|
this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;
|
|
1005
|
-
this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =
|
|
1006
|
-
result.retransmittedBytesSent;
|
|
1007
1006
|
this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
|
|
1008
1007
|
this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
|
|
1009
1008
|
}
|
|
@@ -1136,6 +1135,10 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1136
1135
|
this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;
|
|
1137
1136
|
this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;
|
|
1138
1137
|
this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;
|
|
1138
|
+
this.statsResults[mediaType][sendrecvType].totalRtxPacketsReceived =
|
|
1139
|
+
result.retransmittedPacketsReceived;
|
|
1140
|
+
this.statsResults[mediaType][sendrecvType].totalRtxBytesReceived =
|
|
1141
|
+
result.retransmittedBytesReceived;
|
|
1139
1142
|
|
|
1140
1143
|
this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);
|
|
1141
1144
|
|
|
@@ -237,10 +237,16 @@ export const getVideoReceiverMqa = ({
|
|
|
237
237
|
const lastPacketsLost = getLastTotalValue('totalPacketsLost');
|
|
238
238
|
const lastBytesReceived = getLastTotalValue('totalBytesReceived');
|
|
239
239
|
|
|
240
|
+
const lastRtxPacketsReceived = getLastTotalValue('totalRtxPacketsReceived');
|
|
241
|
+
const lastRtxBytesReceived = getLastTotalValue('totalRtxBytesReceived');
|
|
242
|
+
|
|
240
243
|
const packetsLost = getTotalValue('totalPacketsLost');
|
|
241
244
|
const totalPacketsReceived = getTotalValue('totalPacketsReceived');
|
|
242
245
|
const totalBytesReceived = getTotalValue('totalBytesReceived');
|
|
243
246
|
|
|
247
|
+
const totalRtxPacketsReceived = getTotalValue('totalRtxPacketsReceived');
|
|
248
|
+
const totalRtxBytesReceived = getTotalValue('totalRtxBytesReceived');
|
|
249
|
+
|
|
244
250
|
const meanRemoteJitter = Object.keys(statsResults)
|
|
245
251
|
.filter((mt) => mt.includes(baseMediaType))
|
|
246
252
|
.reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRemoteJitter), []);
|
|
@@ -266,10 +272,15 @@ export const getVideoReceiverMqa = ({
|
|
|
266
272
|
|
|
267
273
|
// Calculate the outgoing bitrate
|
|
268
274
|
const totalBytesReceivedInaMin = totalBytesReceived - lastBytesReceived;
|
|
275
|
+
const totalRtxBytesReceivedInaMin = totalRtxBytesReceived - lastRtxBytesReceived;
|
|
269
276
|
|
|
270
277
|
videoReceiver.common.rtpBitrate = totalBytesReceivedInaMin
|
|
271
278
|
? (totalBytesReceivedInaMin * 8) / 60
|
|
272
279
|
: 0;
|
|
280
|
+
videoReceiver.common.rtxPackets = totalRtxPacketsReceived - lastRtxPacketsReceived;
|
|
281
|
+
videoReceiver.common.rtxBitrate = totalRtxBytesReceivedInaMin
|
|
282
|
+
? (totalRtxBytesReceivedInaMin * 8) / 60
|
|
283
|
+
: 0;
|
|
273
284
|
};
|
|
274
285
|
|
|
275
286
|
export const getVideoReceiverStreamMqa = ({
|
|
@@ -349,11 +360,15 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, b
|
|
|
349
360
|
const lastPacketsSent = getLastTotalValue('totalPacketsSent');
|
|
350
361
|
const lastBytesSent = getLastTotalValue('totalBytesSent');
|
|
351
362
|
const lastPacketsLostTotal = getLastTotalValue('totalPacketsLostOnReceiver');
|
|
363
|
+
const lastRtxPacketsSent = getLastTotalValue('totalRtxPacketsSent');
|
|
364
|
+
const lastRtxBytesSent = getLastTotalValue('totalRtxBytesSent');
|
|
352
365
|
|
|
353
366
|
const totalPacketsLostOnReceiver = getTotalValue('totalPacketsLostOnReceiver');
|
|
354
367
|
const totalPacketsSent = getTotalValue('totalPacketsSent');
|
|
355
368
|
const totalBytesSent = getTotalValue('totalBytesSent');
|
|
356
369
|
const availableOutgoingBitrate = getTotalValue('availableOutgoingBitrate');
|
|
370
|
+
const totalRtxPacketsSent = getTotalValue('totalRtxPacketsSent');
|
|
371
|
+
const totalRtxBytesSent = getTotalValue('totalRtxBytesSent');
|
|
357
372
|
|
|
358
373
|
videoSender.common.common.direction =
|
|
359
374
|
statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
|
|
@@ -389,8 +404,11 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, b
|
|
|
389
404
|
|
|
390
405
|
// Calculate the outgoing bitrate
|
|
391
406
|
const totalBytesSentInaMin = totalBytesSent - lastBytesSent;
|
|
407
|
+
const totalRtxBytesSentInaMin = totalRtxBytesSent - lastRtxBytesSent;
|
|
392
408
|
|
|
393
409
|
videoSender.common.rtpBitrate = totalBytesSentInaMin ? (totalBytesSentInaMin * 8) / 60 : 0;
|
|
410
|
+
videoSender.common.rtxPackets = totalRtxPacketsSent - lastRtxPacketsSent;
|
|
411
|
+
videoSender.common.rtxBitrate = totalRtxBytesSentInaMin ? (totalRtxBytesSentInaMin * 8) / 60 : 0;
|
|
394
412
|
};
|
|
395
413
|
|
|
396
414
|
export const getVideoSenderStreamMqa = ({
|
|
@@ -1302,6 +1302,31 @@ describe('plugin-meetings', () => {
|
|
|
1302
1302
|
);
|
|
1303
1303
|
});
|
|
1304
1304
|
});
|
|
1305
|
+
|
|
1306
|
+
describe('#handleLLMOnline', () => {
|
|
1307
|
+
beforeEach(() => {
|
|
1308
|
+
webex.internal.llm.off = sinon.stub();
|
|
1309
|
+
});
|
|
1310
|
+
|
|
1311
|
+
it('turns off llm online, emits transcription connected events', () => {
|
|
1312
|
+
meeting.handleLLMOnline();
|
|
1313
|
+
assert.calledOnceWithExactly(
|
|
1314
|
+
webex.internal.llm.off,
|
|
1315
|
+
'online',
|
|
1316
|
+
meeting.handleLLMOnline
|
|
1317
|
+
);
|
|
1318
|
+
assert.calledWith(
|
|
1319
|
+
TriggerProxy.trigger,
|
|
1320
|
+
sinon.match.instanceOf(Meeting),
|
|
1321
|
+
{
|
|
1322
|
+
file: 'meeting/index',
|
|
1323
|
+
function: 'handleLLMOnline',
|
|
1324
|
+
},
|
|
1325
|
+
EVENT_TRIGGERS.MEETING_TRANSCRIPTION_CONNECTED
|
|
1326
|
+
);
|
|
1327
|
+
});
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1305
1330
|
describe('#join', () => {
|
|
1306
1331
|
let sandbox = null;
|
|
1307
1332
|
let setCorrelationIdSpy;
|
|
@@ -1351,15 +1376,10 @@ describe('plugin-meetings', () => {
|
|
|
1351
1376
|
assert.calledOnce(MeetingUtil.joinMeeting);
|
|
1352
1377
|
assert.calledOnce(meeting.setLocus);
|
|
1353
1378
|
assert.equal(result, joinMeetingResult);
|
|
1354
|
-
|
|
1355
1379
|
assert.calledWith(
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
file: 'meeting/index',
|
|
1360
|
-
function: 'join',
|
|
1361
|
-
},
|
|
1362
|
-
EVENT_TRIGGERS.MEETING_TRANSCRIPTION_CONNECTED
|
|
1380
|
+
webex.internal.llm.on,
|
|
1381
|
+
'online',
|
|
1382
|
+
meeting.handleLLMOnline
|
|
1363
1383
|
);
|
|
1364
1384
|
});
|
|
1365
1385
|
|
|
@@ -18,6 +18,7 @@ import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy
|
|
|
18
18
|
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
19
19
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
20
20
|
import Meeting, {CallStateForMetrics} from '@webex/plugin-meetings/src/meeting';
|
|
21
|
+
import {Services} from '@webex/webex-core';
|
|
21
22
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
22
23
|
import Meetings from '@webex/plugin-meetings/src/meetings';
|
|
23
24
|
import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
|
|
@@ -75,6 +76,8 @@ describe('plugin-meetings', () => {
|
|
|
75
76
|
let test1;
|
|
76
77
|
let test2;
|
|
77
78
|
let locusInfo;
|
|
79
|
+
let services;
|
|
80
|
+
let catalog;
|
|
78
81
|
|
|
79
82
|
describe('meetings index', () => {
|
|
80
83
|
beforeEach(() => {
|
|
@@ -93,9 +96,13 @@ describe('plugin-meetings', () => {
|
|
|
93
96
|
device: Device,
|
|
94
97
|
mercury: Mercury,
|
|
95
98
|
meetings: Meetings,
|
|
99
|
+
services: Services,
|
|
96
100
|
},
|
|
97
101
|
});
|
|
98
102
|
|
|
103
|
+
services = webex.internal.services;
|
|
104
|
+
catalog = services._getCatalog();
|
|
105
|
+
|
|
99
106
|
Object.assign(webex, {
|
|
100
107
|
logging: logger,
|
|
101
108
|
});
|
|
@@ -161,6 +168,7 @@ describe('plugin-meetings', () => {
|
|
|
161
168
|
],
|
|
162
169
|
})
|
|
163
170
|
),
|
|
171
|
+
_getCatalog: sinon.stub().returns(catalog),
|
|
164
172
|
fetchClientRegionInfo: sinon.stub().returns(Promise.resolve()),
|
|
165
173
|
},
|
|
166
174
|
metrics: {
|
|
@@ -1917,34 +1925,34 @@ describe('plugin-meetings', () => {
|
|
|
1917
1925
|
let loggerProxySpy;
|
|
1918
1926
|
|
|
1919
1927
|
it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
|
|
1928
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
1920
1929
|
assert.isDefined(webex.meetings.preferredWebexSite);
|
|
1921
1930
|
await webex.meetings.fetchUserPreferredWebexSite();
|
|
1922
1931
|
|
|
1923
1932
|
assert.equal(webex.meetings.preferredWebexSite, 'go.webex.com');
|
|
1933
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), [
|
|
1934
|
+
'go.webex.com',
|
|
1935
|
+
]);
|
|
1924
1936
|
});
|
|
1925
1937
|
|
|
1926
1938
|
const setup = ({user} = {}) => {
|
|
1927
1939
|
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
1940
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), []);
|
|
1928
1941
|
|
|
1929
1942
|
Object.assign(webex.internal, {
|
|
1930
|
-
services: {
|
|
1931
|
-
getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
|
|
1932
|
-
},
|
|
1933
1943
|
user: {
|
|
1934
1944
|
get: sinon.stub().returns(Promise.resolve(user)),
|
|
1935
1945
|
},
|
|
1936
1946
|
});
|
|
1947
|
+
|
|
1948
|
+
Object.assign(webex.internal.services, {
|
|
1949
|
+
getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
|
|
1950
|
+
});
|
|
1937
1951
|
};
|
|
1938
1952
|
|
|
1939
1953
|
it('should not fail if UserPreferred info is not fetched ', async () => {
|
|
1940
1954
|
setup();
|
|
1941
1955
|
|
|
1942
|
-
Object.assign(webex.internal, {
|
|
1943
|
-
services: {
|
|
1944
|
-
getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
|
|
1945
|
-
},
|
|
1946
|
-
});
|
|
1947
|
-
|
|
1948
1956
|
await webex.meetings.fetchUserPreferredWebexSite().then(() => {
|
|
1949
1957
|
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
1950
1958
|
});
|
|
@@ -1952,6 +1960,7 @@ describe('plugin-meetings', () => {
|
|
|
1952
1960
|
loggerProxySpy,
|
|
1953
1961
|
'Failed to fetch preferred site from user - no site will be set'
|
|
1954
1962
|
);
|
|
1963
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), ['']);
|
|
1955
1964
|
});
|
|
1956
1965
|
|
|
1957
1966
|
it('should fall back to fetching the site from the user', async () => {
|
|
@@ -1968,6 +1977,10 @@ describe('plugin-meetings', () => {
|
|
|
1968
1977
|
await webex.meetings.fetchUserPreferredWebexSite();
|
|
1969
1978
|
|
|
1970
1979
|
assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
|
|
1980
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), [
|
|
1981
|
+
'',
|
|
1982
|
+
'site.webex.com',
|
|
1983
|
+
]);
|
|
1971
1984
|
assert.notCalled(loggerProxySpy);
|
|
1972
1985
|
});
|
|
1973
1986
|
|
|
@@ -1989,6 +2002,7 @@ describe('plugin-meetings', () => {
|
|
|
1989
2002
|
loggerProxySpy,
|
|
1990
2003
|
'Failed to fetch preferred site from user - no site will be set'
|
|
1991
2004
|
);
|
|
2005
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), ['']);
|
|
1992
2006
|
});
|
|
1993
2007
|
}
|
|
1994
2008
|
);
|
|
@@ -2005,6 +2019,7 @@ describe('plugin-meetings', () => {
|
|
|
2005
2019
|
loggerProxySpy,
|
|
2006
2020
|
'Failed to fetch preferred site from user - no site will be set'
|
|
2007
2021
|
);
|
|
2022
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), ['']);
|
|
2008
2023
|
});
|
|
2009
2024
|
|
|
2010
2025
|
it('should fall back to fetching the site from the user', async () => {
|
|
@@ -2022,6 +2037,10 @@ describe('plugin-meetings', () => {
|
|
|
2022
2037
|
|
|
2023
2038
|
assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
|
|
2024
2039
|
assert.notCalled(loggerProxySpy);
|
|
2040
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), [
|
|
2041
|
+
'',
|
|
2042
|
+
'site.webex.com',
|
|
2043
|
+
]);
|
|
2025
2044
|
});
|
|
2026
2045
|
|
|
2027
2046
|
forEach(
|
|
@@ -2042,6 +2061,7 @@ describe('plugin-meetings', () => {
|
|
|
2042
2061
|
loggerProxySpy,
|
|
2043
2062
|
'Failed to fetch preferred site from user - no site will be set'
|
|
2044
2063
|
);
|
|
2064
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), ['']);
|
|
2045
2065
|
});
|
|
2046
2066
|
}
|
|
2047
2067
|
);
|
|
@@ -2058,6 +2078,7 @@ describe('plugin-meetings', () => {
|
|
|
2058
2078
|
loggerProxySpy,
|
|
2059
2079
|
'Failed to fetch preferred site from user - no site will be set'
|
|
2060
2080
|
);
|
|
2081
|
+
assert.deepEqual(webex.internal.services._getCatalog().getAllowedDomains(), ['']);
|
|
2061
2082
|
});
|
|
2062
2083
|
});
|
|
2063
2084
|
});
|
|
@@ -2344,12 +2365,14 @@ describe('plugin-meetings', () => {
|
|
|
2344
2365
|
sessionType: 'MAIN',
|
|
2345
2366
|
};
|
|
2346
2367
|
newLocus.self.state = 'JOINED';
|
|
2347
|
-
newLocus.self.devices = [
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2368
|
+
newLocus.self.devices = [
|
|
2369
|
+
{
|
|
2370
|
+
intent: {
|
|
2371
|
+
reason: 'ON_HOLD_LOBBY',
|
|
2372
|
+
type: 'WAIT',
|
|
2373
|
+
},
|
|
2374
|
+
},
|
|
2375
|
+
];
|
|
2353
2376
|
LoggerProxy.logger.log = sinon.stub();
|
|
2354
2377
|
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
2355
2378
|
assert.equal(result, true);
|
|
@@ -141,6 +141,272 @@ describe('isAnyPublicClusterReachable', () => {
|
|
|
141
141
|
});
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
|
|
145
|
+
describe('isWebexMediaBackendUnreachable', () => {
|
|
146
|
+
let webex;
|
|
147
|
+
|
|
148
|
+
beforeEach(() => {
|
|
149
|
+
webex = new MockWebex();
|
|
150
|
+
|
|
151
|
+
sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
afterEach(() => {
|
|
155
|
+
sinon.restore();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const runCheck = async (mockStorage: any, expectedValue: boolean) => {
|
|
159
|
+
if (mockStorage) {
|
|
160
|
+
await webex.boundedStorage.put(
|
|
161
|
+
'Reachability',
|
|
162
|
+
'reachability.result',
|
|
163
|
+
JSON.stringify(mockStorage)
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
const reachability = new Reachability(webex);
|
|
167
|
+
|
|
168
|
+
const result = await reachability.isWebexMediaBackendUnreachable();
|
|
169
|
+
|
|
170
|
+
assert.equal(result, expectedValue);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
[
|
|
174
|
+
{
|
|
175
|
+
title: 'no clusters at all',
|
|
176
|
+
mockStorage: {},
|
|
177
|
+
expectedResult: false,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
title: 'clusters without results',
|
|
181
|
+
mockStorage: {a: {}, b: {}},
|
|
182
|
+
expectedResult: false,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
title: 'all clusters untested',
|
|
186
|
+
mockStorage: {
|
|
187
|
+
a: {udp: 'untested'},
|
|
188
|
+
b: {udp: 'untested', tcp: 'untested'},
|
|
189
|
+
},
|
|
190
|
+
expectedResult: false,
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
title: 'one cluster with udp reachable',
|
|
194
|
+
mockStorage: {x: {udp: {result: 'reachable'}, tcp: {result: 'unreachable'}}},
|
|
195
|
+
expectedResult: false,
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
title: 'one cluster with tcp reachable',
|
|
199
|
+
mockStorage: {x: {tcp: {result: 'reachable'}}},
|
|
200
|
+
expectedResult: false,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
title: 'one cluster with xtls reachable',
|
|
204
|
+
mockStorage: {x: {xtls: {result: 'reachable'}}, y: {xtls: {result: 'unreachable'}}},
|
|
205
|
+
expectedResult: false,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
title: 'multiple clusters with various protocols reachable',
|
|
209
|
+
mockStorage: {
|
|
210
|
+
a: {udp: {result: 'reachable'}, tcp: {result: 'reachable'}},
|
|
211
|
+
b: {udp: {result: 'unreachable'}, tcp: {result: 'reachable'}},
|
|
212
|
+
c: {tcp: {result: 'reachable'}},
|
|
213
|
+
d: {xtls: {result: 'reachable'}},
|
|
214
|
+
},
|
|
215
|
+
expectedResult: false,
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
title: 'multiple clusters with all protocols unreachable',
|
|
219
|
+
mockStorage: {
|
|
220
|
+
a: {
|
|
221
|
+
udp: {result: 'unreachable'},
|
|
222
|
+
tcp: {result: 'unreachable'},
|
|
223
|
+
xtls: {result: 'unreachable'},
|
|
224
|
+
},
|
|
225
|
+
b: {
|
|
226
|
+
udp: {result: 'unreachable'},
|
|
227
|
+
tcp: {result: 'unreachable'},
|
|
228
|
+
xtls: {result: 'unreachable'},
|
|
229
|
+
},
|
|
230
|
+
c: {
|
|
231
|
+
udp: {result: 'unreachable'},
|
|
232
|
+
tcp: {result: 'unreachable'},
|
|
233
|
+
xtls: {result: 'unreachable'},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
expectedResult: true,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
title: 'multiple clusters with UDP and TCP protocols unreachable, but TLS not tested',
|
|
240
|
+
mockStorage: {
|
|
241
|
+
a: {
|
|
242
|
+
udp: {result: 'unreachable'},
|
|
243
|
+
tcp: {result: 'unreachable'},
|
|
244
|
+
xtls: {result: 'untested'},
|
|
245
|
+
},
|
|
246
|
+
b: {
|
|
247
|
+
udp: {result: 'unreachable'},
|
|
248
|
+
tcp: {result: 'unreachable'},
|
|
249
|
+
xtls: {result: 'untested'},
|
|
250
|
+
},
|
|
251
|
+
c: {
|
|
252
|
+
udp: {result: 'unreachable'},
|
|
253
|
+
tcp: {result: 'unreachable'},
|
|
254
|
+
xtls: {result: 'untested'},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
expectedResult: false,
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
title: 'multiple clusters with UDP and TCP protocols unreachable, but TLS missing',
|
|
261
|
+
mockStorage: {
|
|
262
|
+
a: {
|
|
263
|
+
udp: {result: 'unreachable'},
|
|
264
|
+
tcp: {result: 'unreachable'},
|
|
265
|
+
},
|
|
266
|
+
b: {
|
|
267
|
+
udp: {result: 'unreachable'},
|
|
268
|
+
tcp: {result: 'unreachable'},
|
|
269
|
+
},
|
|
270
|
+
c: {
|
|
271
|
+
udp: {result: 'unreachable'},
|
|
272
|
+
tcp: {result: 'unreachable'},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
expectedResult: false,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
title: 'multiple clusters with UDP and TLS protocols unreachable, but TCP not tested',
|
|
279
|
+
mockStorage: {
|
|
280
|
+
a: {
|
|
281
|
+
udp: {result: 'unreachable'},
|
|
282
|
+
tcp: {result: 'untested'},
|
|
283
|
+
xtls: {result: 'unreachable'},
|
|
284
|
+
},
|
|
285
|
+
b: {
|
|
286
|
+
udp: {result: 'unreachable'},
|
|
287
|
+
tcp: {result: 'untested'},
|
|
288
|
+
xtls: {result: 'unreachable'},
|
|
289
|
+
},
|
|
290
|
+
c: {
|
|
291
|
+
udp: {result: 'unreachable'},
|
|
292
|
+
tcp: {result: 'untested'},
|
|
293
|
+
xtls: {result: 'unreachable'},
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
expectedResult: false,
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
title: 'multiple clusters with UDP and TLS protocols unreachable, but TCP missing',
|
|
300
|
+
mockStorage: {
|
|
301
|
+
a: {
|
|
302
|
+
udp: {result: 'unreachable'},
|
|
303
|
+
xtls: {result: 'unreachable'},
|
|
304
|
+
},
|
|
305
|
+
b: {
|
|
306
|
+
udp: {result: 'unreachable'},
|
|
307
|
+
xtls: {result: 'unreachable'},
|
|
308
|
+
},
|
|
309
|
+
c: {
|
|
310
|
+
udp: {result: 'unreachable'},
|
|
311
|
+
xtls: {result: 'unreachable'},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
expectedResult: false,
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
title: 'multiple clusters with all protocols unreachable, some untested',
|
|
318
|
+
mockStorage: {
|
|
319
|
+
a: {
|
|
320
|
+
udp: {result: 'unreachable'},
|
|
321
|
+
tcp: {result: 'unreachable'},
|
|
322
|
+
xtls: {result: 'unreachable'},
|
|
323
|
+
},
|
|
324
|
+
b: {udp: {result: 'unreachable'}, tcp: {result: 'untested'}, xtls: {result: 'unreachable'}},
|
|
325
|
+
c: {udp: {result: 'unreachable'}, tcp: {result: 'unreachable'}, xtls: {result: 'untested'}},
|
|
326
|
+
},
|
|
327
|
+
expectedResult: true,
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
title: 'multiple clusters with all protocols unreachable, except for 1 reachable on udp',
|
|
331
|
+
mockStorage: {
|
|
332
|
+
a: {
|
|
333
|
+
udp: {result: 'reachable'},
|
|
334
|
+
tcp: {result: 'unreachable'},
|
|
335
|
+
xtls: {result: 'unreachable'},
|
|
336
|
+
},
|
|
337
|
+
b: {
|
|
338
|
+
udp: {result: 'unreachable'},
|
|
339
|
+
tcp: {result: 'unreachable'},
|
|
340
|
+
xtls: {result: 'unreachable'},
|
|
341
|
+
},
|
|
342
|
+
c: {
|
|
343
|
+
udp: {result: 'unreachable'},
|
|
344
|
+
tcp: {result: 'unreachable'},
|
|
345
|
+
xtls: {result: 'unreachable'},
|
|
346
|
+
},
|
|
347
|
+
},
|
|
348
|
+
expectedResult: false,
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
title: 'multiple clusters with all protocols unreachable, except for 1 reachable on tcp',
|
|
352
|
+
mockStorage: {
|
|
353
|
+
a: {
|
|
354
|
+
udp: {result: 'unreachable'},
|
|
355
|
+
tcp: {result: 'unreachable'},
|
|
356
|
+
xtls: {result: 'unreachable'},
|
|
357
|
+
},
|
|
358
|
+
b: {
|
|
359
|
+
udp: {result: 'unreachable'},
|
|
360
|
+
tcp: {result: 'unreachable'},
|
|
361
|
+
xtls: {result: 'unreachable'},
|
|
362
|
+
},
|
|
363
|
+
c: {
|
|
364
|
+
udp: {result: 'unreachable'},
|
|
365
|
+
tcp: {result: 'reachable'},
|
|
366
|
+
xtls: {result: 'unreachable'},
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
expectedResult: false,
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
title: 'multiple clusters with all protocols unreachable, except for 1 reachable on xtls',
|
|
373
|
+
mockStorage: {
|
|
374
|
+
a: {
|
|
375
|
+
udp: {result: 'unreachable'},
|
|
376
|
+
tcp: {result: 'unreachable'},
|
|
377
|
+
xtls: {result: 'unreachable'},
|
|
378
|
+
},
|
|
379
|
+
b: {
|
|
380
|
+
udp: {result: 'unreachable'},
|
|
381
|
+
tcp: {result: 'unreachable'},
|
|
382
|
+
xtls: {result: 'reachable'},
|
|
383
|
+
},
|
|
384
|
+
c: {
|
|
385
|
+
udp: {result: 'unreachable'},
|
|
386
|
+
tcp: {result: 'unreachable'},
|
|
387
|
+
xtls: {result: 'unreachable'},
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
expectedResult: false,
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
title: 'multiple clusters with some missing results',
|
|
394
|
+
mockStorage: {
|
|
395
|
+
a: {udp: {result: 'unreachable'}},
|
|
396
|
+
b: {tcp: {result: 'unreachable'}},
|
|
397
|
+
c: {xtls: {result: 'unreachable'}},
|
|
398
|
+
d: {},
|
|
399
|
+
},
|
|
400
|
+
expectedResult: true,
|
|
401
|
+
},
|
|
402
|
+
].forEach(({mockStorage, expectedResult, title}) => {
|
|
403
|
+
it(`returns ${expectedResult} when ${title}`, async () => {
|
|
404
|
+
await runCheck(mockStorage, expectedResult);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
|
|
144
410
|
describe('gatherReachability', () => {
|
|
145
411
|
let webex;
|
|
146
412
|
|