@webex/plugin-meetings 3.8.0-next.55 → 3.8.0-next.57
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 +5 -1
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +75 -35
- package/dist/meeting/index.js.map +1 -1
- package/dist/meetings/index.js +22 -0
- package/dist/meetings/index.js.map +1 -1
- package/dist/types/meeting/index.d.ts +6 -0
- package/dist/types/meetings/index.d.ts +9 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +5 -5
- package/src/media/index.ts +6 -0
- package/src/meeting/index.ts +49 -15
- package/src/meetings/index.ts +20 -0
- package/test/unit/spec/media/index.ts +30 -0
- package/test/unit/spec/meeting/index.js +124 -10
- package/test/unit/spec/meetings/index.js +15 -2
@@ -1976,5 +1976,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1976
1976
|
* @returns {Promise<void>}
|
1977
1977
|
*/
|
1978
1978
|
checkAndRefreshPermissionToken(threshold: number, reason: string): Promise<void>;
|
1979
|
+
/**
|
1980
|
+
* Gets the media reachability metrics
|
1981
|
+
*
|
1982
|
+
* @returns {Promise<MediaReachabilityMetrics>}
|
1983
|
+
*/
|
1984
|
+
private getMediaReachabilityMetricFields;
|
1979
1985
|
}
|
1980
1986
|
export {};
|
@@ -227,6 +227,15 @@ export default class Meetings extends WebexPlugin {
|
|
227
227
|
* @returns {undefined}
|
228
228
|
*/
|
229
229
|
private _toggleIpv6BackendNativeSupport;
|
230
|
+
/**
|
231
|
+
* API to toggle usage of audio main DTX, needs to be called before webex.meetings.register()
|
232
|
+
*
|
233
|
+
* @param {Boolean} newValue
|
234
|
+
* @private
|
235
|
+
* @memberof Meetings
|
236
|
+
* @returns {undefined}
|
237
|
+
*/
|
238
|
+
private _toggleDisableAudioMainDtx;
|
230
239
|
/**
|
231
240
|
* Executes a registration step and updates the registration status.
|
232
241
|
* @param {Function} step - The registration step to execute.
|
package/dist/webinar/index.js
CHANGED
package/package.json
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
"@webex/eslint-config-legacy": "0.0.0",
|
44
44
|
"@webex/jest-config-legacy": "0.0.0",
|
45
45
|
"@webex/legacy-tools": "0.0.0",
|
46
|
-
"@webex/plugin-meetings": "3.8.0-next.
|
46
|
+
"@webex/plugin-meetings": "3.8.0-next.57",
|
47
47
|
"@webex/plugin-rooms": "3.8.0-next.21",
|
48
48
|
"@webex/test-helper-chai": "3.8.0-next.17",
|
49
49
|
"@webex/test-helper-mocha": "3.8.0-next.17",
|
@@ -63,7 +63,7 @@
|
|
63
63
|
"dependencies": {
|
64
64
|
"@webex/common": "3.8.0-next.17",
|
65
65
|
"@webex/event-dictionary-ts": "^1.0.1753",
|
66
|
-
"@webex/internal-media-core": "2.
|
66
|
+
"@webex/internal-media-core": "2.15.0",
|
67
67
|
"@webex/internal-plugin-conversation": "3.8.0-next.21",
|
68
68
|
"@webex/internal-plugin-device": "3.8.0-next.17",
|
69
69
|
"@webex/internal-plugin-llm": "3.8.0-next.20",
|
@@ -71,8 +71,8 @@
|
|
71
71
|
"@webex/internal-plugin-metrics": "3.8.0-next.17",
|
72
72
|
"@webex/internal-plugin-support": "3.8.0-next.21",
|
73
73
|
"@webex/internal-plugin-user": "3.8.0-next.17",
|
74
|
-
"@webex/internal-plugin-voicea": "3.8.0-next.
|
75
|
-
"@webex/media-helpers": "3.8.0-next.
|
74
|
+
"@webex/internal-plugin-voicea": "3.8.0-next.57",
|
75
|
+
"@webex/media-helpers": "3.8.0-next.20",
|
76
76
|
"@webex/plugin-people": "3.8.0-next.19",
|
77
77
|
"@webex/plugin-rooms": "3.8.0-next.21",
|
78
78
|
"@webex/web-capabilities": "^1.4.0",
|
@@ -92,5 +92,5 @@
|
|
92
92
|
"//": [
|
93
93
|
"TODO: upgrade jwt-decode when moving to node 18"
|
94
94
|
],
|
95
|
-
"version": "3.8.0-next.
|
95
|
+
"version": "3.8.0-next.57"
|
96
96
|
}
|
package/src/media/index.ts
CHANGED
@@ -142,6 +142,7 @@ Media.createMediaConnection = (
|
|
142
142
|
turnServerInfo?: TurnServerInfo;
|
143
143
|
bundlePolicy?: BundlePolicy;
|
144
144
|
iceCandidatesTimeout?: number;
|
145
|
+
disableAudioMainDtx?: boolean;
|
145
146
|
}
|
146
147
|
) => {
|
147
148
|
const {
|
@@ -153,6 +154,7 @@ Media.createMediaConnection = (
|
|
153
154
|
turnServerInfo,
|
154
155
|
bundlePolicy,
|
155
156
|
iceCandidatesTimeout,
|
157
|
+
disableAudioMainDtx,
|
156
158
|
} = options;
|
157
159
|
|
158
160
|
const iceServers = [];
|
@@ -176,6 +178,10 @@ Media.createMediaConnection = (
|
|
176
178
|
config.bundlePolicy = bundlePolicy;
|
177
179
|
}
|
178
180
|
|
181
|
+
if (disableAudioMainDtx !== undefined) {
|
182
|
+
config.disableAudioMainDtx = disableAudioMainDtx;
|
183
|
+
}
|
184
|
+
|
179
185
|
return new MultistreamRoapMediaConnection(
|
180
186
|
config,
|
181
187
|
meetingId,
|
package/src/meeting/index.ts
CHANGED
@@ -164,6 +164,7 @@ import Member from '../member';
|
|
164
164
|
import {BrbState, createBrbState} from './brbState';
|
165
165
|
import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
|
166
166
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
167
|
+
import {ReachabilityMetrics} from '../reachability/reachability.types';
|
167
168
|
|
168
169
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
169
170
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
@@ -262,6 +263,8 @@ type FetchMeetingInfoParams = {
|
|
262
263
|
sendCAevents?: boolean;
|
263
264
|
};
|
264
265
|
|
266
|
+
type MediaReachabilityMetrics = ReachabilityMetrics & {isSubnetReachable: boolean};
|
267
|
+
|
265
268
|
/**
|
266
269
|
* MediaDirection
|
267
270
|
* @typedef {Object} MediaDirection
|
@@ -7009,6 +7012,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7009
7012
|
bundlePolicy,
|
7010
7013
|
// @ts-ignore - config coming from registerPlugin
|
7011
7014
|
iceCandidatesTimeout: this.config.iceCandidatesGatheringTimeout,
|
7015
|
+
// @ts-ignore - config coming from registerPlugin
|
7016
|
+
disableAudioMainDtx: this.config.experimental.disableAudioMainDtx,
|
7012
7017
|
}
|
7013
7018
|
);
|
7014
7019
|
|
@@ -7769,14 +7774,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7769
7774
|
|
7770
7775
|
const {connectionType, selectedCandidatePairChanges, numTransports} =
|
7771
7776
|
await this.mediaProperties.getCurrentConnectionInfo();
|
7772
|
-
|
7773
|
-
const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
|
7777
|
+
|
7774
7778
|
const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
|
7775
7779
|
|
7776
|
-
|
7777
|
-
const isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(
|
7778
|
-
this.mediaServerIp
|
7779
|
-
);
|
7780
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7780
7781
|
|
7781
7782
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
7782
7783
|
correlation_id: this.correlationId,
|
@@ -7787,8 +7788,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7787
7788
|
isMultistream: this.isMultistream,
|
7788
7789
|
retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
|
7789
7790
|
isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
|
7790
|
-
|
7791
|
-
...reachabilityStats,
|
7791
|
+
...reachabilityMetrics,
|
7792
7792
|
...iceCandidateErrors,
|
7793
7793
|
iceCandidatesCount: this.iceCandidatesCount,
|
7794
7794
|
});
|
@@ -7810,18 +7810,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7810
7810
|
LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
|
7811
7811
|
|
7812
7812
|
// @ts-ignore
|
7813
|
-
const reachabilityMetrics = await this.
|
7813
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7814
7814
|
|
7815
7815
|
const {selectedCandidatePairChanges, numTransports} =
|
7816
7816
|
await this.mediaProperties.getCurrentConnectionInfo();
|
7817
7817
|
|
7818
7818
|
const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
|
7819
7819
|
|
7820
|
-
// @ts-ignore
|
7821
|
-
const isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(
|
7822
|
-
this.mediaServerIp
|
7823
|
-
);
|
7824
|
-
|
7825
7820
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
7826
7821
|
correlation_id: this.correlationId,
|
7827
7822
|
locus_id: this.locusUrl.split('/').pop(),
|
@@ -7851,7 +7846,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7851
7846
|
this.mediaProperties.webrtcMediaConnection?.mediaConnection?.pc?.iceConnectionState ||
|
7852
7847
|
'unknown',
|
7853
7848
|
...reachabilityMetrics,
|
7854
|
-
isSubnetReachable,
|
7855
7849
|
...iceCandidateErrors,
|
7856
7850
|
iceCandidatesCount: this.iceCandidatesCount,
|
7857
7851
|
});
|
@@ -9622,4 +9616,44 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9622
9616
|
|
9623
9617
|
return Promise.resolve();
|
9624
9618
|
}
|
9619
|
+
|
9620
|
+
/**
|
9621
|
+
* Gets the media reachability metrics
|
9622
|
+
*
|
9623
|
+
* @returns {Promise<MediaReachabilityMetrics>}
|
9624
|
+
*/
|
9625
|
+
private async getMediaReachabilityMetricFields(): Promise<MediaReachabilityMetrics> {
|
9626
|
+
const reachabilityMetrics: ReachabilityMetrics =
|
9627
|
+
// @ts-ignore
|
9628
|
+
await this.webex.meetings.reachability.getReachabilityMetrics();
|
9629
|
+
|
9630
|
+
const successKeys: Array<keyof ReachabilityMetrics> = [
|
9631
|
+
'reachability_public_udp_success',
|
9632
|
+
'reachability_public_tcp_success',
|
9633
|
+
'reachability_public_xtls_success',
|
9634
|
+
'reachability_vmn_udp_success',
|
9635
|
+
'reachability_vmn_tcp_success',
|
9636
|
+
'reachability_vmn_xtls_success',
|
9637
|
+
];
|
9638
|
+
|
9639
|
+
const totalSuccessCases = successKeys.reduce((total, key) => {
|
9640
|
+
const value = reachabilityMetrics[key];
|
9641
|
+
if (typeof value === 'number') {
|
9642
|
+
return total + value;
|
9643
|
+
}
|
9644
|
+
|
9645
|
+
return total;
|
9646
|
+
}, 0);
|
9647
|
+
|
9648
|
+
let isSubnetReachable = null;
|
9649
|
+
if (totalSuccessCases > 0) {
|
9650
|
+
// @ts-ignore
|
9651
|
+
isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
|
9652
|
+
}
|
9653
|
+
|
9654
|
+
return {
|
9655
|
+
...reachabilityMetrics,
|
9656
|
+
isSubnetReachable,
|
9657
|
+
};
|
9658
|
+
}
|
9625
9659
|
}
|
package/src/meetings/index.ts
CHANGED
@@ -807,6 +807,26 @@ export default class Meetings extends WebexPlugin {
|
|
807
807
|
}
|
808
808
|
}
|
809
809
|
|
810
|
+
/**
|
811
|
+
* API to toggle usage of audio main DTX, needs to be called before webex.meetings.register()
|
812
|
+
*
|
813
|
+
* @param {Boolean} newValue
|
814
|
+
* @private
|
815
|
+
* @memberof Meetings
|
816
|
+
* @returns {undefined}
|
817
|
+
*/
|
818
|
+
private _toggleDisableAudioMainDtx(newValue: boolean) {
|
819
|
+
if (typeof newValue !== 'boolean') {
|
820
|
+
return;
|
821
|
+
}
|
822
|
+
|
823
|
+
// @ts-ignore
|
824
|
+
if (this.config.experimental.disableAudioMainDtx !== newValue) {
|
825
|
+
// @ts-ignore
|
826
|
+
this.config.experimental.disableAudioMainDtx = newValue;
|
827
|
+
}
|
828
|
+
}
|
829
|
+
|
810
830
|
/**
|
811
831
|
* Executes a registration step and updates the registration status.
|
812
832
|
* @param {Function} step - The registration step to execute.
|
@@ -159,6 +159,7 @@ describe('createMediaConnection', () => {
|
|
159
159
|
password: 'turn password',
|
160
160
|
},
|
161
161
|
bundlePolicy: 'max-bundle',
|
162
|
+
disableAudioMainDtx: false,
|
162
163
|
});
|
163
164
|
assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
|
164
165
|
assert.calledWith(
|
@@ -172,6 +173,7 @@ describe('createMediaConnection', () => {
|
|
172
173
|
},
|
173
174
|
],
|
174
175
|
bundlePolicy: 'max-bundle',
|
176
|
+
disableAudioMainDtx: false,
|
175
177
|
},
|
176
178
|
'meeting id'
|
177
179
|
);
|
@@ -262,6 +264,34 @@ describe('createMediaConnection', () => {
|
|
262
264
|
);
|
263
265
|
});
|
264
266
|
|
267
|
+
it('does not pass disableAudioMainDtx to MultistreamRoapMediaConnection if disableAudioMainDtx is undefined', () => {
|
268
|
+
const multistreamRoapMediaConnectionConstructorStub = sinon
|
269
|
+
.stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
|
270
|
+
.returns(fakeRoapMediaConnection);
|
271
|
+
|
272
|
+
Media.createMediaConnection(true, 'debug string', 'meeting id', {
|
273
|
+
mediaProperties: {
|
274
|
+
mediaDirection: {
|
275
|
+
sendAudio: true,
|
276
|
+
sendVideo: true,
|
277
|
+
sendShare: false,
|
278
|
+
receiveAudio: true,
|
279
|
+
receiveVideo: true,
|
280
|
+
receiveShare: true,
|
281
|
+
},
|
282
|
+
},
|
283
|
+
disableAudioMainDtx: undefined,
|
284
|
+
});
|
285
|
+
assert.calledOnce(multistreamRoapMediaConnectionConstructorStub);
|
286
|
+
assert.calledWith(
|
287
|
+
multistreamRoapMediaConnectionConstructorStub,
|
288
|
+
{
|
289
|
+
iceServers: [],
|
290
|
+
},
|
291
|
+
'meeting id'
|
292
|
+
);
|
293
|
+
});
|
294
|
+
|
265
295
|
[
|
266
296
|
{testCase: 'turnServerInfo is undefined', turnServerInfo: undefined},
|
267
297
|
{
|
@@ -2166,7 +2166,7 @@ describe('plugin-meetings', () => {
|
|
2166
2166
|
someReachabilityMetric1: 'some value1',
|
2167
2167
|
someReachabilityMetric2: 'some value2',
|
2168
2168
|
selectedCandidatePairChanges: 2,
|
2169
|
-
isSubnetReachable:
|
2169
|
+
isSubnetReachable: null,
|
2170
2170
|
numTransports: 1,
|
2171
2171
|
iceCandidatesCount: 0,
|
2172
2172
|
}
|
@@ -2213,7 +2213,7 @@ describe('plugin-meetings', () => {
|
|
2213
2213
|
signalingState: 'unknown',
|
2214
2214
|
connectionState: 'unknown',
|
2215
2215
|
iceConnectionState: 'unknown',
|
2216
|
-
isSubnetReachable:
|
2216
|
+
isSubnetReachable: null,
|
2217
2217
|
})
|
2218
2218
|
);
|
2219
2219
|
|
@@ -2279,7 +2279,7 @@ describe('plugin-meetings', () => {
|
|
2279
2279
|
selectedCandidatePairChanges: 2,
|
2280
2280
|
numTransports: 1,
|
2281
2281
|
iceCandidatesCount: 0,
|
2282
|
-
isSubnetReachable:
|
2282
|
+
isSubnetReachable: null,
|
2283
2283
|
}
|
2284
2284
|
);
|
2285
2285
|
});
|
@@ -2337,7 +2337,7 @@ describe('plugin-meetings', () => {
|
|
2337
2337
|
signalingState: 'have-local-offer',
|
2338
2338
|
connectionState: 'connecting',
|
2339
2339
|
iceConnectionState: 'checking',
|
2340
|
-
isSubnetReachable:
|
2340
|
+
isSubnetReachable: null,
|
2341
2341
|
})
|
2342
2342
|
);
|
2343
2343
|
|
@@ -2395,7 +2395,7 @@ describe('plugin-meetings', () => {
|
|
2395
2395
|
signalingState: 'have-local-offer',
|
2396
2396
|
connectionState: 'connecting',
|
2397
2397
|
iceConnectionState: 'checking',
|
2398
|
-
isSubnetReachable:
|
2398
|
+
isSubnetReachable: null,
|
2399
2399
|
})
|
2400
2400
|
);
|
2401
2401
|
|
@@ -2731,7 +2731,7 @@ describe('plugin-meetings', () => {
|
|
2731
2731
|
sinon.stub().returns(FAKE_ERROR));
|
2732
2732
|
webex.meetings.reachability = {
|
2733
2733
|
isWebexMediaBackendUnreachable: sinon.stub().resolves(false),
|
2734
|
-
getReachabilityMetrics: sinon.stub().resolves(),
|
2734
|
+
getReachabilityMetrics: sinon.stub().resolves({}),
|
2735
2735
|
stopReachability: sinon.stub(),
|
2736
2736
|
isSubnetReachable: sinon.stub().returns(true),
|
2737
2737
|
};
|
@@ -2917,7 +2917,7 @@ describe('plugin-meetings', () => {
|
|
2917
2917
|
selectedCandidatePairChanges: 2,
|
2918
2918
|
numTransports: 1,
|
2919
2919
|
iceCandidatesCount: 0,
|
2920
|
-
isSubnetReachable:
|
2920
|
+
isSubnetReachable: null,
|
2921
2921
|
},
|
2922
2922
|
]);
|
2923
2923
|
|
@@ -3120,7 +3120,7 @@ describe('plugin-meetings', () => {
|
|
3120
3120
|
retriedWithTurnServer: true,
|
3121
3121
|
isJoinWithMediaRetry: false,
|
3122
3122
|
iceCandidatesCount: 0,
|
3123
|
-
isSubnetReachable:
|
3123
|
+
isSubnetReachable: null,
|
3124
3124
|
},
|
3125
3125
|
]);
|
3126
3126
|
meeting.roap.doTurnDiscovery;
|
@@ -3277,7 +3277,7 @@ describe('plugin-meetings', () => {
|
|
3277
3277
|
iceCandidatesCount: 3,
|
3278
3278
|
'701_error': 3,
|
3279
3279
|
'701_turn_host_lookup_received_error': 1,
|
3280
|
-
isSubnetReachable:
|
3280
|
+
isSubnetReachable: null,
|
3281
3281
|
}
|
3282
3282
|
);
|
3283
3283
|
|
@@ -3340,7 +3340,7 @@ describe('plugin-meetings', () => {
|
|
3340
3340
|
iceConnectionState: 'unknown',
|
3341
3341
|
selectedCandidatePairChanges: 2,
|
3342
3342
|
numTransports: 1,
|
3343
|
-
isSubnetReachable:
|
3343
|
+
isSubnetReachable: null,
|
3344
3344
|
iceCandidatesCount: 0,
|
3345
3345
|
}
|
3346
3346
|
);
|
@@ -3402,6 +3402,120 @@ describe('plugin-meetings', () => {
|
|
3402
3402
|
numTransports: 1,
|
3403
3403
|
'701_error': 2,
|
3404
3404
|
'701_turn_host_lookup_received_error': 1,
|
3405
|
+
isSubnetReachable: null,
|
3406
|
+
iceCandidatesCount: 0,
|
3407
|
+
}
|
3408
|
+
);
|
3409
|
+
|
3410
|
+
assert.isOk(errorThrown);
|
3411
|
+
});
|
3412
|
+
|
3413
|
+
it('should send valid isSubnetReachability if media connection success', async () => {
|
3414
|
+
meeting.roap.doTurnDiscovery = sinon.stub().returns({
|
3415
|
+
turnServerInfo: undefined,
|
3416
|
+
turnDiscoverySkippedReason: undefined,
|
3417
|
+
});
|
3418
|
+
meeting.meetingState = 'ACTIVE';
|
3419
|
+
meeting.mediaProperties.waitForMediaConnectionConnected.resolves();
|
3420
|
+
meeting.webex.meetings.reachability = {
|
3421
|
+
getReachabilityMetrics: sinon.stub().resolves({
|
3422
|
+
reachability_public_udp_success: 5,
|
3423
|
+
}),
|
3424
|
+
stopReachability: sinon.stub(),
|
3425
|
+
isSubnetReachable: sinon.stub().returns(false),
|
3426
|
+
};
|
3427
|
+
|
3428
|
+
const forceRtcMetricsSend = sinon.stub().resolves();
|
3429
|
+
const closeMediaConnectionStub = sinon.stub();
|
3430
|
+
Media.createMediaConnection = sinon.stub().returns({
|
3431
|
+
close: closeMediaConnectionStub,
|
3432
|
+
forceRtcMetricsSend,
|
3433
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
3434
|
+
initiateOffer: sinon.stub().resolves({}),
|
3435
|
+
on: sinon.stub(),
|
3436
|
+
});
|
3437
|
+
|
3438
|
+
await meeting
|
3439
|
+
.addMedia({
|
3440
|
+
mediaSettings: {},
|
3441
|
+
});
|
3442
|
+
|
3443
|
+
assert.calledWith(
|
3444
|
+
Metrics.sendBehavioralMetric,
|
3445
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS,
|
3446
|
+
{
|
3447
|
+
correlation_id: meeting.correlationId,
|
3448
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
3449
|
+
connectionType: 'udp',
|
3450
|
+
selectedCandidatePairChanges: 2,
|
3451
|
+
numTransports: 1,
|
3452
|
+
isMultistream: false,
|
3453
|
+
retriedWithTurnServer: false,
|
3454
|
+
isJoinWithMediaRetry: false,
|
3455
|
+
iceCandidatesCount: 0,
|
3456
|
+
reachability_public_udp_success: 5,
|
3457
|
+
isSubnetReachable: false,
|
3458
|
+
}
|
3459
|
+
);
|
3460
|
+
});
|
3461
|
+
|
3462
|
+
it('should send valid isSubnetReachability if media connection fails', async () => {
|
3463
|
+
let errorThrown = undefined;
|
3464
|
+
|
3465
|
+
meeting.roap.doTurnDiscovery = sinon.stub().returns({
|
3466
|
+
turnServerInfo: undefined,
|
3467
|
+
turnDiscoverySkippedReason: undefined,
|
3468
|
+
});
|
3469
|
+
meeting.meetingState = 'ACTIVE';
|
3470
|
+
meeting.mediaProperties.waitForMediaConnectionConnected.rejects({iceConnected: false});
|
3471
|
+
meeting.webex.meetings.reachability = {
|
3472
|
+
getReachabilityMetrics: sinon.stub().resolves({
|
3473
|
+
reachability_public_udp_success: 5,
|
3474
|
+
}),
|
3475
|
+
stopReachability: sinon.stub(),
|
3476
|
+
isSubnetReachable: sinon.stub().returns(true),
|
3477
|
+
};
|
3478
|
+
|
3479
|
+
const forceRtcMetricsSend = sinon.stub().resolves();
|
3480
|
+
const closeMediaConnectionStub = sinon.stub();
|
3481
|
+
Media.createMediaConnection = sinon.stub().returns({
|
3482
|
+
close: closeMediaConnectionStub,
|
3483
|
+
forceRtcMetricsSend,
|
3484
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
3485
|
+
initiateOffer: sinon.stub().resolves({}),
|
3486
|
+
on: sinon.stub(),
|
3487
|
+
});
|
3488
|
+
|
3489
|
+
await meeting
|
3490
|
+
.addMedia({
|
3491
|
+
mediaSettings: {},
|
3492
|
+
})
|
3493
|
+
.catch((err) => {
|
3494
|
+
errorThrown = err;
|
3495
|
+
assert.instanceOf(err, AddMediaFailed);
|
3496
|
+
});
|
3497
|
+
|
3498
|
+
// Check that the only metric sent is ADD_MEDIA_FAILURE
|
3499
|
+
assert.calledOnceWithExactly(
|
3500
|
+
Metrics.sendBehavioralMetric,
|
3501
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
3502
|
+
{
|
3503
|
+
correlation_id: meeting.correlationId,
|
3504
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
3505
|
+
reason: errorThrown.message,
|
3506
|
+
stack: errorThrown.stack,
|
3507
|
+
code: errorThrown.code,
|
3508
|
+
turnDiscoverySkippedReason: undefined,
|
3509
|
+
turnServerUsed: true,
|
3510
|
+
retriedWithTurnServer: false,
|
3511
|
+
isMultistream: false,
|
3512
|
+
isJoinWithMediaRetry: false,
|
3513
|
+
signalingState: 'unknown',
|
3514
|
+
connectionState: 'unknown',
|
3515
|
+
iceConnectionState: 'unknown',
|
3516
|
+
selectedCandidatePairChanges: 2,
|
3517
|
+
numTransports: 1,
|
3518
|
+
reachability_public_udp_success: 5,
|
3405
3519
|
isSubnetReachable: true,
|
3406
3520
|
iceCandidatesCount: 0,
|
3407
3521
|
}
|
@@ -400,6 +400,19 @@ describe('plugin-meetings', () => {
|
|
400
400
|
});
|
401
401
|
});
|
402
402
|
|
403
|
+
describe('#_toggleDisableAudioMainDtx', () => {
|
404
|
+
it('should have _toggleDisableAudioMainDtx', () => {
|
405
|
+
assert.equal(typeof webex.meetings._toggleDisableAudioMainDtx, 'function');
|
406
|
+
});
|
407
|
+
|
408
|
+
describe('success', () => {
|
409
|
+
it('should update meetings to disable audio main dtx', () => {
|
410
|
+
webex.meetings._toggleDisableAudioMainDtx(true);
|
411
|
+
assert.equal(webex.meetings.config.experimental.disableAudioMainDtx, true);
|
412
|
+
});
|
413
|
+
});
|
414
|
+
});
|
415
|
+
|
403
416
|
describe('Public API Contracts', () => {
|
404
417
|
describe('#register', () => {
|
405
418
|
it('emits an event and resolves when register succeeds', async () => {
|
@@ -658,7 +671,7 @@ describe('plugin-meetings', () => {
|
|
658
671
|
quality: 'LOW',
|
659
672
|
authToken: 'fake_token',
|
660
673
|
mirror: false,
|
661
|
-
canvasResolutionScaling: 1
|
674
|
+
canvasResolutionScaling: 1,
|
662
675
|
});
|
663
676
|
assert.exists(result.enable);
|
664
677
|
assert.exists(result.disable);
|
@@ -674,7 +687,7 @@ describe('plugin-meetings', () => {
|
|
674
687
|
quality: 'HIGH',
|
675
688
|
blurStrength: 'STRONG',
|
676
689
|
bgImageUrl: 'https://test.webex.com/landscape.5a535788.jpg',
|
677
|
-
canvasResolutionScaling: 1
|
690
|
+
canvasResolutionScaling: 1,
|
678
691
|
};
|
679
692
|
|
680
693
|
const result = await webex.meetings.createVirtualBackgroundEffect(effectOptions);
|