@webex/plugin-meetings 3.1.0-next.2 → 3.1.0-next.21
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/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
- package/dist/common/errors/reconnection-not-started.js.map +1 -0
- package/dist/constants.js +16 -5
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +7 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +10 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/properties.js +102 -57
- package/dist/media/properties.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +10 -10
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +6 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +543 -467
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +27 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/util.js +9 -16
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.js +37 -49
- package/dist/meeting/voicea-meeting.js.map +1 -1
- package/dist/meetings/index.js +12 -28
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +88 -9
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +138 -109
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/request.js +3 -27
- package/dist/roap/request.js.map +1 -1
- package/dist/statsAnalyzer/index.js +8 -2
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +17 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
- package/dist/types/constants.d.ts +13 -3
- package/dist/types/media/properties.d.ts +26 -2
- package/dist/types/mediaQualityMetrics/config.d.ts +8 -2
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +5 -6
- package/dist/types/meeting/locusMediaRequest.d.ts +1 -0
- package/dist/types/meeting/util.d.ts +3 -0
- package/dist/types/meeting/voicea-meeting.d.ts +3 -2
- package/dist/types/meetings/index.d.ts +1 -16
- package/dist/types/reachability/index.d.ts +11 -0
- package/dist/types/reconnection-manager/index.d.ts +4 -14
- package/dist/webinar/index.js +1 -1
- package/package.json +21 -21
- package/src/common/errors/reconnection-not-started.ts +25 -0
- package/src/constants.ts +14 -5
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +16 -0
- package/src/media/properties.ts +67 -15
- package/src/mediaQualityMetrics/config.ts +13 -7
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +121 -98
- package/src/meeting/locusMediaRequest.ts +31 -0
- package/src/meeting/util.ts +9 -16
- package/src/meeting/voicea-meeting.ts +44 -46
- package/src/meetings/index.ts +15 -27
- package/src/reachability/index.ts +60 -0
- package/src/reconnection-manager/index.ts +128 -105
- package/src/roap/request.ts +1 -24
- package/src/statsAnalyzer/index.ts +10 -3
- package/src/statsAnalyzer/mqaUtil.ts +23 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +21 -0
- package/test/unit/spec/media/properties.ts +145 -140
- package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
- package/test/unit/spec/meeting/index.js +243 -97
- package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
- package/test/unit/spec/meeting/utils.js +3 -10
- package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
- package/test/unit/spec/meetings/index.js +59 -17
- package/test/unit/spec/reachability/index.ts +266 -0
- package/test/unit/spec/reconnection-manager/index.js +127 -39
- package/test/unit/spec/roap/request.ts +0 -37
- package/test/unit/spec/stats-analyzer/index.js +100 -8
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
- package/src/common/errors/reconnection-in-progress.ts +0 -8
|
@@ -998,12 +998,13 @@ 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].
|
|
1006
|
-
|
|
1006
|
+
this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
|
|
1007
|
+
this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
|
|
1007
1008
|
}
|
|
1008
1009
|
}
|
|
1009
1010
|
|
|
@@ -1116,6 +1117,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1116
1117
|
|
|
1117
1118
|
this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp =
|
|
1118
1119
|
result.lastPacketReceivedTimestamp;
|
|
1120
|
+
this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
|
|
1121
|
+
this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
|
|
1119
1122
|
|
|
1120
1123
|
// From Thin
|
|
1121
1124
|
this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
|
|
@@ -1132,6 +1135,10 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1132
1135
|
this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;
|
|
1133
1136
|
this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;
|
|
1134
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;
|
|
1135
1142
|
|
|
1136
1143
|
this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);
|
|
1137
1144
|
|
|
@@ -216,6 +216,8 @@ export const getAudioSenderStreamMqa = ({
|
|
|
216
216
|
statsResults[mediaType][sendrecvType].totalKeyFramesEncoded - lastFramesEncoded || 0;
|
|
217
217
|
audioSenderStream.requestedKeyFrames =
|
|
218
218
|
statsResults[mediaType][sendrecvType].totalFirCount - lastFirCount || 0;
|
|
219
|
+
|
|
220
|
+
audioSenderStream.requestedBitrate = statsResults[mediaType][sendrecvType].requestedBitrate || 0;
|
|
219
221
|
};
|
|
220
222
|
|
|
221
223
|
export const getVideoReceiverMqa = ({
|
|
@@ -235,10 +237,16 @@ export const getVideoReceiverMqa = ({
|
|
|
235
237
|
const lastPacketsLost = getLastTotalValue('totalPacketsLost');
|
|
236
238
|
const lastBytesReceived = getLastTotalValue('totalBytesReceived');
|
|
237
239
|
|
|
240
|
+
const lastRtxPacketsReceived = getLastTotalValue('totalRtxPacketsReceived');
|
|
241
|
+
const lastRtxBytesReceived = getLastTotalValue('totalRtxBytesReceived');
|
|
242
|
+
|
|
238
243
|
const packetsLost = getTotalValue('totalPacketsLost');
|
|
239
244
|
const totalPacketsReceived = getTotalValue('totalPacketsReceived');
|
|
240
245
|
const totalBytesReceived = getTotalValue('totalBytesReceived');
|
|
241
246
|
|
|
247
|
+
const totalRtxPacketsReceived = getTotalValue('totalRtxPacketsReceived');
|
|
248
|
+
const totalRtxBytesReceived = getTotalValue('totalRtxBytesReceived');
|
|
249
|
+
|
|
242
250
|
const meanRemoteJitter = Object.keys(statsResults)
|
|
243
251
|
.filter((mt) => mt.includes(baseMediaType))
|
|
244
252
|
.reduce((acc, mt) => acc.concat(statsResults[mt][sendrecvType].meanRemoteJitter), []);
|
|
@@ -264,10 +272,15 @@ export const getVideoReceiverMqa = ({
|
|
|
264
272
|
|
|
265
273
|
// Calculate the outgoing bitrate
|
|
266
274
|
const totalBytesReceivedInaMin = totalBytesReceived - lastBytesReceived;
|
|
275
|
+
const totalRtxBytesReceivedInaMin = totalRtxBytesReceived - lastRtxBytesReceived;
|
|
267
276
|
|
|
268
277
|
videoReceiver.common.rtpBitrate = totalBytesReceivedInaMin
|
|
269
278
|
? (totalBytesReceivedInaMin * 8) / 60
|
|
270
279
|
: 0;
|
|
280
|
+
videoReceiver.common.rtxPackets = totalRtxPacketsReceived - lastRtxPacketsReceived;
|
|
281
|
+
videoReceiver.common.rtxBitrate = totalRtxBytesReceivedInaMin
|
|
282
|
+
? (totalRtxBytesReceivedInaMin * 8) / 60
|
|
283
|
+
: 0;
|
|
271
284
|
};
|
|
272
285
|
|
|
273
286
|
export const getVideoReceiverStreamMqa = ({
|
|
@@ -347,11 +360,15 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, b
|
|
|
347
360
|
const lastPacketsSent = getLastTotalValue('totalPacketsSent');
|
|
348
361
|
const lastBytesSent = getLastTotalValue('totalBytesSent');
|
|
349
362
|
const lastPacketsLostTotal = getLastTotalValue('totalPacketsLostOnReceiver');
|
|
363
|
+
const lastRtxPacketsSent = getLastTotalValue('totalRtxPacketsSent');
|
|
364
|
+
const lastRtxBytesSent = getLastTotalValue('totalRtxBytesSent');
|
|
350
365
|
|
|
351
366
|
const totalPacketsLostOnReceiver = getTotalValue('totalPacketsLostOnReceiver');
|
|
352
367
|
const totalPacketsSent = getTotalValue('totalPacketsSent');
|
|
353
368
|
const totalBytesSent = getTotalValue('totalBytesSent');
|
|
354
369
|
const availableOutgoingBitrate = getTotalValue('availableOutgoingBitrate');
|
|
370
|
+
const totalRtxPacketsSent = getTotalValue('totalRtxPacketsSent');
|
|
371
|
+
const totalRtxBytesSent = getTotalValue('totalRtxBytesSent');
|
|
355
372
|
|
|
356
373
|
videoSender.common.common.direction =
|
|
357
374
|
statsResults[Object.keys(statsResults).find((mediaType) => mediaType.includes(baseMediaType))]
|
|
@@ -387,8 +404,11 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, b
|
|
|
387
404
|
|
|
388
405
|
// Calculate the outgoing bitrate
|
|
389
406
|
const totalBytesSentInaMin = totalBytesSent - lastBytesSent;
|
|
407
|
+
const totalRtxBytesSentInaMin = totalRtxBytesSent - lastRtxBytesSent;
|
|
390
408
|
|
|
391
409
|
videoSender.common.rtpBitrate = totalBytesSentInaMin ? (totalBytesSentInaMin * 8) / 60 : 0;
|
|
410
|
+
videoSender.common.rtxPackets = totalRtxPacketsSent - lastRtxPacketsSent;
|
|
411
|
+
videoSender.common.rtxBitrate = totalRtxBytesSentInaMin ? (totalRtxBytesSentInaMin * 8) / 60 : 0;
|
|
392
412
|
};
|
|
393
413
|
|
|
394
414
|
export const getVideoSenderStreamMqa = ({
|
|
@@ -437,4 +457,7 @@ export const getVideoSenderStreamMqa = ({
|
|
|
437
457
|
videoSenderStream.transmittedWidth = statsResults[mediaType][sendrecvType].width || 0;
|
|
438
458
|
videoSenderStream.transmittedFrameSize =
|
|
439
459
|
(videoSenderStream.transmittedHeight * videoSenderStream.transmittedWidth) / 256;
|
|
460
|
+
videoSenderStream.requestedBitrate = statsResults[mediaType][sendrecvType].requestedBitrate || 0;
|
|
461
|
+
videoSenderStream.requestedFrameSize =
|
|
462
|
+
statsResults[mediaType][sendrecvType].requestedFrameSize || 0;
|
|
440
463
|
};
|
|
@@ -269,6 +269,26 @@ describe('plugin-meetings', () => {
|
|
|
269
269
|
assert.equal(updates.hasInterpretationChanged, false);
|
|
270
270
|
});
|
|
271
271
|
|
|
272
|
+
it('returns hasManualCaptionChanged = true when it has changed', () => {
|
|
273
|
+
const newControls = {
|
|
274
|
+
manualCaptionControl: {enabled: false},
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const {updates} = ControlsUtils.getControls({manualCaptionControl: {enabled: true}}, newControls);
|
|
278
|
+
|
|
279
|
+
assert.equal(updates.hasManualCaptionChanged, true);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('returns hasManualCaptionChanged = false when it has not changed', () => {
|
|
283
|
+
const newControls = {
|
|
284
|
+
manualCaptionControl: {enabled: true},
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const {updates} = ControlsUtils.getControls({manualCaptionControl: {enabled: true}}, newControls);
|
|
288
|
+
|
|
289
|
+
assert.equal(updates.hasManualCaptionChanged, false);
|
|
290
|
+
});
|
|
291
|
+
|
|
272
292
|
describe('videoEnabled', () => {
|
|
273
293
|
const testVideoEnabled = (oldControls, newControls, updatedProperty) => {
|
|
274
294
|
const result = ControlsUtils.getControls(oldControls, newControls);
|
|
@@ -467,6 +467,27 @@ describe('plugin-meetings', () => {
|
|
|
467
467
|
);
|
|
468
468
|
});
|
|
469
469
|
|
|
470
|
+
it('should update the manual caption state', () => {
|
|
471
|
+
locusInfo.emitScoped = sinon.stub();
|
|
472
|
+
locusInfo.controls = {
|
|
473
|
+
manualCaptionControl: {enabled: false},
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
locusInfo.updateControls({manualCaptionControl: { enabled: true, }});
|
|
477
|
+
|
|
478
|
+
assert.calledWith(
|
|
479
|
+
locusInfo.emitScoped,
|
|
480
|
+
{
|
|
481
|
+
file: 'locus-info',
|
|
482
|
+
function: 'updateControls',
|
|
483
|
+
},
|
|
484
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_MANUAL_CAPTION_UPDATED,
|
|
485
|
+
{
|
|
486
|
+
enabled: true,
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
});
|
|
490
|
+
|
|
470
491
|
it('should update the meetingContainerURL from null', () => {
|
|
471
492
|
locusInfo.controls = {
|
|
472
493
|
meetingContainer: {meetingContainerUrl: null},
|
|
@@ -54,189 +54,194 @@ describe('MediaProperties', () => {
|
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
describe('
|
|
58
|
-
it('
|
|
59
|
-
|
|
57
|
+
describe('getCurrentConnectionInfo', () => {
|
|
58
|
+
it('handles the case when getStats() fails', async () => {
|
|
59
|
+
mockMC.getStats.rejects(new Error());
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
const {connectionType, selectedCandidatePairChanges, numTransports} =
|
|
62
|
+
await mediaProperties.getCurrentConnectionInfo();
|
|
62
63
|
|
|
63
|
-
assert.
|
|
64
|
+
assert.equal(connectionType, 'unknown');
|
|
65
|
+
assert.equal(selectedCandidatePairChanges, -1);
|
|
66
|
+
assert.equal(numTransports, 0);
|
|
64
67
|
});
|
|
65
|
-
it('calls getStats() only after waitForMediaConnectionConnected resolves', async () => {
|
|
66
|
-
const waitForMediaConnectionConnectedResult = new Defer();
|
|
67
|
-
|
|
68
|
-
const waitForMediaConnectionConnectedStub = sinon
|
|
69
|
-
.stub(mediaProperties, 'waitForMediaConnectionConnected')
|
|
70
|
-
.returns(waitForMediaConnectionConnectedResult.promise);
|
|
71
|
-
|
|
72
|
-
const result = mediaProperties.getCurrentConnectionType();
|
|
73
68
|
|
|
74
|
-
|
|
69
|
+
describe('selectedCandidatePairChanges and numTransports', () => {
|
|
70
|
+
it('returns correct values when getStats() returns no transport stats at all', async () => {
|
|
71
|
+
mockMC.getStats.resolves([{type: 'something', id: '1234'}]);
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
const {selectedCandidatePairChanges, numTransports} =
|
|
74
|
+
await mediaProperties.getCurrentConnectionInfo();
|
|
78
75
|
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
assert.equal(selectedCandidatePairChanges, -1);
|
|
77
|
+
assert.equal(numTransports, 0);
|
|
78
|
+
});
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
85
|
-
it('rejects if waitForMediaConnectionConnected rejects', async () => {
|
|
86
|
-
const waitForMediaConnectionConnectedResult = new Defer();
|
|
80
|
+
it('returns correct values when getStats() returns transport stats without selectedCandidatePairChanges', async () => {
|
|
81
|
+
mockMC.getStats.resolves([{type: 'transport', id: '1234'}]);
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.returns(waitForMediaConnectionConnectedResult.promise);
|
|
83
|
+
const {selectedCandidatePairChanges, numTransports} =
|
|
84
|
+
await mediaProperties.getCurrentConnectionInfo();
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
assert.equal(selectedCandidatePairChanges, -1);
|
|
87
|
+
assert.equal(numTransports, 1);
|
|
88
|
+
});
|
|
93
89
|
|
|
94
|
-
|
|
90
|
+
it('returns correct values when getStats() returns transport stats with selectedCandidatePairChanges', async () => {
|
|
91
|
+
mockMC.getStats.resolves([
|
|
92
|
+
{type: 'transport', id: '1234', selectedCandidatePairChanges: 13},
|
|
93
|
+
]);
|
|
95
94
|
|
|
96
|
-
|
|
95
|
+
const {selectedCandidatePairChanges, numTransports} =
|
|
96
|
+
await mediaProperties.getCurrentConnectionInfo();
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
assert.equal(selectedCandidatePairChanges, 13);
|
|
99
|
+
assert.equal(numTransports, 1);
|
|
100
|
+
});
|
|
100
101
|
|
|
101
|
-
|
|
102
|
+
it('returns correct values when getStats() returns multiple transport stats', async () => {
|
|
103
|
+
mockMC.getStats.resolves([
|
|
104
|
+
{type: 'transport', id: '1', selectedCandidatePairChanges: 11},
|
|
105
|
+
{type: 'transport', id: '2', selectedCandidatePairChanges: 12},
|
|
106
|
+
]);
|
|
102
107
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
it('returns "unknown" if getStats() fails', async () => {
|
|
106
|
-
mockMC.getStats.rejects(new Error());
|
|
108
|
+
const {selectedCandidatePairChanges, numTransports} =
|
|
109
|
+
await mediaProperties.getCurrentConnectionInfo();
|
|
107
110
|
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
assert.equal(selectedCandidatePairChanges, 11); // we expect stats from the first transport to be returned
|
|
112
|
+
assert.equal(numTransports, 2);
|
|
113
|
+
});
|
|
110
114
|
});
|
|
115
|
+
describe('connectionType', () => {
|
|
116
|
+
it('returns "unknown" if getStats() returns no candidate pairs', async () => {
|
|
117
|
+
mockMC.getStats.resolves([{type: 'something', id: '1234'}]);
|
|
111
118
|
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
120
|
+
assert.equal(connectionType, 'unknown');
|
|
121
|
+
});
|
|
114
122
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
123
|
+
it('returns "unknown" if getStats() returns no successful candidate pair', async () => {
|
|
124
|
+
mockMC.getStats.resolves([{type: 'candidate-pair', id: '1234', state: 'inprogress'}]);
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
127
|
+
assert.equal(connectionType, 'unknown');
|
|
128
|
+
});
|
|
121
129
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
it('returns "unknown" if getStats() returns a successful candidate pair but local candidate is missing', async () => {
|
|
131
|
+
mockMC.getStats.resolves([
|
|
132
|
+
{type: 'candidate-pair', id: '1234', state: 'succeeded', localCandidateId: 'wrong id'},
|
|
133
|
+
]);
|
|
125
134
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
]);
|
|
135
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
136
|
+
assert.equal(connectionType, 'unknown');
|
|
137
|
+
});
|
|
130
138
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
it('returns "UDP" if getStats() returns a successful candidate pair with udp local candidate', async () => {
|
|
140
|
+
mockMC.getStats.resolves([
|
|
141
|
+
{
|
|
142
|
+
type: 'candidate-pair',
|
|
143
|
+
id: 'some candidate pair id',
|
|
144
|
+
state: 'succeeded',
|
|
145
|
+
localCandidateId: 'local candidate id',
|
|
146
|
+
},
|
|
147
|
+
{type: 'local-candidate', id: 'some other candidate id', protocol: 'tcp'},
|
|
148
|
+
{type: 'local-candidate', id: 'local candidate id', protocol: 'udp'},
|
|
149
|
+
]);
|
|
134
150
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
type: 'candidate-pair',
|
|
139
|
-
id: 'some candidate pair id',
|
|
140
|
-
state: 'succeeded',
|
|
141
|
-
localCandidateId: 'local candidate id',
|
|
142
|
-
},
|
|
143
|
-
{type: 'local-candidate', id: 'some other candidate id', protocol: 'tcp'},
|
|
144
|
-
{type: 'local-candidate', id: 'local candidate id', protocol: 'udp'},
|
|
145
|
-
]);
|
|
146
|
-
|
|
147
|
-
const connectionType = await mediaProperties.getCurrentConnectionType();
|
|
148
|
-
assert.equal(connectionType, 'UDP');
|
|
149
|
-
});
|
|
151
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
152
|
+
assert.equal(connectionType, 'UDP');
|
|
153
|
+
});
|
|
150
154
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const connectionType = await mediaProperties.getCurrentConnectionType();
|
|
164
|
-
assert.equal(connectionType, 'TCP');
|
|
165
|
-
});
|
|
155
|
+
it('returns "TCP" if getStats() returns a successful candidate pair with tcp local candidate', async () => {
|
|
156
|
+
mockMC.getStats.resolves([
|
|
157
|
+
{
|
|
158
|
+
type: 'candidate-pair',
|
|
159
|
+
id: 'some candidate pair id',
|
|
160
|
+
state: 'succeeded',
|
|
161
|
+
localCandidateId: 'some candidate id',
|
|
162
|
+
},
|
|
163
|
+
{type: 'local-candidate', id: 'some other candidate id', protocol: 'udp'},
|
|
164
|
+
{type: 'local-candidate', id: 'some candidate id', protocol: 'tcp'},
|
|
165
|
+
]);
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
168
|
+
assert.equal(connectionType, 'TCP');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
[
|
|
172
|
+
{relayProtocol: 'tls', expectedConnectionType: 'TURN-TLS'},
|
|
173
|
+
{relayProtocol: 'tcp', expectedConnectionType: 'TURN-TCP'},
|
|
174
|
+
{relayProtocol: 'udp', expectedConnectionType: 'TURN-UDP'},
|
|
175
|
+
].forEach(({relayProtocol, expectedConnectionType}) =>
|
|
176
|
+
it(`returns "${expectedConnectionType}" if getStats() returns a successful candidate pair with a local candidate with relayProtocol=${relayProtocol}`, async () => {
|
|
177
|
+
mockMC.getStats.resolves([
|
|
178
|
+
{
|
|
179
|
+
type: 'candidate-pair',
|
|
180
|
+
id: 'some candidate pair id',
|
|
181
|
+
state: 'succeeded',
|
|
182
|
+
localCandidateId: 'selected candidate id',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'candidate-pair',
|
|
186
|
+
id: 'some other candidate pair id',
|
|
187
|
+
state: 'failed',
|
|
188
|
+
localCandidateId: 'some other candidate id 1',
|
|
189
|
+
},
|
|
190
|
+
{type: 'local-candidate', id: 'some other candidate id 1', protocol: 'udp'},
|
|
191
|
+
{type: 'local-candidate', id: 'some other candidate id 2', protocol: 'tcp'},
|
|
192
|
+
{
|
|
193
|
+
type: 'local-candidate',
|
|
194
|
+
id: 'selected candidate id',
|
|
195
|
+
protocol: 'udp',
|
|
196
|
+
relayProtocol,
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
201
|
+
assert.equal(connectionType, expectedConnectionType);
|
|
202
|
+
})
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
it('returns connection type of the first successful candidate pair', async () => {
|
|
206
|
+
// in real life this will never happen and all active candidate pairs will have same transport,
|
|
207
|
+
// but here we're simulating a situation where they have different transports and just checking
|
|
208
|
+
// that the code still works and just returns the first one
|
|
173
209
|
mockMC.getStats.resolves([
|
|
210
|
+
{
|
|
211
|
+
type: 'inbound-rtp',
|
|
212
|
+
id: 'whatever',
|
|
213
|
+
},
|
|
174
214
|
{
|
|
175
215
|
type: 'candidate-pair',
|
|
176
216
|
id: 'some candidate pair id',
|
|
177
217
|
state: 'succeeded',
|
|
178
|
-
localCandidateId: 'selected candidate id',
|
|
218
|
+
localCandidateId: '1st selected candidate id',
|
|
179
219
|
},
|
|
180
220
|
{
|
|
181
221
|
type: 'candidate-pair',
|
|
182
222
|
id: 'some other candidate pair id',
|
|
183
|
-
state: '
|
|
184
|
-
localCandidateId: '
|
|
223
|
+
state: 'succeeded',
|
|
224
|
+
localCandidateId: '2nd selected candidate id',
|
|
185
225
|
},
|
|
186
226
|
{type: 'local-candidate', id: 'some other candidate id 1', protocol: 'udp'},
|
|
187
227
|
{type: 'local-candidate', id: 'some other candidate id 2', protocol: 'tcp'},
|
|
188
228
|
{
|
|
189
229
|
type: 'local-candidate',
|
|
190
|
-
id: 'selected candidate id',
|
|
230
|
+
id: '1st selected candidate id',
|
|
231
|
+
protocol: 'udp',
|
|
232
|
+
relayProtocol: 'tls',
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
type: 'local-candidate',
|
|
236
|
+
id: '2nd selected candidate id',
|
|
191
237
|
protocol: 'udp',
|
|
192
|
-
relayProtocol,
|
|
238
|
+
relayProtocol: 'tcp',
|
|
193
239
|
},
|
|
194
240
|
]);
|
|
195
241
|
|
|
196
|
-
const connectionType = await mediaProperties.
|
|
197
|
-
assert.equal(connectionType,
|
|
198
|
-
})
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
it('returns connection type of the first successful candidate pair', async () => {
|
|
202
|
-
// in real life this will never happen and all active candidate pairs will have same transport,
|
|
203
|
-
// but here we're simulating a situation where they have different transports and just checking
|
|
204
|
-
// that the code still works and just returns the first one
|
|
205
|
-
mockMC.getStats.resolves([
|
|
206
|
-
{
|
|
207
|
-
type: 'inbound-rtp',
|
|
208
|
-
id: 'whatever',
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
type: 'candidate-pair',
|
|
212
|
-
id: 'some candidate pair id',
|
|
213
|
-
state: 'succeeded',
|
|
214
|
-
localCandidateId: '1st selected candidate id',
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
type: 'candidate-pair',
|
|
218
|
-
id: 'some other candidate pair id',
|
|
219
|
-
state: 'succeeded',
|
|
220
|
-
localCandidateId: '2nd selected candidate id',
|
|
221
|
-
},
|
|
222
|
-
{type: 'local-candidate', id: 'some other candidate id 1', protocol: 'udp'},
|
|
223
|
-
{type: 'local-candidate', id: 'some other candidate id 2', protocol: 'tcp'},
|
|
224
|
-
{
|
|
225
|
-
type: 'local-candidate',
|
|
226
|
-
id: '1st selected candidate id',
|
|
227
|
-
protocol: 'udp',
|
|
228
|
-
relayProtocol: 'tls',
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
type: 'local-candidate',
|
|
232
|
-
id: '2nd selected candidate id',
|
|
233
|
-
protocol: 'udp',
|
|
234
|
-
relayProtocol: 'tcp',
|
|
235
|
-
},
|
|
236
|
-
]);
|
|
237
|
-
|
|
238
|
-
const connectionType = await mediaProperties.getCurrentConnectionType();
|
|
239
|
-
assert.equal(connectionType, 'TURN-TLS');
|
|
242
|
+
const {connectionType} = await mediaProperties.getCurrentConnectionInfo();
|
|
243
|
+
assert.equal(connectionType, 'TURN-TLS');
|
|
244
|
+
});
|
|
240
245
|
});
|
|
241
246
|
});
|
|
242
247
|
});
|
|
@@ -30,6 +30,9 @@ describe('plugin-meetings', () => {
|
|
|
30
30
|
canStartTranscribing: null,
|
|
31
31
|
canStopTranscribing: null,
|
|
32
32
|
isClosedCaptionActive: null,
|
|
33
|
+
canStartManualCaption: null,
|
|
34
|
+
canStopManualCaption: null,
|
|
35
|
+
isManualCaptionActive: null,
|
|
33
36
|
isSaveTranscriptsEnabled: null,
|
|
34
37
|
isWebexAssistantActive: null,
|
|
35
38
|
canViewCaptionPanel: null,
|
|
@@ -110,6 +113,9 @@ describe('plugin-meetings', () => {
|
|
|
110
113
|
'canEnableClosedCaption',
|
|
111
114
|
'canStopTranscribing',
|
|
112
115
|
'isClosedCaptionActive',
|
|
116
|
+
'canStartManualCaption',
|
|
117
|
+
'canStopManualCaption',
|
|
118
|
+
'isManualCaptionActive',
|
|
113
119
|
'isSaveTranscriptsEnabled',
|
|
114
120
|
'isWebexAssistantActive',
|
|
115
121
|
'canViewCaptionPanel',
|