mediasoup-client 3.7.1 → 3.7.2
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/README.md +85 -112
- package/lib/Consumer.d.ts +1 -1
- package/lib/Consumer.d.ts.map +1 -1
- package/lib/Consumer.js +1 -1
- package/lib/DataConsumer.d.ts +1 -1
- package/lib/DataConsumer.d.ts.map +1 -1
- package/lib/DataConsumer.js +1 -1
- package/lib/DataProducer.d.ts +1 -1
- package/lib/DataProducer.d.ts.map +1 -1
- package/lib/DataProducer.js +1 -1
- package/lib/Device.d.ts +3 -3
- package/lib/Device.d.ts.map +1 -1
- package/lib/Device.js +66 -89
- package/lib/EnhancedEventEmitter.d.ts.map +1 -1
- package/lib/Logger.d.ts.map +1 -1
- package/lib/Producer.d.ts +5 -15
- package/lib/Producer.d.ts.map +1 -1
- package/lib/Producer.js +2 -2
- package/lib/RtpParameters.d.ts.map +1 -1
- package/lib/SctpParameters.d.ts.map +1 -1
- package/lib/Transport.d.ts +14 -10
- package/lib/Transport.d.ts.map +1 -1
- package/lib/Transport.js +71 -53
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +6 -6
- package/lib/handlers/Chrome111.d.ts +4 -4
- package/lib/handlers/Chrome111.d.ts.map +1 -1
- package/lib/handlers/Chrome111.js +74 -77
- package/lib/handlers/Chrome55.d.ts +4 -4
- package/lib/handlers/Chrome55.d.ts.map +1 -1
- package/lib/handlers/Chrome55.js +83 -80
- package/lib/handlers/Chrome67.d.ts +4 -4
- package/lib/handlers/Chrome67.d.ts.map +1 -1
- package/lib/handlers/Chrome67.js +85 -83
- package/lib/handlers/Chrome70.d.ts +4 -4
- package/lib/handlers/Chrome70.d.ts.map +1 -1
- package/lib/handlers/Chrome70.js +76 -78
- package/lib/handlers/Chrome74.d.ts +4 -4
- package/lib/handlers/Chrome74.d.ts.map +1 -1
- package/lib/handlers/Chrome74.js +75 -78
- package/lib/handlers/Edge11.d.ts +1 -1
- package/lib/handlers/Edge11.d.ts.map +1 -1
- package/lib/handlers/Edge11.js +63 -77
- package/lib/handlers/FakeHandler.d.ts +3 -3
- package/lib/handlers/FakeHandler.d.ts.map +1 -1
- package/lib/handlers/FakeHandler.js +19 -22
- package/lib/handlers/Firefox60.d.ts +4 -4
- package/lib/handlers/Firefox60.d.ts.map +1 -1
- package/lib/handlers/Firefox60.js +75 -72
- package/lib/handlers/HandlerInterface.d.ts.map +1 -1
- package/lib/handlers/ReactNative.d.ts +4 -4
- package/lib/handlers/ReactNative.d.ts.map +1 -1
- package/lib/handlers/ReactNative.js +84 -82
- package/lib/handlers/ReactNativeUnifiedPlan.d.ts +4 -4
- package/lib/handlers/ReactNativeUnifiedPlan.d.ts.map +1 -1
- package/lib/handlers/ReactNativeUnifiedPlan.js +75 -78
- package/lib/handlers/Safari11.d.ts +4 -4
- package/lib/handlers/Safari11.d.ts.map +1 -1
- package/lib/handlers/Safari11.js +84 -81
- package/lib/handlers/Safari12.d.ts +4 -4
- package/lib/handlers/Safari12.d.ts.map +1 -1
- package/lib/handlers/Safari12.js +75 -77
- package/lib/handlers/ortc/edgeUtils.d.ts.map +1 -1
- package/lib/handlers/ortc/utils.d.ts.map +1 -1
- package/lib/handlers/ortc/utils.js +2 -2
- package/lib/handlers/sdp/MediaSection.d.ts +5 -5
- package/lib/handlers/sdp/MediaSection.d.ts.map +1 -1
- package/lib/handlers/sdp/MediaSection.js +293 -317
- package/lib/handlers/sdp/RemoteSdp.d.ts +5 -5
- package/lib/handlers/sdp/RemoteSdp.d.ts.map +1 -1
- package/lib/handlers/sdp/RemoteSdp.js +28 -30
- package/lib/handlers/sdp/commonUtils.d.ts +4 -4
- package/lib/handlers/sdp/commonUtils.d.ts.map +1 -1
- package/lib/handlers/sdp/commonUtils.js +47 -58
- package/lib/handlers/sdp/plainRtpUtils.d.ts +2 -2
- package/lib/handlers/sdp/plainRtpUtils.d.ts.map +1 -1
- package/lib/handlers/sdp/plainRtpUtils.js +5 -7
- package/lib/handlers/sdp/planBUtils.d.ts +2 -2
- package/lib/handlers/sdp/planBUtils.d.ts.map +1 -1
- package/lib/handlers/sdp/planBUtils.js +11 -14
- package/lib/handlers/sdp/unifiedPlanUtils.d.ts +2 -2
- package/lib/handlers/sdp/unifiedPlanUtils.d.ts.map +1 -1
- package/lib/handlers/sdp/unifiedPlanUtils.js +11 -14
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/ortc.d.ts.map +1 -1
- package/lib/ortc.js +98 -108
- package/lib/scalabilityModes.d.ts.map +1 -1
- package/lib/scalabilityModes.js +2 -2
- package/lib/{tests → test}/fakeParameters.d.ts +2 -2
- package/lib/test/fakeParameters.d.ts.map +1 -0
- package/lib/test/fakeParameters.js +645 -0
- package/lib/{tests → test}/test.d.ts.map +1 -1
- package/lib/{tests → test}/test.js +466 -495
- package/lib/test/uaTestCases.d.ts.map +1 -0
- package/lib/{tests → test}/uaTestCases.js +17 -17
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/npm-scripts.mjs +72 -98
- package/package.json +93 -90
- package/lib/tests/fakeParameters.d.ts.map +0 -1
- package/lib/tests/fakeParameters.js +0 -662
- package/lib/tests/uaTestCases.d.ts.map +0 -1
- /package/lib/{tests → test}/test.d.ts +0 -0
- /package/lib/{tests → test}/uaTestCases.d.ts +0 -0
|
@@ -37,15 +37,108 @@ const FakeHandler_1 = require("../handlers/FakeHandler");
|
|
|
37
37
|
const fakeParameters = __importStar(require("./fakeParameters"));
|
|
38
38
|
const uaTestCases_1 = require("./uaTestCases");
|
|
39
39
|
const { Device, detectDevice, parseScalabilityMode, debug } = mediasoupClient;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
const ctx = {};
|
|
41
|
+
beforeEach(async () => {
|
|
42
|
+
ctx.device = new Device({
|
|
43
|
+
handlerFactory: FakeHandler_1.FakeHandler.createFactory(fakeParameters),
|
|
44
|
+
});
|
|
45
|
+
ctx.loadedDevice = new Device({
|
|
46
|
+
handlerFactory: FakeHandler_1.FakeHandler.createFactory(fakeParameters),
|
|
47
|
+
});
|
|
48
|
+
const routerRtpCapabilities = fakeParameters.generateRouterRtpCapabilities();
|
|
49
|
+
// Only load loadedDevice.
|
|
50
|
+
await ctx.loadedDevice.load({ routerRtpCapabilities });
|
|
51
|
+
const { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters } = fakeParameters.generateTransportRemoteParameters();
|
|
52
|
+
ctx.sendTransport = ctx.loadedDevice.createSendTransport({
|
|
53
|
+
id,
|
|
54
|
+
iceParameters,
|
|
55
|
+
iceCandidates,
|
|
56
|
+
dtlsParameters,
|
|
57
|
+
sctpParameters,
|
|
58
|
+
});
|
|
59
|
+
ctx.connectedSendTransport = ctx.loadedDevice.createSendTransport({
|
|
60
|
+
id,
|
|
61
|
+
iceParameters,
|
|
62
|
+
iceCandidates,
|
|
63
|
+
dtlsParameters,
|
|
64
|
+
sctpParameters,
|
|
65
|
+
});
|
|
66
|
+
ctx.connectedSendTransport.on('connect',
|
|
67
|
+
// eslint-disable-next-line no-shadow, @typescript-eslint/no-unused-vars
|
|
68
|
+
({ dtlsParameters }, callback /* errback */) => {
|
|
69
|
+
setTimeout(callback);
|
|
70
|
+
});
|
|
71
|
+
ctx.connectedSendTransport.on('produce',
|
|
72
|
+
// eslint-disable-next-line no-shadow, @typescript-eslint/no-unused-vars
|
|
73
|
+
({ kind, rtpParameters, appData }, callback /* errback */) => {
|
|
74
|
+
// eslint-disable-next-line no-shadow
|
|
75
|
+
const id = fakeParameters.generateProducerRemoteParameters().id;
|
|
76
|
+
setTimeout(() => callback({ id }));
|
|
77
|
+
});
|
|
78
|
+
ctx.connectedSendTransport.on('producedata', (
|
|
79
|
+
// eslint-disable-next-line no-shadow, @typescript-eslint/no-unused-vars
|
|
80
|
+
{ sctpStreamParameters, label, protocol, appData }, callback /* errback */) => {
|
|
81
|
+
// eslint-disable-next-line no-shadow
|
|
82
|
+
const id = fakeParameters.generateDataProducerRemoteParameters().id;
|
|
83
|
+
setTimeout(() => callback({ id }));
|
|
84
|
+
});
|
|
85
|
+
ctx.recvTransport = ctx.loadedDevice.createRecvTransport({
|
|
86
|
+
id,
|
|
87
|
+
iceParameters,
|
|
88
|
+
iceCandidates,
|
|
89
|
+
dtlsParameters,
|
|
90
|
+
sctpParameters,
|
|
91
|
+
});
|
|
92
|
+
ctx.connectedRecvTransport = ctx.loadedDevice.createRecvTransport({
|
|
93
|
+
id,
|
|
94
|
+
iceParameters,
|
|
95
|
+
iceCandidates,
|
|
96
|
+
dtlsParameters,
|
|
97
|
+
sctpParameters,
|
|
98
|
+
});
|
|
99
|
+
ctx.connectedRecvTransport.on('connect',
|
|
100
|
+
// eslint-disable-next-line no-shadow, @typescript-eslint/no-unused-vars
|
|
101
|
+
({ dtlsParameters }, callback /* errback */) => {
|
|
102
|
+
setTimeout(callback);
|
|
103
|
+
});
|
|
104
|
+
const audioTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
105
|
+
ctx.audioProducer = await ctx.connectedSendTransport.produce({
|
|
106
|
+
track: audioTrack,
|
|
107
|
+
stopTracks: false,
|
|
108
|
+
});
|
|
109
|
+
const videoTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'video' });
|
|
110
|
+
ctx.videoProducer = await ctx.connectedSendTransport.produce({
|
|
111
|
+
track: videoTrack,
|
|
112
|
+
});
|
|
113
|
+
const audioConsumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
114
|
+
codecMimeType: 'audio/opus',
|
|
115
|
+
});
|
|
116
|
+
ctx.audioConsumer = await ctx.connectedRecvTransport.consume({
|
|
117
|
+
id: audioConsumerRemoteParameters.id,
|
|
118
|
+
producerId: audioConsumerRemoteParameters.producerId,
|
|
119
|
+
kind: audioConsumerRemoteParameters.kind,
|
|
120
|
+
rtpParameters: audioConsumerRemoteParameters.rtpParameters,
|
|
121
|
+
});
|
|
122
|
+
const videoConsumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
123
|
+
codecMimeType: 'video/VP8',
|
|
124
|
+
});
|
|
125
|
+
ctx.videoConsumer = await ctx.connectedRecvTransport.consume({
|
|
126
|
+
id: videoConsumerRemoteParameters.id,
|
|
127
|
+
producerId: videoConsumerRemoteParameters.producerId,
|
|
128
|
+
kind: videoConsumerRemoteParameters.kind,
|
|
129
|
+
rtpParameters: videoConsumerRemoteParameters.rtpParameters,
|
|
130
|
+
});
|
|
131
|
+
ctx.dataProducer = await ctx.connectedSendTransport.produceData({
|
|
132
|
+
ordered: false,
|
|
133
|
+
maxPacketLifeTime: 5555,
|
|
134
|
+
});
|
|
135
|
+
const dataConsumerRemoteParameters = fakeParameters.generateDataConsumerRemoteParameters();
|
|
136
|
+
ctx.dataConsumer = await ctx.connectedRecvTransport.consumeData({
|
|
137
|
+
id: dataConsumerRemoteParameters.id,
|
|
138
|
+
dataProducerId: dataConsumerRemoteParameters.dataProducerId,
|
|
139
|
+
sctpStreamParameters: dataConsumerRemoteParameters.sctpStreamParameters,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
49
142
|
test('mediasoup-client exposes debug dependency', () => {
|
|
50
143
|
expect(typeof debug).toBe('function');
|
|
51
144
|
}, 500);
|
|
@@ -53,102 +146,89 @@ test('detectDevice() returns nothing in Node', () => {
|
|
|
53
146
|
expect(detectDevice()).toBe(undefined);
|
|
54
147
|
});
|
|
55
148
|
test('create a Device in Node without custom handlerName/handlerFactory throws UnsupportedError', () => {
|
|
56
|
-
expect(() => new Device())
|
|
57
|
-
.toThrow(errors_1.UnsupportedError);
|
|
149
|
+
expect(() => new Device()).toThrow(errors_1.UnsupportedError);
|
|
58
150
|
});
|
|
59
151
|
test('create a Device with an unknown handlerName string throws TypeError', () => {
|
|
60
152
|
// @ts-ignore
|
|
61
|
-
expect(() => new Device({ handlerName: 'FooBrowser666' }))
|
|
62
|
-
.toThrow(TypeError);
|
|
153
|
+
expect(() => new Device({ handlerName: 'FooBrowser666' })).toThrow(TypeError);
|
|
63
154
|
});
|
|
64
155
|
test('create a Device in Node with a valid handlerFactory succeeds', () => {
|
|
65
|
-
device = new Device({
|
|
156
|
+
const device = new Device({
|
|
157
|
+
handlerFactory: FakeHandler_1.FakeHandler.createFactory(fakeParameters),
|
|
158
|
+
});
|
|
66
159
|
expect(typeof device).toBe('object');
|
|
67
160
|
expect(device.handlerName).toBe('FakeHandler');
|
|
68
161
|
expect(device.loaded).toBe(false);
|
|
69
162
|
});
|
|
70
163
|
test('device.rtpCapabilities getter throws InvalidStateError if not loaded', () => {
|
|
71
|
-
expect(() => device.rtpCapabilities)
|
|
72
|
-
.toThrow(errors_1.InvalidStateError);
|
|
164
|
+
expect(() => ctx.device.rtpCapabilities).toThrow(errors_1.InvalidStateError);
|
|
73
165
|
});
|
|
74
166
|
test('device.sctpCapabilities getter throws InvalidStateError if not loaded', () => {
|
|
75
|
-
expect(() => device.sctpCapabilities)
|
|
76
|
-
.toThrow(errors_1.InvalidStateError);
|
|
167
|
+
expect(() => ctx.device.sctpCapabilities).toThrow(errors_1.InvalidStateError);
|
|
77
168
|
});
|
|
78
169
|
test('device.canProduce() throws InvalidStateError if not loaded', () => {
|
|
79
|
-
expect(() => device.canProduce('audio'))
|
|
80
|
-
.toThrow(errors_1.InvalidStateError);
|
|
170
|
+
expect(() => ctx.device.canProduce('audio')).toThrow(errors_1.InvalidStateError);
|
|
81
171
|
});
|
|
82
172
|
test('device.createSendTransport() throws InvalidStateError if not loaded', () => {
|
|
83
173
|
const { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters } = fakeParameters.generateTransportRemoteParameters();
|
|
84
|
-
expect(() => device.createSendTransport({
|
|
174
|
+
expect(() => ctx.device.createSendTransport({
|
|
85
175
|
id,
|
|
86
176
|
iceParameters,
|
|
87
177
|
iceCandidates,
|
|
88
178
|
dtlsParameters,
|
|
89
|
-
sctpParameters
|
|
90
|
-
}))
|
|
91
|
-
.toThrow(errors_1.InvalidStateError);
|
|
179
|
+
sctpParameters,
|
|
180
|
+
})).toThrow(errors_1.InvalidStateError);
|
|
92
181
|
});
|
|
93
182
|
test('device.load() without routerRtpCapabilities rejects with TypeError', async () => {
|
|
94
183
|
// @ts-ignore
|
|
95
|
-
await expect(device.load({}))
|
|
96
|
-
|
|
97
|
-
.toThrow(TypeError);
|
|
98
|
-
expect(device.loaded).toBe(false);
|
|
184
|
+
await expect(ctx.device.load({})).rejects.toThrow(TypeError);
|
|
185
|
+
expect(ctx.device.loaded).toBe(false);
|
|
99
186
|
}, 500);
|
|
100
187
|
test('device.load() with invalid routerRtpCapabilities rejects with TypeError', async () => {
|
|
101
|
-
//
|
|
188
|
+
// Clone fake router RTP capabilities to make them invalid.
|
|
102
189
|
const routerRtpCapabilities = utils.clone(fakeParameters.generateRouterRtpCapabilities());
|
|
103
190
|
for (const codec of routerRtpCapabilities.codecs) {
|
|
104
191
|
// @ts-ignore
|
|
105
192
|
delete codec.mimeType;
|
|
106
193
|
}
|
|
107
|
-
await expect(device.load({ routerRtpCapabilities }))
|
|
108
|
-
|
|
109
|
-
.toThrow(TypeError);
|
|
110
|
-
expect(device.loaded).toBe(false);
|
|
194
|
+
await expect(ctx.device.load({ routerRtpCapabilities })).rejects.toThrow(TypeError);
|
|
195
|
+
expect(ctx.device.loaded).toBe(false);
|
|
111
196
|
}, 500);
|
|
112
197
|
test('device.load() succeeds', async () => {
|
|
113
198
|
// Assume we get the router RTP capabilities.
|
|
114
199
|
const routerRtpCapabilities = fakeParameters.generateRouterRtpCapabilities();
|
|
115
|
-
await expect(device.load({ routerRtpCapabilities }))
|
|
116
|
-
|
|
117
|
-
.toBe(undefined);
|
|
118
|
-
expect(device.loaded).toBe(true);
|
|
200
|
+
await expect(ctx.device.load({ routerRtpCapabilities })).resolves.toBe(undefined);
|
|
201
|
+
expect(ctx.device.loaded).toBe(true);
|
|
119
202
|
}, 500);
|
|
120
203
|
test('device.load() rejects with InvalidStateError if already loaded', async () => {
|
|
121
|
-
|
|
122
|
-
await expect(
|
|
123
|
-
|
|
124
|
-
.toThrow(errors_1.InvalidStateError);
|
|
125
|
-
expect(device.loaded).toBe(true);
|
|
204
|
+
const routerRtpCapabilities = fakeParameters.generateRouterRtpCapabilities();
|
|
205
|
+
await expect(ctx.loadedDevice.load({ routerRtpCapabilities })).rejects.toThrow(errors_1.InvalidStateError);
|
|
206
|
+
expect(ctx.loadedDevice.loaded).toBe(true);
|
|
126
207
|
}, 500);
|
|
127
208
|
test('device.rtpCapabilities getter succeeds', () => {
|
|
128
|
-
expect(typeof
|
|
209
|
+
expect(typeof ctx.loadedDevice.rtpCapabilities).toBe('object');
|
|
129
210
|
});
|
|
130
211
|
test('device.sctpCapabilities getter succeeds', () => {
|
|
131
|
-
expect(typeof
|
|
212
|
+
expect(typeof ctx.loadedDevice.sctpCapabilities).toBe('object');
|
|
132
213
|
});
|
|
133
214
|
test('device.canProduce() with "audio"/"video" kind returns true', () => {
|
|
134
|
-
expect(
|
|
135
|
-
expect(
|
|
215
|
+
expect(ctx.loadedDevice.canProduce('audio')).toBe(true);
|
|
216
|
+
expect(ctx.loadedDevice.canProduce('video')).toBe(true);
|
|
136
217
|
});
|
|
137
218
|
test('device.canProduce() with invalid kind throws TypeError', () => {
|
|
138
219
|
// @ts-ignore
|
|
139
|
-
expect(() =>
|
|
140
|
-
.toThrow(TypeError);
|
|
220
|
+
expect(() => ctx.loadedDevice.canProduce('chicken')).toThrow(TypeError);
|
|
141
221
|
});
|
|
142
222
|
test('device.createSendTransport() for sending media succeeds', () => {
|
|
143
223
|
// Assume we create a transport in the server and get its remote parameters.
|
|
144
224
|
const { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters } = fakeParameters.generateTransportRemoteParameters();
|
|
145
|
-
sendTransport =
|
|
225
|
+
const sendTransport = ctx.loadedDevice.createSendTransport({
|
|
146
226
|
id,
|
|
147
227
|
iceParameters,
|
|
148
228
|
iceCandidates,
|
|
149
229
|
dtlsParameters,
|
|
150
230
|
sctpParameters,
|
|
151
|
-
appData: { foo: 123 }
|
|
231
|
+
appData: { foo: 123 },
|
|
152
232
|
});
|
|
153
233
|
expect(typeof sendTransport).toBe('object');
|
|
154
234
|
expect(sendTransport.id).toBe(id);
|
|
@@ -162,12 +242,12 @@ test('device.createSendTransport() for sending media succeeds', () => {
|
|
|
162
242
|
test('device.createRecvTransport() for receiving media succeeds', () => {
|
|
163
243
|
// Assume we create a transport in the server and get its remote parameters.
|
|
164
244
|
const { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters } = fakeParameters.generateTransportRemoteParameters();
|
|
165
|
-
recvTransport =
|
|
245
|
+
const recvTransport = ctx.loadedDevice.createRecvTransport({
|
|
166
246
|
id,
|
|
167
247
|
iceParameters,
|
|
168
248
|
iceCandidates,
|
|
169
249
|
dtlsParameters,
|
|
170
|
-
sctpParameters
|
|
250
|
+
sctpParameters,
|
|
171
251
|
});
|
|
172
252
|
expect(typeof recvTransport).toBe('object');
|
|
173
253
|
expect(recvTransport.id).toBe(id);
|
|
@@ -180,95 +260,58 @@ test('device.createRecvTransport() for receiving media succeeds', () => {
|
|
|
180
260
|
});
|
|
181
261
|
test('device.createSendTransport() with missing remote Transport parameters throws TypeError', () => {
|
|
182
262
|
// @ts-ignore
|
|
183
|
-
expect(() =>
|
|
184
|
-
|
|
263
|
+
expect(() => ctx.loadedDevice.createSendTransport({ id: '1234' })).toThrow(TypeError);
|
|
264
|
+
expect(() =>
|
|
185
265
|
// @ts-ignore
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
expect(() => device.createSendTransport({
|
|
266
|
+
ctx.loadedDevice.createSendTransport({ id: '1234', iceParameters: {} })).toThrow(TypeError);
|
|
267
|
+
expect(() => ctx.loadedDevice.createSendTransport({
|
|
189
268
|
id: '1234',
|
|
190
269
|
// @ts-ignore
|
|
191
270
|
iceParameters: {},
|
|
192
|
-
iceCandidates: []
|
|
193
|
-
}))
|
|
194
|
-
.toThrow(TypeError);
|
|
271
|
+
iceCandidates: [],
|
|
272
|
+
})).toThrow(TypeError);
|
|
195
273
|
});
|
|
196
274
|
test('device.createRecvTransport() with a non object appData throws TypeError', () => {
|
|
197
275
|
const { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters } = fakeParameters.generateTransportRemoteParameters();
|
|
198
|
-
expect(() =>
|
|
276
|
+
expect(() => ctx.loadedDevice.createRecvTransport({
|
|
199
277
|
id,
|
|
200
278
|
iceParameters,
|
|
201
279
|
iceCandidates,
|
|
202
280
|
dtlsParameters,
|
|
203
281
|
sctpParameters,
|
|
204
282
|
// @ts-ignore
|
|
205
|
-
appData: 1234
|
|
206
|
-
}))
|
|
207
|
-
.toThrow(TypeError);
|
|
283
|
+
appData: 1234,
|
|
284
|
+
})).toThrow(TypeError);
|
|
208
285
|
});
|
|
209
|
-
test('transport.produce() without "
|
|
286
|
+
test('transport.produce() without "produce" listener rejects', async () => {
|
|
210
287
|
const audioTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
.toThrow(Error);
|
|
288
|
+
ctx.sendTransport.removeAllListeners('produce');
|
|
289
|
+
await expect(ctx.sendTransport.produce({ track: audioTrack })).rejects.toThrow(Error);
|
|
214
290
|
}, 500);
|
|
215
291
|
test('transport.produce() succeeds', async () => {
|
|
216
292
|
const audioTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
217
293
|
const videoTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'video' });
|
|
218
|
-
let audioProducerId;
|
|
219
|
-
let videoProducerId;
|
|
220
294
|
let connectEventNumTimesCalled = 0;
|
|
221
295
|
let produceEventNumTimesCalled = 0;
|
|
222
|
-
// eslint-disable-next-line no-unused-vars
|
|
223
|
-
sendTransport.on('connect', ({ dtlsParameters }, callback /* errback */) => {
|
|
224
|
-
connectEventNumTimesCalled++;
|
|
225
|
-
expect(typeof dtlsParameters).toBe('object');
|
|
226
|
-
// Emulate communication with the server and success response (no response
|
|
227
|
-
// data needed).
|
|
228
|
-
setTimeout(callback);
|
|
229
|
-
});
|
|
230
|
-
// eslint-disable-next-line no-unused-vars
|
|
231
|
-
sendTransport.on('produce', ({ kind, rtpParameters, appData }, callback /* errback */) => {
|
|
232
|
-
produceEventNumTimesCalled++;
|
|
233
|
-
expect(typeof kind).toBe('string');
|
|
234
|
-
expect(typeof rtpParameters).toBe('object');
|
|
235
|
-
let id;
|
|
236
|
-
switch (kind) {
|
|
237
|
-
case 'audio':
|
|
238
|
-
{
|
|
239
|
-
expect(appData).toEqual({ foo: 'FOO' });
|
|
240
|
-
id = fakeParameters.generateProducerRemoteParameters().id;
|
|
241
|
-
audioProducerId = id;
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
case 'video':
|
|
245
|
-
{
|
|
246
|
-
expect(appData).toEqual({});
|
|
247
|
-
id = fakeParameters.generateProducerRemoteParameters().id;
|
|
248
|
-
videoProducerId = id;
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
default:
|
|
252
|
-
{
|
|
253
|
-
throw new Error('unknown kind');
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
// Emulate communication with the server and success response with Producer
|
|
257
|
-
// remote parameters.
|
|
258
|
-
setTimeout(() => callback({ id }));
|
|
259
|
-
});
|
|
260
296
|
let codecs;
|
|
261
297
|
let headerExtensions;
|
|
262
298
|
let encodings;
|
|
263
299
|
let rtcp;
|
|
264
300
|
// Pause the audio track before creating its Producer.
|
|
265
301
|
audioTrack.enabled = false;
|
|
302
|
+
ctx.connectedSendTransport.prependListener('connect', () => ++connectEventNumTimesCalled);
|
|
303
|
+
ctx.connectedSendTransport.prependListener('produce', () => ++produceEventNumTimesCalled);
|
|
266
304
|
// Use stopTracks: false.
|
|
267
|
-
audioProducer = await
|
|
268
|
-
|
|
305
|
+
const audioProducer = await ctx.connectedSendTransport.produce({
|
|
306
|
+
track: audioTrack,
|
|
307
|
+
stopTracks: false,
|
|
308
|
+
appData: { foo: 'FOO' },
|
|
309
|
+
});
|
|
310
|
+
// 'connect' event should not have been called since it was in beforeEach already.
|
|
311
|
+
expect(connectEventNumTimesCalled).toBe(0);
|
|
269
312
|
expect(produceEventNumTimesCalled).toBe(1);
|
|
270
313
|
expect(typeof audioProducer).toBe('object');
|
|
271
|
-
expect(audioProducer.id).toBe(
|
|
314
|
+
expect(typeof audioProducer.id).toBe('string');
|
|
272
315
|
expect(audioProducer.closed).toBe(false);
|
|
273
316
|
expect(audioProducer.kind).toBe('audio');
|
|
274
317
|
expect(audioProducer.track).toBe(audioTrack);
|
|
@@ -281,13 +324,11 @@ test('transport.produce() succeeds', async () => {
|
|
|
281
324
|
payloadType: 111,
|
|
282
325
|
clockRate: 48000,
|
|
283
326
|
channels: 2,
|
|
284
|
-
rtcpFeedback: [
|
|
285
|
-
{ type: 'transport-cc', parameter: '' }
|
|
286
|
-
],
|
|
327
|
+
rtcpFeedback: [{ type: 'transport-cc', parameter: '' }],
|
|
287
328
|
parameters: {
|
|
288
329
|
minptime: 10,
|
|
289
|
-
useinbandfec: 1
|
|
290
|
-
}
|
|
330
|
+
useinbandfec: 1,
|
|
331
|
+
},
|
|
291
332
|
});
|
|
292
333
|
headerExtensions = audioProducer.rtpParameters.headerExtensions;
|
|
293
334
|
expect(headerExtensions).toEqual([
|
|
@@ -295,14 +336,14 @@ test('transport.produce() succeeds', async () => {
|
|
|
295
336
|
uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
|
|
296
337
|
id: 1,
|
|
297
338
|
encrypt: false,
|
|
298
|
-
parameters: {}
|
|
339
|
+
parameters: {},
|
|
299
340
|
},
|
|
300
341
|
{
|
|
301
342
|
uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level',
|
|
302
343
|
id: 10,
|
|
303
344
|
encrypt: false,
|
|
304
|
-
parameters: {}
|
|
305
|
-
}
|
|
345
|
+
parameters: {},
|
|
346
|
+
},
|
|
306
347
|
]);
|
|
307
348
|
encodings = audioProducer.rtpParameters.encodings;
|
|
308
349
|
expect(Array.isArray(encodings)).toBe(true);
|
|
@@ -318,22 +359,19 @@ test('transport.produce() succeeds', async () => {
|
|
|
318
359
|
expect(audioProducer.appData).toEqual({ foo: 'FOO' });
|
|
319
360
|
// Reset the audio paused state.
|
|
320
361
|
audioProducer.resume();
|
|
321
|
-
const videoEncodings = [
|
|
322
|
-
{ maxBitrate: 100000 },
|
|
323
|
-
{ maxBitrate: 500000 }
|
|
324
|
-
];
|
|
362
|
+
const videoEncodings = [{ maxBitrate: 100000 }, { maxBitrate: 500000 }];
|
|
325
363
|
// Note that stopTracks is not give so it's true by default.
|
|
326
364
|
// Use disableTrackOnPause: false and zeroRtpOnPause: true
|
|
327
|
-
videoProducer = await
|
|
365
|
+
const videoProducer = await ctx.connectedSendTransport.produce({
|
|
328
366
|
track: videoTrack,
|
|
329
367
|
encodings: videoEncodings,
|
|
330
368
|
disableTrackOnPause: false,
|
|
331
|
-
zeroRtpOnPause: true
|
|
369
|
+
zeroRtpOnPause: true,
|
|
332
370
|
});
|
|
333
|
-
expect(connectEventNumTimesCalled).toBe(
|
|
371
|
+
expect(connectEventNumTimesCalled).toBe(0);
|
|
334
372
|
expect(produceEventNumTimesCalled).toBe(2);
|
|
335
373
|
expect(typeof videoProducer).toBe('object');
|
|
336
|
-
expect(videoProducer.id).toBe(
|
|
374
|
+
expect(typeof videoProducer.id).toBe('string');
|
|
337
375
|
expect(videoProducer.closed).toBe(false);
|
|
338
376
|
expect(videoProducer.kind).toBe('video');
|
|
339
377
|
expect(videoProducer.track).toBe(videoTrack);
|
|
@@ -350,11 +388,11 @@ test('transport.produce() succeeds', async () => {
|
|
|
350
388
|
{ type: 'transport-cc', parameter: '' },
|
|
351
389
|
{ type: 'ccm', parameter: 'fir' },
|
|
352
390
|
{ type: 'nack', parameter: '' },
|
|
353
|
-
{ type: 'nack', parameter: 'pli' }
|
|
391
|
+
{ type: 'nack', parameter: 'pli' },
|
|
354
392
|
],
|
|
355
393
|
parameters: {
|
|
356
|
-
baz: '1234abcd'
|
|
357
|
-
}
|
|
394
|
+
baz: '1234abcd',
|
|
395
|
+
},
|
|
358
396
|
});
|
|
359
397
|
expect(codecs[1]).toEqual({
|
|
360
398
|
mimeType: 'video/rtx',
|
|
@@ -362,8 +400,8 @@ test('transport.produce() succeeds', async () => {
|
|
|
362
400
|
clockRate: 90000,
|
|
363
401
|
rtcpFeedback: [],
|
|
364
402
|
parameters: {
|
|
365
|
-
apt: 96
|
|
366
|
-
}
|
|
403
|
+
apt: 96,
|
|
404
|
+
},
|
|
367
405
|
});
|
|
368
406
|
headerExtensions = videoProducer.rtpParameters.headerExtensions;
|
|
369
407
|
expect(headerExtensions).toEqual([
|
|
@@ -371,32 +409,32 @@ test('transport.produce() succeeds', async () => {
|
|
|
371
409
|
uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
|
|
372
410
|
id: 1,
|
|
373
411
|
encrypt: false,
|
|
374
|
-
parameters: {}
|
|
412
|
+
parameters: {},
|
|
375
413
|
},
|
|
376
414
|
{
|
|
377
415
|
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
378
416
|
id: 3,
|
|
379
417
|
encrypt: false,
|
|
380
|
-
parameters: {}
|
|
418
|
+
parameters: {},
|
|
381
419
|
},
|
|
382
420
|
{
|
|
383
421
|
uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01',
|
|
384
422
|
id: 5,
|
|
385
423
|
encrypt: false,
|
|
386
|
-
parameters: {}
|
|
424
|
+
parameters: {},
|
|
387
425
|
},
|
|
388
426
|
{
|
|
389
427
|
uri: 'urn:3gpp:video-orientation',
|
|
390
428
|
id: 4,
|
|
391
429
|
encrypt: false,
|
|
392
|
-
parameters: {}
|
|
430
|
+
parameters: {},
|
|
393
431
|
},
|
|
394
432
|
{
|
|
395
433
|
uri: 'urn:ietf:params:rtp-hdrext:toffset',
|
|
396
434
|
id: 2,
|
|
397
435
|
encrypt: false,
|
|
398
|
-
parameters: {}
|
|
399
|
-
}
|
|
436
|
+
parameters: {},
|
|
437
|
+
},
|
|
400
438
|
]);
|
|
401
439
|
encodings = videoProducer.rtpParameters.encodings;
|
|
402
440
|
expect(Array.isArray(encodings)).toBe(true);
|
|
@@ -417,58 +455,47 @@ test('transport.produce() succeeds', async () => {
|
|
|
417
455
|
expect(videoProducer.paused).toBe(false);
|
|
418
456
|
expect(videoProducer.maxSpatialLayer).toBe(undefined);
|
|
419
457
|
expect(videoProducer.appData).toEqual({});
|
|
420
|
-
sendTransport.removeAllListeners('connect');
|
|
421
|
-
sendTransport.removeAllListeners('produce');
|
|
422
458
|
}, 500);
|
|
423
459
|
test('transport.produce() without track rejects with TypeError', async () => {
|
|
424
|
-
await expect(sendTransport.produce({}))
|
|
425
|
-
.rejects
|
|
426
|
-
.toThrow(TypeError);
|
|
460
|
+
await expect(ctx.sendTransport.produce({})).rejects.toThrow(TypeError);
|
|
427
461
|
}, 500);
|
|
428
462
|
test('transport.produce() in a receiving Transport rejects with UnsupportedError', async () => {
|
|
429
463
|
const track = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
430
|
-
await expect(recvTransport.produce({ track }))
|
|
431
|
-
.rejects
|
|
432
|
-
.toThrow(errors_1.UnsupportedError);
|
|
464
|
+
await expect(ctx.recvTransport.produce({ track })).rejects.toThrow(errors_1.UnsupportedError);
|
|
433
465
|
}, 500);
|
|
434
466
|
test('transport.produce() with an ended track rejects with InvalidStateError', async () => {
|
|
435
467
|
const track = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
436
468
|
track.stop();
|
|
437
|
-
await expect(sendTransport.produce({ track }))
|
|
438
|
-
.rejects
|
|
439
|
-
.toThrow(errors_1.InvalidStateError);
|
|
469
|
+
await expect(ctx.sendTransport.produce({ track })).rejects.toThrow(errors_1.InvalidStateError);
|
|
440
470
|
}, 500);
|
|
441
471
|
test('transport.produce() with a non object appData rejects with TypeError', async () => {
|
|
442
472
|
const track = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
473
|
+
await expect(
|
|
443
474
|
// @ts-ignore
|
|
444
|
-
|
|
445
|
-
.rejects
|
|
446
|
-
.toThrow(TypeError);
|
|
475
|
+
ctx.sendTransport.produce({ track, appData: true })).rejects.toThrow(TypeError);
|
|
447
476
|
}, 500);
|
|
448
477
|
test('transport.consume() succeeds', async () => {
|
|
449
|
-
const audioConsumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
450
|
-
|
|
451
|
-
let connectEventNumTimesCalled = 0;
|
|
452
|
-
// eslint-disable-next-line no-unused-vars
|
|
453
|
-
recvTransport.on('connect', ({ dtlsParameters }, callback /* errback */) => {
|
|
454
|
-
connectEventNumTimesCalled++;
|
|
455
|
-
expect(typeof dtlsParameters).toBe('object');
|
|
456
|
-
// Emulate communication with the server and success response (no response
|
|
457
|
-
// data needed).
|
|
458
|
-
setTimeout(callback);
|
|
478
|
+
const audioConsumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
479
|
+
codecMimeType: 'audio/opus',
|
|
459
480
|
});
|
|
481
|
+
const videoConsumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
482
|
+
codecMimeType: 'video/VP8',
|
|
483
|
+
});
|
|
484
|
+
let connectEventNumTimesCalled = 0;
|
|
460
485
|
let codecs;
|
|
461
486
|
let headerExtensions;
|
|
462
487
|
let encodings;
|
|
463
488
|
let rtcp;
|
|
464
|
-
|
|
489
|
+
ctx.connectedRecvTransport.prependListener('connect', () => ++connectEventNumTimesCalled);
|
|
490
|
+
const audioConsumer = await ctx.connectedRecvTransport.consume({
|
|
465
491
|
id: audioConsumerRemoteParameters.id,
|
|
466
492
|
producerId: audioConsumerRemoteParameters.producerId,
|
|
467
493
|
kind: audioConsumerRemoteParameters.kind,
|
|
468
494
|
rtpParameters: audioConsumerRemoteParameters.rtpParameters,
|
|
469
|
-
appData: { bar: 'BAR' }
|
|
495
|
+
appData: { bar: 'BAR' },
|
|
470
496
|
});
|
|
471
|
-
|
|
497
|
+
// 'connect' event should not have been called since it was in beforeEach already.
|
|
498
|
+
expect(connectEventNumTimesCalled).toBe(0);
|
|
472
499
|
expect(typeof audioConsumer).toBe('object');
|
|
473
500
|
expect(audioConsumer.id).toBe(audioConsumerRemoteParameters.id);
|
|
474
501
|
expect(audioConsumer.producerId).toBe(audioConsumerRemoteParameters.producerId);
|
|
@@ -484,13 +511,11 @@ test('transport.consume() succeeds', async () => {
|
|
|
484
511
|
payloadType: 100,
|
|
485
512
|
clockRate: 48000,
|
|
486
513
|
channels: 2,
|
|
487
|
-
rtcpFeedback: [
|
|
488
|
-
{ type: 'transport-cc', parameter: '' }
|
|
489
|
-
],
|
|
514
|
+
rtcpFeedback: [{ type: 'transport-cc', parameter: '' }],
|
|
490
515
|
parameters: {
|
|
491
516
|
useinbandfec: 1,
|
|
492
|
-
foo: 'bar'
|
|
493
|
-
}
|
|
517
|
+
foo: 'bar',
|
|
518
|
+
},
|
|
494
519
|
});
|
|
495
520
|
headerExtensions = audioConsumer.rtpParameters.headerExtensions;
|
|
496
521
|
expect(headerExtensions).toEqual([
|
|
@@ -498,20 +523,20 @@ test('transport.consume() succeeds', async () => {
|
|
|
498
523
|
uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
|
|
499
524
|
id: 1,
|
|
500
525
|
encrypt: false,
|
|
501
|
-
parameters: {}
|
|
526
|
+
parameters: {},
|
|
502
527
|
},
|
|
503
528
|
{
|
|
504
529
|
uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01',
|
|
505
530
|
id: 5,
|
|
506
531
|
encrypt: false,
|
|
507
|
-
parameters: {}
|
|
532
|
+
parameters: {},
|
|
508
533
|
},
|
|
509
534
|
{
|
|
510
535
|
uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level',
|
|
511
536
|
id: 10,
|
|
512
537
|
encrypt: false,
|
|
513
|
-
parameters: {}
|
|
514
|
-
}
|
|
538
|
+
parameters: {},
|
|
539
|
+
},
|
|
515
540
|
]);
|
|
516
541
|
encodings = audioConsumer.rtpParameters.encodings;
|
|
517
542
|
expect(Array.isArray(encodings)).toBe(true);
|
|
@@ -519,18 +544,18 @@ test('transport.consume() succeeds', async () => {
|
|
|
519
544
|
expect(typeof encodings?.[0]).toBe('object');
|
|
520
545
|
expect(Object.keys(encodings[0])).toEqual(['ssrc', 'dtx']);
|
|
521
546
|
expect(typeof encodings[0].ssrc).toBe('number');
|
|
522
|
-
rtcp =
|
|
547
|
+
rtcp = audioConsumer.rtpParameters.rtcp;
|
|
523
548
|
expect(typeof rtcp).toBe('object');
|
|
524
549
|
expect(typeof rtcp?.cname).toBe('string');
|
|
525
550
|
expect(audioConsumer.paused).toBe(false);
|
|
526
551
|
expect(audioConsumer.appData).toEqual({ bar: 'BAR' });
|
|
527
|
-
videoConsumer = await
|
|
552
|
+
const videoConsumer = await ctx.connectedRecvTransport.consume({
|
|
528
553
|
id: videoConsumerRemoteParameters.id,
|
|
529
554
|
producerId: videoConsumerRemoteParameters.producerId,
|
|
530
555
|
kind: videoConsumerRemoteParameters.kind,
|
|
531
|
-
rtpParameters: videoConsumerRemoteParameters.rtpParameters
|
|
556
|
+
rtpParameters: videoConsumerRemoteParameters.rtpParameters,
|
|
532
557
|
});
|
|
533
|
-
expect(connectEventNumTimesCalled).toBe(
|
|
558
|
+
expect(connectEventNumTimesCalled).toBe(0);
|
|
534
559
|
expect(typeof videoConsumer).toBe('object');
|
|
535
560
|
expect(videoConsumer.id).toBe(videoConsumerRemoteParameters.id);
|
|
536
561
|
expect(videoConsumer.producerId).toBe(videoConsumerRemoteParameters.producerId);
|
|
@@ -550,11 +575,11 @@ test('transport.consume() succeeds', async () => {
|
|
|
550
575
|
{ type: 'nack', parameter: 'pli' },
|
|
551
576
|
{ type: 'ccm', parameter: 'fir' },
|
|
552
577
|
{ type: 'goog-remb', parameter: '' },
|
|
553
|
-
{ type: 'transport-cc', parameter: '' }
|
|
578
|
+
{ type: 'transport-cc', parameter: '' },
|
|
554
579
|
],
|
|
555
580
|
parameters: {
|
|
556
|
-
'x-google-start-bitrate': 1500
|
|
557
|
-
}
|
|
581
|
+
'x-google-start-bitrate': 1500,
|
|
582
|
+
},
|
|
558
583
|
});
|
|
559
584
|
expect(codecs[1]).toEqual({
|
|
560
585
|
mimeType: 'video/rtx',
|
|
@@ -562,8 +587,8 @@ test('transport.consume() succeeds', async () => {
|
|
|
562
587
|
clockRate: 90000,
|
|
563
588
|
rtcpFeedback: [],
|
|
564
589
|
parameters: {
|
|
565
|
-
apt: 101
|
|
566
|
-
}
|
|
590
|
+
apt: 101,
|
|
591
|
+
},
|
|
567
592
|
});
|
|
568
593
|
headerExtensions = videoConsumer.rtpParameters.headerExtensions;
|
|
569
594
|
expect(headerExtensions).toEqual([
|
|
@@ -571,32 +596,32 @@ test('transport.consume() succeeds', async () => {
|
|
|
571
596
|
uri: 'urn:ietf:params:rtp-hdrext:sdes:mid',
|
|
572
597
|
id: 1,
|
|
573
598
|
encrypt: false,
|
|
574
|
-
parameters: {}
|
|
599
|
+
parameters: {},
|
|
575
600
|
},
|
|
576
601
|
{
|
|
577
602
|
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
578
603
|
id: 4,
|
|
579
604
|
encrypt: false,
|
|
580
|
-
parameters: {}
|
|
605
|
+
parameters: {},
|
|
581
606
|
},
|
|
582
607
|
{
|
|
583
608
|
uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01',
|
|
584
609
|
id: 5,
|
|
585
610
|
encrypt: false,
|
|
586
|
-
parameters: {}
|
|
611
|
+
parameters: {},
|
|
587
612
|
},
|
|
588
613
|
{
|
|
589
614
|
uri: 'urn:3gpp:video-orientation',
|
|
590
615
|
id: 11,
|
|
591
616
|
encrypt: false,
|
|
592
|
-
parameters: {}
|
|
617
|
+
parameters: {},
|
|
593
618
|
},
|
|
594
619
|
{
|
|
595
620
|
uri: 'urn:ietf:params:rtp-hdrext:toffset',
|
|
596
621
|
id: 12,
|
|
597
622
|
encrypt: false,
|
|
598
|
-
parameters: {}
|
|
599
|
-
}
|
|
623
|
+
parameters: {},
|
|
624
|
+
},
|
|
600
625
|
]);
|
|
601
626
|
encodings = videoConsumer.rtpParameters.encodings;
|
|
602
627
|
expect(Array.isArray(encodings)).toBe(true);
|
|
@@ -612,15 +637,19 @@ test('transport.consume() succeeds', async () => {
|
|
|
612
637
|
expect(typeof rtcp?.cname).toBe('string');
|
|
613
638
|
expect(videoConsumer.paused).toBe(false);
|
|
614
639
|
expect(videoConsumer.appData).toEqual({});
|
|
615
|
-
recvTransport.removeAllListeners('connect');
|
|
616
640
|
}, 500);
|
|
617
641
|
test('transport.consume() batches consumers created in same macrotask into the same task', async () => {
|
|
618
|
-
const videoConsumerRemoteParameters1 = fakeParameters.generateConsumerRemoteParameters({
|
|
619
|
-
|
|
620
|
-
|
|
642
|
+
const videoConsumerRemoteParameters1 = fakeParameters.generateConsumerRemoteParameters({
|
|
643
|
+
codecMimeType: 'video/VP8',
|
|
644
|
+
});
|
|
645
|
+
const videoConsumerRemoteParameters2 = fakeParameters.generateConsumerRemoteParameters({
|
|
646
|
+
codecMimeType: 'video/VP8',
|
|
647
|
+
});
|
|
648
|
+
// @ts-ignore
|
|
649
|
+
const pushSpy = jest.spyOn(ctx.connectedRecvTransport._awaitQueue, 'push');
|
|
621
650
|
const waitForConsumer = (id) => {
|
|
622
|
-
return new Promise(
|
|
623
|
-
|
|
651
|
+
return new Promise(resolve => {
|
|
652
|
+
ctx.connectedRecvTransport.observer.on('newconsumer', consumer => {
|
|
624
653
|
if (consumer.id === id) {
|
|
625
654
|
resolve();
|
|
626
655
|
}
|
|
@@ -629,114 +658,95 @@ test('transport.consume() batches consumers created in same macrotask into the s
|
|
|
629
658
|
};
|
|
630
659
|
const allConsumersCreated = Promise.all([
|
|
631
660
|
waitForConsumer(videoConsumerRemoteParameters1.id),
|
|
632
|
-
waitForConsumer(videoConsumerRemoteParameters2.id)
|
|
661
|
+
waitForConsumer(videoConsumerRemoteParameters2.id),
|
|
633
662
|
]);
|
|
634
663
|
await Promise.all([
|
|
635
|
-
|
|
664
|
+
ctx.connectedRecvTransport.consume({
|
|
636
665
|
id: videoConsumerRemoteParameters1.id,
|
|
637
666
|
producerId: videoConsumerRemoteParameters1.producerId,
|
|
638
667
|
kind: videoConsumerRemoteParameters1.kind,
|
|
639
|
-
rtpParameters: videoConsumerRemoteParameters1.rtpParameters
|
|
668
|
+
rtpParameters: videoConsumerRemoteParameters1.rtpParameters,
|
|
640
669
|
}),
|
|
641
|
-
|
|
670
|
+
ctx.connectedRecvTransport.consume({
|
|
642
671
|
id: videoConsumerRemoteParameters2.id,
|
|
643
672
|
producerId: videoConsumerRemoteParameters2.producerId,
|
|
644
673
|
kind: videoConsumerRemoteParameters2.kind,
|
|
645
|
-
rtpParameters: videoConsumerRemoteParameters2.rtpParameters
|
|
646
|
-
})
|
|
674
|
+
rtpParameters: videoConsumerRemoteParameters2.rtpParameters,
|
|
675
|
+
}),
|
|
647
676
|
]);
|
|
648
677
|
await allConsumersCreated;
|
|
649
678
|
expect(pushSpy).toBeCalledTimes(1);
|
|
650
679
|
}, 500);
|
|
651
680
|
test('transport.consume() without remote Consumer parameters rejects with TypeError', async () => {
|
|
652
681
|
// @ts-ignore
|
|
653
|
-
await expect(recvTransport.consume({}))
|
|
654
|
-
.rejects
|
|
655
|
-
.toThrow(TypeError);
|
|
682
|
+
await expect(ctx.recvTransport.consume({})).rejects.toThrow(TypeError);
|
|
656
683
|
}, 500);
|
|
657
684
|
test('transport.consume() with missing remote Consumer parameters rejects with TypeError', async () => {
|
|
658
685
|
// @ts-ignore
|
|
659
|
-
await expect(recvTransport.consume({ id: '1234' }))
|
|
660
|
-
|
|
661
|
-
.toThrow(TypeError);
|
|
686
|
+
await expect(ctx.recvTransport.consume({ id: '1234' })).rejects.toThrow(TypeError);
|
|
687
|
+
await expect(
|
|
662
688
|
// @ts-ignore
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
.toThrow(TypeError);
|
|
666
|
-
await expect(recvTransport.consume(
|
|
689
|
+
ctx.recvTransport.consume({ id: '1234', producerId: '4444' })).rejects.toThrow(TypeError);
|
|
690
|
+
await expect(ctx.recvTransport.consume(
|
|
667
691
|
// @ts-ignore
|
|
668
692
|
{
|
|
669
693
|
id: '1234',
|
|
670
694
|
producerId: '4444',
|
|
671
|
-
kind: 'audio'
|
|
672
|
-
}))
|
|
673
|
-
|
|
674
|
-
.toThrow(TypeError);
|
|
675
|
-
await expect(recvTransport.consume(
|
|
695
|
+
kind: 'audio',
|
|
696
|
+
})).rejects.toThrow(TypeError);
|
|
697
|
+
await expect(ctx.recvTransport.consume(
|
|
676
698
|
// @ts-ignore
|
|
677
699
|
{
|
|
678
700
|
id: '1234',
|
|
679
701
|
producerId: '4444',
|
|
680
|
-
kind: 'audio'
|
|
681
|
-
}))
|
|
682
|
-
.rejects
|
|
683
|
-
.toThrow(TypeError);
|
|
702
|
+
kind: 'audio',
|
|
703
|
+
})).rejects.toThrow(TypeError);
|
|
684
704
|
}, 500);
|
|
685
705
|
test('transport.consume() in a sending Transport rejects with UnsupportedError', async () => {
|
|
686
|
-
const { id, producerId, kind, rtpParameters } = fakeParameters.generateConsumerRemoteParameters({
|
|
687
|
-
|
|
706
|
+
const { id, producerId, kind, rtpParameters } = fakeParameters.generateConsumerRemoteParameters({
|
|
707
|
+
codecMimeType: 'audio/opus',
|
|
708
|
+
});
|
|
709
|
+
await expect(ctx.sendTransport.consume({
|
|
688
710
|
id,
|
|
689
711
|
producerId,
|
|
690
712
|
kind,
|
|
691
|
-
rtpParameters
|
|
692
|
-
}))
|
|
693
|
-
.rejects
|
|
694
|
-
.toThrow(errors_1.UnsupportedError);
|
|
713
|
+
rtpParameters,
|
|
714
|
+
})).rejects.toThrow(errors_1.UnsupportedError);
|
|
695
715
|
}, 500);
|
|
696
716
|
test('transport.consume() with unsupported rtpParameters rejects with UnsupportedError', async () => {
|
|
697
|
-
const { id, producerId, kind, rtpParameters } = fakeParameters.generateConsumerRemoteParameters({
|
|
698
|
-
|
|
717
|
+
const { id, producerId, kind, rtpParameters } = fakeParameters.generateConsumerRemoteParameters({
|
|
718
|
+
codecMimeType: 'audio/ISAC',
|
|
719
|
+
});
|
|
720
|
+
await expect(ctx.sendTransport.consume({
|
|
699
721
|
id,
|
|
700
722
|
producerId,
|
|
701
723
|
kind,
|
|
702
|
-
rtpParameters
|
|
703
|
-
}))
|
|
704
|
-
.rejects
|
|
705
|
-
.toThrow(errors_1.UnsupportedError);
|
|
724
|
+
rtpParameters,
|
|
725
|
+
})).rejects.toThrow(errors_1.UnsupportedError);
|
|
706
726
|
}, 500);
|
|
707
727
|
test('transport.consume() with a non object appData rejects with TypeError', async () => {
|
|
708
|
-
const consumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
728
|
+
const consumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
|
|
729
|
+
codecMimeType: 'audio/opus',
|
|
730
|
+
});
|
|
731
|
+
await expect(
|
|
709
732
|
// @ts-ignore
|
|
710
|
-
|
|
711
|
-
.rejects
|
|
712
|
-
.toThrow(TypeError);
|
|
733
|
+
ctx.recvTransport.consume({ consumerRemoteParameters, appData: true })).rejects.toThrow(TypeError);
|
|
713
734
|
}, 500);
|
|
714
735
|
test('transport.produceData() succeeds', async () => {
|
|
715
|
-
let dataProducerId;
|
|
716
736
|
let produceDataEventNumTimesCalled = 0;
|
|
717
|
-
|
|
718
|
-
sendTransport.on('producedata', ({ sctpStreamParameters, label, protocol, appData }, callback /* errback */) => {
|
|
737
|
+
ctx.connectedSendTransport.prependListener('producedata', () => {
|
|
719
738
|
produceDataEventNumTimesCalled++;
|
|
720
|
-
expect(typeof sctpStreamParameters).toBe('object');
|
|
721
|
-
expect(label).toBe('FOO');
|
|
722
|
-
expect(protocol).toBe('BAR');
|
|
723
|
-
expect(appData).toEqual({ foo: 'FOO' });
|
|
724
|
-
const id = fakeParameters.generateDataProducerRemoteParameters().id;
|
|
725
|
-
dataProducerId = id;
|
|
726
|
-
// Emulate communication with the server and success response with Producer
|
|
727
|
-
// remote parameters.
|
|
728
|
-
setTimeout(() => callback({ id }));
|
|
729
739
|
});
|
|
730
|
-
dataProducer = await
|
|
740
|
+
const dataProducer = await ctx.connectedSendTransport.produceData({
|
|
731
741
|
ordered: false,
|
|
732
742
|
maxPacketLifeTime: 5555,
|
|
733
743
|
label: 'FOO',
|
|
734
744
|
protocol: 'BAR',
|
|
735
|
-
appData: { foo: 'FOO' }
|
|
745
|
+
appData: { foo: 'FOO' },
|
|
736
746
|
});
|
|
737
747
|
expect(produceDataEventNumTimesCalled).toBe(1);
|
|
738
748
|
expect(typeof dataProducer).toBe('object');
|
|
739
|
-
expect(dataProducer.id).toBe(
|
|
749
|
+
expect(typeof dataProducer.id).toBe('string');
|
|
740
750
|
expect(dataProducer.closed).toBe(false);
|
|
741
751
|
expect(typeof dataProducer.sctpStreamParameters).toBe('object');
|
|
742
752
|
expect(typeof dataProducer.sctpStreamParameters.streamId).toBe('number');
|
|
@@ -745,28 +755,24 @@ test('transport.produceData() succeeds', async () => {
|
|
|
745
755
|
expect(dataProducer.sctpStreamParameters.maxRetransmits).toBe(undefined);
|
|
746
756
|
expect(dataProducer.label).toBe('FOO');
|
|
747
757
|
expect(dataProducer.protocol).toBe('BAR');
|
|
748
|
-
sendTransport.removeAllListeners('producedata');
|
|
749
758
|
}, 500);
|
|
750
759
|
test('transport.produceData() in a receiving Transport rejects with UnsupportedError', async () => {
|
|
751
|
-
await expect(recvTransport.produceData({}))
|
|
752
|
-
.rejects
|
|
753
|
-
.toThrow(errors_1.UnsupportedError);
|
|
760
|
+
await expect(ctx.recvTransport.produceData({})).rejects.toThrow(errors_1.UnsupportedError);
|
|
754
761
|
}, 500);
|
|
755
762
|
test('transport.produceData() with a non object appData rejects with TypeError', async () => {
|
|
763
|
+
await expect(
|
|
756
764
|
// @ts-ignore
|
|
757
|
-
|
|
758
|
-
.rejects
|
|
759
|
-
.toThrow(TypeError);
|
|
765
|
+
ctx.sendTransport.produceData({ appData: true })).rejects.toThrow(TypeError);
|
|
760
766
|
}, 500);
|
|
761
767
|
test('transport.consumeData() succeeds', async () => {
|
|
762
768
|
const dataConsumerRemoteParameters = fakeParameters.generateDataConsumerRemoteParameters();
|
|
763
|
-
dataConsumer = await
|
|
769
|
+
const dataConsumer = await ctx.connectedRecvTransport.consumeData({
|
|
764
770
|
id: dataConsumerRemoteParameters.id,
|
|
765
771
|
dataProducerId: dataConsumerRemoteParameters.dataProducerId,
|
|
766
772
|
sctpStreamParameters: dataConsumerRemoteParameters.sctpStreamParameters,
|
|
767
773
|
label: 'FOO',
|
|
768
774
|
protocol: 'BAR',
|
|
769
|
-
appData: { bar: 'BAR' }
|
|
775
|
+
appData: { bar: 'BAR' },
|
|
770
776
|
});
|
|
771
777
|
expect(typeof dataConsumer).toBe('object');
|
|
772
778
|
expect(dataConsumer.id).toBe(dataConsumerRemoteParameters.id);
|
|
@@ -779,66 +785,52 @@ test('transport.consumeData() succeeds', async () => {
|
|
|
779
785
|
}, 500);
|
|
780
786
|
test('transport.consumeData() without remote DataConsumer parameters rejects with TypeError', async () => {
|
|
781
787
|
// @ts-ignore
|
|
782
|
-
await expect(recvTransport.consumeData({}))
|
|
783
|
-
.rejects
|
|
784
|
-
.toThrow(TypeError);
|
|
788
|
+
await expect(ctx.recvTransport.consumeData({})).rejects.toThrow(TypeError);
|
|
785
789
|
}, 500);
|
|
786
790
|
test('transport.consumeData() with missing remote DataConsumer parameters rejects with TypeError', async () => {
|
|
787
791
|
// @ts-ignore
|
|
788
|
-
await expect(recvTransport.consumeData({ id: '1234' }))
|
|
789
|
-
|
|
790
|
-
.toThrow(TypeError);
|
|
792
|
+
await expect(ctx.recvTransport.consumeData({ id: '1234' })).rejects.toThrow(TypeError);
|
|
793
|
+
await expect(
|
|
791
794
|
// @ts-ignore
|
|
792
|
-
|
|
793
|
-
.rejects
|
|
794
|
-
.toThrow(TypeError);
|
|
795
|
+
ctx.recvTransport.consumeData({ id: '1234', dataProducerId: '4444' })).rejects.toThrow(TypeError);
|
|
795
796
|
}, 500);
|
|
796
797
|
test('transport.consumeData() in a sending Transport rejects with UnsupportedError', async () => {
|
|
797
798
|
const { id, dataProducerId, sctpStreamParameters } = fakeParameters.generateDataConsumerRemoteParameters();
|
|
798
|
-
await expect(sendTransport.consumeData({
|
|
799
|
+
await expect(ctx.sendTransport.consumeData({
|
|
799
800
|
id,
|
|
800
801
|
dataProducerId,
|
|
801
|
-
sctpStreamParameters
|
|
802
|
-
}))
|
|
803
|
-
.rejects
|
|
804
|
-
.toThrow(errors_1.UnsupportedError);
|
|
802
|
+
sctpStreamParameters,
|
|
803
|
+
})).rejects.toThrow(errors_1.UnsupportedError);
|
|
805
804
|
}, 500);
|
|
806
805
|
test('transport.consumeData() with a non object appData rejects with TypeError', async () => {
|
|
807
806
|
const dataConsumerRemoteParameters = fakeParameters.generateDataConsumerRemoteParameters();
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
807
|
+
await expect(ctx.recvTransport.consumeData({
|
|
808
|
+
dataConsumerRemoteParameters,
|
|
809
|
+
// @ts-ignore
|
|
810
|
+
appData: true,
|
|
811
|
+
})).rejects.toThrow(TypeError);
|
|
812
812
|
}, 500);
|
|
813
813
|
test('transport.getStats() succeeds', async () => {
|
|
814
|
-
const stats = await sendTransport.getStats();
|
|
814
|
+
const stats = await ctx.sendTransport.getStats();
|
|
815
815
|
expect(typeof stats).toBe('object');
|
|
816
816
|
}, 500);
|
|
817
817
|
test('transport.restartIce() succeeds', async () => {
|
|
818
|
-
await expect(sendTransport.restartIce({
|
|
818
|
+
await expect(ctx.sendTransport.restartIce({
|
|
819
819
|
iceParameters: {
|
|
820
820
|
usernameFragment: 'foo',
|
|
821
|
-
password: 'xxx'
|
|
822
|
-
}
|
|
823
|
-
}))
|
|
824
|
-
.resolves
|
|
825
|
-
.toBe(undefined);
|
|
821
|
+
password: 'xxx',
|
|
822
|
+
},
|
|
823
|
+
})).resolves.toBe(undefined);
|
|
826
824
|
}, 500);
|
|
827
825
|
test('transport.restartIce() without remote iceParameters rejects with TypeError', async () => {
|
|
828
826
|
// @ts-ignore
|
|
829
|
-
await expect(sendTransport.restartIce({}))
|
|
830
|
-
.rejects
|
|
831
|
-
.toThrow(TypeError);
|
|
827
|
+
await expect(ctx.sendTransport.restartIce({})).rejects.toThrow(TypeError);
|
|
832
828
|
}, 500);
|
|
833
829
|
test('transport.updateIceServers() succeeds', async () => {
|
|
834
|
-
await expect(sendTransport.updateIceServers({ iceServers: [] }))
|
|
835
|
-
.resolves
|
|
836
|
-
.toBe(undefined);
|
|
830
|
+
await expect(ctx.sendTransport.updateIceServers({ iceServers: [] })).resolves.toBe(undefined);
|
|
837
831
|
}, 500);
|
|
838
832
|
test('transport.updateIceServers() without iceServers rejects with TypeError', async () => {
|
|
839
|
-
await expect(sendTransport.updateIceServers({}))
|
|
840
|
-
.rejects
|
|
841
|
-
.toThrow(TypeError);
|
|
833
|
+
await expect(ctx.sendTransport.updateIceServers({})).rejects.toThrow(TypeError);
|
|
842
834
|
}, 500);
|
|
843
835
|
test('ICE gathering state change fires "icegatheringstatechange" in live Transport', () => {
|
|
844
836
|
// NOTE: These tests are a bit flaky and we should isolate them. FakeHandler
|
|
@@ -846,341 +838,284 @@ test('ICE gathering state change fires "icegatheringstatechange" in live Transpo
|
|
|
846
838
|
// private setupTransport() method is called (which has happens many times in
|
|
847
839
|
// tests above already). So here we have to reset it manually to test things.
|
|
848
840
|
// @ts-ignore
|
|
849
|
-
sendTransport.handler.setIceGatheringState('new');
|
|
841
|
+
ctx.sendTransport.handler.setIceGatheringState('new');
|
|
850
842
|
// @ts-ignore
|
|
851
|
-
sendTransport.handler.setConnectionState('new');
|
|
843
|
+
ctx.sendTransport.handler.setConnectionState('new');
|
|
852
844
|
let iceGatheringStateChangeEventNumTimesCalled = 0;
|
|
853
845
|
let connectionStateChangeEventNumTimesCalled = 0;
|
|
854
|
-
sendTransport.on('icegatheringstatechange',
|
|
846
|
+
ctx.sendTransport.on('icegatheringstatechange', iceGatheringState => {
|
|
855
847
|
iceGatheringStateChangeEventNumTimesCalled++;
|
|
856
848
|
expect(iceGatheringState).toBe('complete');
|
|
857
|
-
expect(sendTransport.iceGatheringState).toBe('complete');
|
|
858
|
-
expect(sendTransport.connectionState).toBe('new');
|
|
849
|
+
expect(ctx.sendTransport.iceGatheringState).toBe('complete');
|
|
850
|
+
expect(ctx.sendTransport.connectionState).toBe('new');
|
|
859
851
|
});
|
|
860
852
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
861
|
-
sendTransport.on('connectionstatechange',
|
|
853
|
+
ctx.sendTransport.on('connectionstatechange', connectionState => {
|
|
862
854
|
connectionStateChangeEventNumTimesCalled++;
|
|
863
855
|
});
|
|
864
856
|
// @ts-ignore
|
|
865
|
-
sendTransport.handler.setIceGatheringState('complete');
|
|
857
|
+
ctx.sendTransport.handler.setIceGatheringState('complete');
|
|
866
858
|
expect(iceGatheringStateChangeEventNumTimesCalled).toBe(1);
|
|
867
859
|
expect(connectionStateChangeEventNumTimesCalled).toBe(0);
|
|
868
|
-
expect(sendTransport.iceGatheringState).toBe('complete');
|
|
869
|
-
expect(sendTransport.connectionState).toBe('new');
|
|
870
|
-
sendTransport.removeAllListeners('icegatheringstatechange');
|
|
871
|
-
sendTransport.removeAllListeners('connectionstatechange');
|
|
860
|
+
expect(ctx.sendTransport.iceGatheringState).toBe('complete');
|
|
861
|
+
expect(ctx.sendTransport.connectionState).toBe('new');
|
|
872
862
|
});
|
|
873
863
|
test('connection state change fires "connectionstatechange" in live Transport', () => {
|
|
874
864
|
let connectionStateChangeEventNumTimesCalled = 0;
|
|
875
|
-
sendTransport.on('connectionstatechange',
|
|
865
|
+
ctx.sendTransport.on('connectionstatechange', connectionState => {
|
|
876
866
|
connectionStateChangeEventNumTimesCalled++;
|
|
877
867
|
expect(connectionState).toBe('completed');
|
|
878
868
|
});
|
|
879
869
|
// @ts-ignore
|
|
880
|
-
sendTransport.handler.setConnectionState('completed');
|
|
870
|
+
ctx.sendTransport.handler.setConnectionState('completed');
|
|
881
871
|
expect(connectionStateChangeEventNumTimesCalled).toBe(1);
|
|
882
|
-
expect(sendTransport.connectionState).toBe('completed');
|
|
883
|
-
sendTransport.removeAllListeners('connectionstatechange');
|
|
872
|
+
expect(ctx.sendTransport.connectionState).toBe('completed');
|
|
884
873
|
});
|
|
885
874
|
test('producer.pause() succeeds', () => {
|
|
886
|
-
videoProducer.pause();
|
|
887
|
-
expect(videoProducer.paused).toBe(true);
|
|
888
|
-
|
|
889
|
-
expect(videoProducer.track?.enabled).toBe(true);
|
|
875
|
+
ctx.videoProducer.pause();
|
|
876
|
+
expect(ctx.videoProducer.paused).toBe(true);
|
|
877
|
+
expect(ctx.videoProducer.track?.enabled).toBe(false);
|
|
890
878
|
});
|
|
891
879
|
test('producer.resume() succeeds', () => {
|
|
892
|
-
videoProducer.resume();
|
|
893
|
-
expect(videoProducer.paused).toBe(false);
|
|
894
|
-
expect(videoProducer.track?.enabled).toBe(true);
|
|
880
|
+
ctx.videoProducer.resume();
|
|
881
|
+
expect(ctx.videoProducer.paused).toBe(false);
|
|
882
|
+
expect(ctx.videoProducer.track?.enabled).toBe(true);
|
|
895
883
|
});
|
|
896
884
|
test('producer.replaceTrack() with a new track succeeds', async () => {
|
|
897
885
|
// Have the audio Producer paused.
|
|
898
|
-
audioProducer.pause();
|
|
899
|
-
const audioProducerPreviousTrack = audioProducer.track;
|
|
886
|
+
ctx.audioProducer.pause();
|
|
887
|
+
const audioProducerPreviousTrack = ctx.audioProducer.track;
|
|
900
888
|
const newAudioTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
901
|
-
await expect(audioProducer.replaceTrack({ track: newAudioTrack }))
|
|
902
|
-
.resolves
|
|
903
|
-
.toBe(undefined);
|
|
889
|
+
await expect(ctx.audioProducer.replaceTrack({ track: newAudioTrack })).resolves.toBe(undefined);
|
|
904
890
|
// Previous track must be 'live' due to stopTracks: false.
|
|
905
891
|
expect(audioProducerPreviousTrack?.readyState).toBe('live');
|
|
906
|
-
expect(audioProducer.track?.readyState).toBe('live');
|
|
907
|
-
expect(audioProducer.track).not.toBe(audioProducerPreviousTrack);
|
|
908
|
-
expect(audioProducer.track).toBe(newAudioTrack);
|
|
892
|
+
expect(ctx.audioProducer.track?.readyState).toBe('live');
|
|
893
|
+
expect(ctx.audioProducer.track).not.toBe(audioProducerPreviousTrack);
|
|
894
|
+
expect(ctx.audioProducer.track).toBe(newAudioTrack);
|
|
909
895
|
// Producer was already paused.
|
|
910
|
-
expect(audioProducer.paused).toBe(true);
|
|
896
|
+
expect(ctx.audioProducer.paused).toBe(true);
|
|
911
897
|
// Reset the audio paused state.
|
|
912
|
-
audioProducer.resume();
|
|
913
|
-
const videoProducerPreviousTrack = videoProducer.track;
|
|
898
|
+
ctx.audioProducer.resume();
|
|
899
|
+
const videoProducerPreviousTrack = ctx.videoProducer.track;
|
|
914
900
|
const newVideoTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'video' });
|
|
915
|
-
await expect(videoProducer.replaceTrack({ track: newVideoTrack }))
|
|
916
|
-
.resolves
|
|
917
|
-
.toBe(undefined);
|
|
901
|
+
await expect(ctx.videoProducer.replaceTrack({ track: newVideoTrack })).resolves.toBe(undefined);
|
|
918
902
|
// Previous track must be 'ended' due to stopTracks: true.
|
|
919
903
|
expect(videoProducerPreviousTrack?.readyState).toBe('ended');
|
|
920
|
-
expect(videoProducer.track).not.toBe(videoProducerPreviousTrack);
|
|
921
|
-
expect(videoProducer.track).toBe(newVideoTrack);
|
|
922
|
-
expect(videoProducer.paused).toBe(false);
|
|
904
|
+
expect(ctx.videoProducer.track).not.toBe(videoProducerPreviousTrack);
|
|
905
|
+
expect(ctx.videoProducer.track).toBe(newVideoTrack);
|
|
906
|
+
expect(ctx.videoProducer.paused).toBe(false);
|
|
923
907
|
}, 500);
|
|
924
908
|
test('producer.replaceTrack() with null succeeds', async () => {
|
|
925
909
|
// Have the audio Producer paused.
|
|
926
|
-
audioProducer.pause();
|
|
927
|
-
const audioProducerPreviousTrack = audioProducer.track;
|
|
928
|
-
await expect(audioProducer.replaceTrack({ track: null }))
|
|
929
|
-
.resolves
|
|
930
|
-
.toBe(undefined);
|
|
910
|
+
ctx.audioProducer.pause();
|
|
911
|
+
const audioProducerPreviousTrack = ctx.audioProducer.track;
|
|
912
|
+
await expect(ctx.audioProducer.replaceTrack({ track: null })).resolves.toBe(undefined);
|
|
931
913
|
// Previous track must be 'live' due to stopTracks: false.
|
|
932
914
|
expect(audioProducerPreviousTrack?.readyState).toBe('live');
|
|
933
|
-
expect(audioProducer.track).toBeNull();
|
|
915
|
+
expect(ctx.audioProducer.track).toBeNull();
|
|
934
916
|
// Producer was already paused.
|
|
935
|
-
expect(audioProducer.paused).toBe(true);
|
|
917
|
+
expect(ctx.audioProducer.paused).toBe(true);
|
|
936
918
|
// Reset the audio paused state.
|
|
937
|
-
audioProducer.resume();
|
|
938
|
-
expect(audioProducer.paused).toBe(false);
|
|
919
|
+
ctx.audioProducer.resume();
|
|
920
|
+
expect(ctx.audioProducer.paused).toBe(false);
|
|
939
921
|
// Manually "mute" the original audio track.
|
|
940
922
|
audioProducerPreviousTrack.enabled = false;
|
|
941
923
|
// Set the original audio track back.
|
|
942
|
-
await expect(audioProducer.replaceTrack({ track: audioProducerPreviousTrack }))
|
|
943
|
-
.resolves
|
|
944
|
-
.toBe(undefined);
|
|
924
|
+
await expect(ctx.audioProducer.replaceTrack({ track: audioProducerPreviousTrack })).resolves.toBe(undefined);
|
|
945
925
|
// The given audio track was muted but the Producer was not, so the track
|
|
946
926
|
// must not be muted now.
|
|
947
|
-
expect(audioProducer.paused).toBe(false);
|
|
927
|
+
expect(ctx.audioProducer.paused).toBe(false);
|
|
948
928
|
expect(audioProducerPreviousTrack?.enabled).toBe(true);
|
|
949
929
|
// Reset the audio paused state.
|
|
950
|
-
audioProducer.resume();
|
|
930
|
+
ctx.audioProducer.resume();
|
|
951
931
|
}, 500);
|
|
952
932
|
test('producer.replaceTrack() with an ended track rejects with InvalidStateError', async () => {
|
|
953
933
|
const track = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
954
934
|
track.stop();
|
|
955
|
-
await expect(videoProducer.replaceTrack({ track }))
|
|
956
|
-
.rejects
|
|
957
|
-
.toThrow(errors_1.InvalidStateError);
|
|
935
|
+
await expect(ctx.videoProducer.replaceTrack({ track })).rejects.toThrow(errors_1.InvalidStateError);
|
|
958
936
|
expect(track.readyState).toBe('ended');
|
|
959
|
-
expect(videoProducer.track?.readyState).toBe('live');
|
|
937
|
+
expect(ctx.videoProducer.track?.readyState).toBe('live');
|
|
960
938
|
}, 500);
|
|
961
939
|
test('producer.replaceTrack() with the same track succeeds', async () => {
|
|
962
|
-
await expect(audioProducer.replaceTrack({ track: audioProducer.track }))
|
|
963
|
-
|
|
964
|
-
.toBe(undefined);
|
|
965
|
-
expect(audioProducer.track?.readyState).toBe('live');
|
|
940
|
+
await expect(ctx.audioProducer.replaceTrack({ track: ctx.audioProducer.track })).resolves.toBe(undefined);
|
|
941
|
+
expect(ctx.audioProducer.track?.readyState).toBe('live');
|
|
966
942
|
}, 500);
|
|
967
943
|
test('producer.setMaxSpatialLayer() succeeds', async () => {
|
|
968
|
-
await expect(videoProducer.setMaxSpatialLayer(0))
|
|
969
|
-
|
|
970
|
-
.toBe(undefined);
|
|
971
|
-
expect(videoProducer.maxSpatialLayer).toBe(0);
|
|
944
|
+
await expect(ctx.videoProducer.setMaxSpatialLayer(0)).resolves.toBe(undefined);
|
|
945
|
+
expect(ctx.videoProducer.maxSpatialLayer).toBe(0);
|
|
972
946
|
}, 500);
|
|
973
947
|
test('producer.setMaxSpatialLayer() in an audio Producer rejects with UnsupportedError', async () => {
|
|
974
|
-
await expect(audioProducer.setMaxSpatialLayer(1))
|
|
975
|
-
|
|
976
|
-
.toThrow(errors_1.UnsupportedError);
|
|
977
|
-
expect(audioProducer.maxSpatialLayer).toBe(undefined);
|
|
948
|
+
await expect(ctx.audioProducer.setMaxSpatialLayer(1)).rejects.toThrow(errors_1.UnsupportedError);
|
|
949
|
+
expect(ctx.audioProducer.maxSpatialLayer).toBe(undefined);
|
|
978
950
|
}, 500);
|
|
979
951
|
test('producer.setMaxSpatialLayer() with invalid spatialLayer rejects with TypeError', async () => {
|
|
952
|
+
await expect(
|
|
980
953
|
// @ts-ignore
|
|
981
|
-
|
|
982
|
-
.rejects
|
|
983
|
-
.toThrow(TypeError);
|
|
954
|
+
ctx.videoProducer.setMaxSpatialLayer('chicken')).rejects.toThrow(TypeError);
|
|
984
955
|
}, 500);
|
|
985
956
|
test('producer.setMaxSpatialLayer() without spatialLayer rejects with TypeError', async () => {
|
|
986
957
|
// @ts-ignore
|
|
987
|
-
await expect(videoProducer.setMaxSpatialLayer())
|
|
988
|
-
.rejects
|
|
989
|
-
.toThrow(TypeError);
|
|
958
|
+
await expect(ctx.videoProducer.setMaxSpatialLayer()).rejects.toThrow(TypeError);
|
|
990
959
|
}, 500);
|
|
991
960
|
test('producer.setRtpEncodingParameters() succeeds', async () => {
|
|
992
|
-
await expect(videoProducer.setRtpEncodingParameters({ scaleResolutionDownBy: 2 }))
|
|
993
|
-
.resolves
|
|
994
|
-
.toBe(undefined);
|
|
995
|
-
expect(videoProducer.maxSpatialLayer).toBe(0);
|
|
961
|
+
await expect(ctx.videoProducer.setRtpEncodingParameters({ scaleResolutionDownBy: 2 })).resolves.toBe(undefined);
|
|
996
962
|
}, 500);
|
|
997
963
|
test('producer.getStats() succeeds', async () => {
|
|
998
|
-
const stats = await videoProducer.getStats();
|
|
964
|
+
const stats = await ctx.videoProducer.getStats();
|
|
999
965
|
expect(typeof stats).toBe('object');
|
|
1000
966
|
}, 500);
|
|
1001
967
|
test('consumer.resume() succeeds', () => {
|
|
1002
|
-
videoConsumer.resume();
|
|
1003
|
-
expect(videoConsumer.paused).toBe(false);
|
|
968
|
+
ctx.videoConsumer.resume();
|
|
969
|
+
expect(ctx.videoConsumer.paused).toBe(false);
|
|
1004
970
|
});
|
|
1005
971
|
test('consumer.pause() succeeds', () => {
|
|
1006
|
-
videoConsumer.pause();
|
|
1007
|
-
expect(videoConsumer.paused).toBe(true);
|
|
972
|
+
ctx.videoConsumer.pause();
|
|
973
|
+
expect(ctx.videoConsumer.paused).toBe(true);
|
|
1008
974
|
});
|
|
1009
975
|
test('consumer.getStats() succeeds', async () => {
|
|
1010
|
-
const stats = await videoConsumer.getStats();
|
|
976
|
+
const stats = await ctx.videoConsumer.getStats();
|
|
1011
977
|
expect(typeof stats).toBe('object');
|
|
1012
978
|
}, 500);
|
|
1013
979
|
test('producer.close() succeed', () => {
|
|
1014
|
-
audioProducer.close();
|
|
1015
|
-
expect(audioProducer.closed).toBe(true);
|
|
980
|
+
ctx.audioProducer.close();
|
|
981
|
+
expect(ctx.audioProducer.closed).toBe(true);
|
|
1016
982
|
// Track will be still 'live' due to stopTracks: false.
|
|
1017
|
-
expect(audioProducer.track?.readyState).toBe('live');
|
|
983
|
+
expect(ctx.audioProducer.track?.readyState).toBe('live');
|
|
1018
984
|
});
|
|
1019
985
|
test('producer.replaceTrack() rejects with InvalidStateError if closed', async () => {
|
|
1020
986
|
const audioTrack = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
.toThrow(errors_1.InvalidStateError);
|
|
987
|
+
ctx.audioProducer.close();
|
|
988
|
+
await expect(ctx.audioProducer.replaceTrack({ track: audioTrack })).rejects.toThrow(errors_1.InvalidStateError);
|
|
1024
989
|
expect(audioTrack.readyState).toBe('live');
|
|
1025
990
|
}, 500);
|
|
1026
991
|
test('producer.getStats() rejects with InvalidStateError if closed', async () => {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
.toThrow(errors_1.InvalidStateError);
|
|
992
|
+
ctx.audioProducer.close();
|
|
993
|
+
await expect(ctx.audioProducer.getStats()).rejects.toThrow(errors_1.InvalidStateError);
|
|
1030
994
|
}, 500);
|
|
1031
995
|
test('consumer.close() succeed', () => {
|
|
1032
|
-
audioConsumer.close();
|
|
1033
|
-
expect(audioConsumer.closed).toBe(true);
|
|
1034
|
-
expect(audioConsumer.track.readyState).toBe('ended');
|
|
996
|
+
ctx.audioConsumer.close();
|
|
997
|
+
expect(ctx.audioConsumer.closed).toBe(true);
|
|
998
|
+
expect(ctx.audioConsumer.track.readyState).toBe('ended');
|
|
1035
999
|
});
|
|
1036
1000
|
test('consumer.getStats() rejects with InvalidStateError if closed', async () => {
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1001
|
+
ctx.audioConsumer.close();
|
|
1002
|
+
await expect(ctx.audioConsumer.getStats()).rejects.toThrow(errors_1.InvalidStateError);
|
|
1040
1003
|
}, 500);
|
|
1041
1004
|
test('dataProducer.close() succeed', () => {
|
|
1042
|
-
dataProducer.close();
|
|
1043
|
-
expect(dataProducer.closed).toBe(true);
|
|
1005
|
+
ctx.dataProducer.close();
|
|
1006
|
+
expect(ctx.dataProducer.closed).toBe(true);
|
|
1044
1007
|
});
|
|
1045
1008
|
test('dataConsumer.close() succeed', () => {
|
|
1046
|
-
dataConsumer.close();
|
|
1047
|
-
expect(dataConsumer.closed).toBe(true);
|
|
1009
|
+
ctx.dataConsumer.close();
|
|
1010
|
+
expect(ctx.dataConsumer.closed).toBe(true);
|
|
1048
1011
|
});
|
|
1049
1012
|
test('remotetely stopped track fires "trackended" in live Producers/Consumers', () => {
|
|
1050
1013
|
let audioProducerTrackendedEventCalled = false;
|
|
1051
1014
|
let videoProducerTrackendedEventCalled = false;
|
|
1052
1015
|
let audiosConsumerTrackendedEventCalled = false;
|
|
1053
1016
|
let videoConsumerTrackendedEventCalled = false;
|
|
1054
|
-
audioProducer.on('trackended', () => {
|
|
1017
|
+
ctx.audioProducer.on('trackended', () => {
|
|
1055
1018
|
audioProducerTrackendedEventCalled = true;
|
|
1056
1019
|
});
|
|
1057
|
-
videoProducer.on('trackended', () => {
|
|
1020
|
+
ctx.videoProducer.on('trackended', () => {
|
|
1058
1021
|
videoProducerTrackendedEventCalled = true;
|
|
1059
1022
|
});
|
|
1060
|
-
audioConsumer.on('trackended', () => {
|
|
1023
|
+
ctx.audioConsumer.on('trackended', () => {
|
|
1061
1024
|
audiosConsumerTrackendedEventCalled = true;
|
|
1062
1025
|
});
|
|
1063
|
-
videoConsumer.on('trackended', () => {
|
|
1026
|
+
ctx.videoConsumer.on('trackended', () => {
|
|
1064
1027
|
videoConsumerTrackendedEventCalled = true;
|
|
1065
1028
|
});
|
|
1066
1029
|
// @ts-ignore
|
|
1067
|
-
audioProducer.track.remoteStop();
|
|
1068
|
-
|
|
1069
|
-
|
|
1030
|
+
ctx.audioProducer.track.remoteStop();
|
|
1031
|
+
expect(audioProducerTrackendedEventCalled).toBe(true);
|
|
1032
|
+
// Let's close the video producer.
|
|
1033
|
+
ctx.videoProducer.close();
|
|
1070
1034
|
// @ts-ignore
|
|
1071
|
-
videoProducer.track.remoteStop();
|
|
1072
|
-
expect(videoProducerTrackendedEventCalled).toBe(
|
|
1035
|
+
ctx.videoProducer.track.remoteStop();
|
|
1036
|
+
expect(videoProducerTrackendedEventCalled).toBe(false);
|
|
1073
1037
|
// @ts-ignore
|
|
1074
|
-
audioConsumer.track.remoteStop();
|
|
1075
|
-
|
|
1076
|
-
expect(audiosConsumerTrackendedEventCalled).toBe(false);
|
|
1038
|
+
ctx.audioConsumer.track.remoteStop();
|
|
1039
|
+
expect(audiosConsumerTrackendedEventCalled).toBe(true);
|
|
1077
1040
|
// @ts-ignore
|
|
1078
|
-
videoConsumer.track.remoteStop();
|
|
1041
|
+
ctx.videoConsumer.track.remoteStop();
|
|
1079
1042
|
expect(videoConsumerTrackendedEventCalled).toBe(true);
|
|
1080
|
-
audioProducer.removeAllListeners();
|
|
1081
|
-
videoProducer.removeAllListeners();
|
|
1082
|
-
audioConsumer.removeAllListeners();
|
|
1083
|
-
videoConsumer.removeAllListeners();
|
|
1084
1043
|
});
|
|
1085
1044
|
test('transport.close() fires "transportclose" in live Producers/Consumers', () => {
|
|
1086
1045
|
let audioProducerTransportcloseEventCalled = false;
|
|
1087
1046
|
let videoProducerTransportcloseEventCalled = false;
|
|
1088
1047
|
let audioConsumerTransportcloseEventCalled = false;
|
|
1089
1048
|
let videoConsumerTransportcloseEventCalled = false;
|
|
1090
|
-
audioProducer.on('transportclose', () => {
|
|
1049
|
+
ctx.audioProducer.on('transportclose', () => {
|
|
1091
1050
|
audioProducerTransportcloseEventCalled = true;
|
|
1092
1051
|
});
|
|
1093
|
-
videoProducer.on('transportclose', () => {
|
|
1052
|
+
ctx.videoProducer.on('transportclose', () => {
|
|
1094
1053
|
videoProducerTransportcloseEventCalled = true;
|
|
1095
1054
|
});
|
|
1096
|
-
audioConsumer.on('transportclose', () => {
|
|
1055
|
+
ctx.audioConsumer.on('transportclose', () => {
|
|
1097
1056
|
audioConsumerTransportcloseEventCalled = true;
|
|
1098
1057
|
});
|
|
1099
|
-
videoConsumer.on('transportclose', () => {
|
|
1058
|
+
ctx.videoConsumer.on('transportclose', () => {
|
|
1100
1059
|
videoConsumerTransportcloseEventCalled = true;
|
|
1101
1060
|
});
|
|
1102
|
-
|
|
1103
|
-
expect(
|
|
1104
|
-
expect(videoProducer.closed).toBe(
|
|
1105
|
-
|
|
1106
|
-
expect(sendTransport.closed).toBe(true);
|
|
1107
|
-
expect(videoProducer.closed).toBe(true);
|
|
1108
|
-
// Audio Producer was already closed.
|
|
1109
|
-
expect(audioProducerTransportcloseEventCalled).toBe(false);
|
|
1061
|
+
ctx.connectedSendTransport.close();
|
|
1062
|
+
expect(ctx.connectedSendTransport.closed).toBe(true);
|
|
1063
|
+
expect(ctx.videoProducer.closed).toBe(true);
|
|
1064
|
+
expect(audioProducerTransportcloseEventCalled).toBe(true);
|
|
1110
1065
|
expect(videoProducerTransportcloseEventCalled).toBe(true);
|
|
1111
|
-
//
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
expect(
|
|
1116
|
-
expect(
|
|
1117
|
-
|
|
1118
|
-
expect(audioConsumerTransportcloseEventCalled).toBe(false);
|
|
1119
|
-
expect(videoConsumerTransportcloseEventCalled).toBe(true);
|
|
1120
|
-
audioProducer.removeAllListeners();
|
|
1121
|
-
videoProducer.removeAllListeners();
|
|
1122
|
-
audioConsumer.removeAllListeners();
|
|
1123
|
-
videoConsumer.removeAllListeners();
|
|
1066
|
+
// Let's close the video consumer.
|
|
1067
|
+
ctx.videoConsumer.close();
|
|
1068
|
+
ctx.connectedRecvTransport.close();
|
|
1069
|
+
expect(ctx.connectedRecvTransport.closed).toBe(true);
|
|
1070
|
+
expect(ctx.videoConsumer.closed).toBe(true);
|
|
1071
|
+
expect(audioConsumerTransportcloseEventCalled).toBe(true);
|
|
1072
|
+
expect(videoConsumerTransportcloseEventCalled).toBe(false);
|
|
1124
1073
|
});
|
|
1125
1074
|
test('transport.produce() rejects with InvalidStateError if closed', async () => {
|
|
1126
1075
|
const track = new fake_mediastreamtrack_1.FakeMediaStreamTrack({ kind: 'audio' });
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
await expect(sendTransport.produce({ track, stopTracks: false }))
|
|
1130
|
-
.rejects
|
|
1131
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1076
|
+
ctx.connectedSendTransport.close();
|
|
1077
|
+
await expect(ctx.connectedSendTransport.produce({ track, stopTracks: false })).rejects.toThrow(errors_1.InvalidStateError);
|
|
1132
1078
|
// The track must be 'live' due to stopTracks: false.
|
|
1133
1079
|
expect(track.readyState).toBe('live');
|
|
1134
|
-
sendTransport.removeAllListeners('produce');
|
|
1135
1080
|
}, 500);
|
|
1136
1081
|
test('transport.consume() rejects with InvalidStateError if closed', async () => {
|
|
1082
|
+
ctx.connectedRecvTransport.close();
|
|
1137
1083
|
// @ts-ignore
|
|
1138
|
-
await expect(
|
|
1139
|
-
.rejects
|
|
1140
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1141
|
-
recvTransport.removeAllListeners();
|
|
1084
|
+
await expect(ctx.connectedRecvTransport.consume({})).rejects.toThrow(errors_1.InvalidStateError);
|
|
1142
1085
|
}, 500);
|
|
1143
1086
|
test('transport.produceData() rejects with InvalidStateError if closed', async () => {
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
await expect(sendTransport.produceData({}))
|
|
1147
|
-
.rejects
|
|
1148
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1149
|
-
sendTransport.removeAllListeners('producedata');
|
|
1087
|
+
ctx.connectedSendTransport.close();
|
|
1088
|
+
await expect(ctx.connectedSendTransport.produceData({})).rejects.toThrow(errors_1.InvalidStateError);
|
|
1150
1089
|
}, 500);
|
|
1151
1090
|
test('transport.consumeData() rejects with InvalidStateError if closed', async () => {
|
|
1091
|
+
ctx.connectedRecvTransport.close();
|
|
1152
1092
|
// @ts-ignore
|
|
1153
|
-
await expect(
|
|
1154
|
-
.rejects
|
|
1155
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1093
|
+
await expect(ctx.connectedRecvTransport.consumeData({})).rejects.toThrow(errors_1.InvalidStateError);
|
|
1156
1094
|
}, 500);
|
|
1157
1095
|
test('transport.getStats() rejects with InvalidStateError if closed', async () => {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1096
|
+
ctx.connectedSendTransport.close();
|
|
1097
|
+
await expect(ctx.connectedSendTransport.getStats()).rejects.toThrow(errors_1.InvalidStateError);
|
|
1161
1098
|
}, 500);
|
|
1162
1099
|
test('transport.restartIce() rejects with InvalidStateError if closed', async () => {
|
|
1100
|
+
ctx.connectedSendTransport.close();
|
|
1101
|
+
await expect(
|
|
1163
1102
|
// @ts-ignore
|
|
1164
|
-
|
|
1165
|
-
.rejects
|
|
1166
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1103
|
+
ctx.connectedSendTransport.restartIce({ ieParameters: {} })).rejects.toThrow(errors_1.InvalidStateError);
|
|
1167
1104
|
}, 500);
|
|
1168
1105
|
test('transport.updateIceServers() rejects with InvalidStateError if closed', async () => {
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
.toThrow(errors_1.InvalidStateError);
|
|
1106
|
+
ctx.connectedSendTransport.close();
|
|
1107
|
+
await expect(ctx.connectedSendTransport.updateIceServers({ iceServers: [] })).rejects.toThrow(errors_1.InvalidStateError);
|
|
1172
1108
|
}, 500);
|
|
1173
1109
|
test('connection state change does not fire "connectionstatechange" in closed Transport', () => {
|
|
1174
1110
|
let connectionStateChangeEventNumTimesCalled = 0;
|
|
1175
|
-
|
|
1176
|
-
sendTransport.on('connectionstatechange', ( /* connectionState */) => {
|
|
1111
|
+
ctx.connectedSendTransport.on('connectionstatechange', ( /* connectionState */) => {
|
|
1177
1112
|
connectionStateChangeEventNumTimesCalled++;
|
|
1178
1113
|
});
|
|
1114
|
+
ctx.connectedSendTransport.close();
|
|
1179
1115
|
// @ts-ignore
|
|
1180
|
-
|
|
1116
|
+
ctx.connectedSendTransport.handler.setConnectionState('disconnected');
|
|
1181
1117
|
expect(connectionStateChangeEventNumTimesCalled).toBe(0);
|
|
1182
|
-
expect(
|
|
1183
|
-
sendTransport.removeAllListeners('connectionstatechange');
|
|
1118
|
+
expect(ctx.connectedSendTransport.connectionState).toBe('disconnected');
|
|
1184
1119
|
});
|
|
1185
1120
|
test('RemoteSdp properly handles multiple streams of the same type in planB', async () => {
|
|
1186
1121
|
let sdp = undefined;
|
|
@@ -1189,9 +1124,11 @@ test('RemoteSdp properly handles multiple streams of the same type in planB', as
|
|
|
1189
1124
|
await remoteSdp.receive({
|
|
1190
1125
|
mid: 'video',
|
|
1191
1126
|
kind: 'video',
|
|
1192
|
-
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1127
|
+
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1128
|
+
codecMimeType: 'video/VP8',
|
|
1129
|
+
}).rtpParameters,
|
|
1193
1130
|
streamId: 'streamId-1',
|
|
1194
|
-
trackId: 'trackId-1'
|
|
1131
|
+
trackId: 'trackId-1',
|
|
1195
1132
|
});
|
|
1196
1133
|
sdp = remoteSdp.getSdp();
|
|
1197
1134
|
sdpObject = sdpTransform.parse(sdp);
|
|
@@ -1206,9 +1143,11 @@ test('RemoteSdp properly handles multiple streams of the same type in planB', as
|
|
|
1206
1143
|
await remoteSdp.receive({
|
|
1207
1144
|
mid: 'video',
|
|
1208
1145
|
kind: 'video',
|
|
1209
|
-
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1146
|
+
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1147
|
+
codecMimeType: 'video/H264',
|
|
1148
|
+
}).rtpParameters,
|
|
1210
1149
|
streamId: 'streamId-2',
|
|
1211
|
-
trackId: 'trackId-2'
|
|
1150
|
+
trackId: 'trackId-2',
|
|
1212
1151
|
});
|
|
1213
1152
|
sdp = remoteSdp.getSdp();
|
|
1214
1153
|
sdpObject = sdpTransform.parse(sdp);
|
|
@@ -1226,7 +1165,9 @@ test('RemoteSdp properly handles multiple streams of the same type in planB', as
|
|
|
1226
1165
|
expect(sdpObject.media[0].ssrcs?.length).toBe(8);
|
|
1227
1166
|
await remoteSdp.planBStopReceiving({
|
|
1228
1167
|
mid: 'video',
|
|
1229
|
-
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1168
|
+
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1169
|
+
codecMimeType: 'video/H264',
|
|
1170
|
+
}).rtpParameters,
|
|
1230
1171
|
});
|
|
1231
1172
|
sdp = remoteSdp.getSdp();
|
|
1232
1173
|
sdpObject = sdpTransform.parse(sdp);
|
|
@@ -1250,9 +1191,11 @@ test('RemoteSdp does not duplicate codec descriptions', async () => {
|
|
|
1250
1191
|
await remoteSdp.receive({
|
|
1251
1192
|
mid: 'video',
|
|
1252
1193
|
kind: 'video',
|
|
1253
|
-
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1194
|
+
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1195
|
+
codecMimeType: 'video/VP8',
|
|
1196
|
+
}).rtpParameters,
|
|
1254
1197
|
streamId: 'streamId-1',
|
|
1255
|
-
trackId: 'trackId-1'
|
|
1198
|
+
trackId: 'trackId-1',
|
|
1256
1199
|
});
|
|
1257
1200
|
sdp = remoteSdp.getSdp();
|
|
1258
1201
|
sdpObject = sdpTransform.parse(sdp);
|
|
@@ -1267,9 +1210,11 @@ test('RemoteSdp does not duplicate codec descriptions', async () => {
|
|
|
1267
1210
|
await remoteSdp.receive({
|
|
1268
1211
|
mid: 'video',
|
|
1269
1212
|
kind: 'video',
|
|
1270
|
-
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1213
|
+
offerRtpParameters: fakeParameters.generateConsumerRemoteParameters({
|
|
1214
|
+
codecMimeType: 'video/VP8',
|
|
1215
|
+
}).rtpParameters,
|
|
1271
1216
|
streamId: 'streamId-1',
|
|
1272
|
-
trackId: 'trackId-1'
|
|
1217
|
+
trackId: 'trackId-1',
|
|
1273
1218
|
});
|
|
1274
1219
|
sdp = remoteSdp.getSdp();
|
|
1275
1220
|
sdpObject = sdpTransform.parse(sdp);
|
|
@@ -1283,25 +1228,51 @@ test('RemoteSdp does not duplicate codec descriptions', async () => {
|
|
|
1283
1228
|
expect(sdpObject.media[0].ssrcs?.length).toBe(8);
|
|
1284
1229
|
}, 500);
|
|
1285
1230
|
test('parseScalabilityMode() works', () => {
|
|
1286
|
-
expect(parseScalabilityMode('L1T3')).toEqual({
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
expect(parseScalabilityMode()).toEqual({
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
expect(parseScalabilityMode('
|
|
1231
|
+
expect(parseScalabilityMode('L1T3')).toEqual({
|
|
1232
|
+
spatialLayers: 1,
|
|
1233
|
+
temporalLayers: 3,
|
|
1234
|
+
});
|
|
1235
|
+
expect(parseScalabilityMode('L3T2_KEY')).toEqual({
|
|
1236
|
+
spatialLayers: 3,
|
|
1237
|
+
temporalLayers: 2,
|
|
1238
|
+
});
|
|
1239
|
+
expect(parseScalabilityMode('S2T3')).toEqual({
|
|
1240
|
+
spatialLayers: 2,
|
|
1241
|
+
temporalLayers: 3,
|
|
1242
|
+
});
|
|
1243
|
+
expect(parseScalabilityMode('foo')).toEqual({
|
|
1244
|
+
spatialLayers: 1,
|
|
1245
|
+
temporalLayers: 1,
|
|
1246
|
+
});
|
|
1247
|
+
expect(parseScalabilityMode()).toEqual({
|
|
1248
|
+
spatialLayers: 1,
|
|
1249
|
+
temporalLayers: 1,
|
|
1250
|
+
});
|
|
1251
|
+
expect(parseScalabilityMode('S0T3')).toEqual({
|
|
1252
|
+
spatialLayers: 1,
|
|
1253
|
+
temporalLayers: 1,
|
|
1254
|
+
});
|
|
1255
|
+
expect(parseScalabilityMode('S1T0')).toEqual({
|
|
1256
|
+
spatialLayers: 1,
|
|
1257
|
+
temporalLayers: 1,
|
|
1258
|
+
});
|
|
1259
|
+
expect(parseScalabilityMode('L20T3')).toEqual({
|
|
1260
|
+
spatialLayers: 20,
|
|
1261
|
+
temporalLayers: 3,
|
|
1262
|
+
});
|
|
1263
|
+
expect(parseScalabilityMode('S200T3')).toEqual({
|
|
1264
|
+
spatialLayers: 1,
|
|
1265
|
+
temporalLayers: 1,
|
|
1266
|
+
});
|
|
1295
1267
|
});
|
|
1296
1268
|
describe('detectDevice() assigns proper handler based on UserAgent', () => {
|
|
1297
1269
|
const originalNavigator = global.navigator;
|
|
1298
1270
|
for (const uaTestCase of uaTestCases_1.uaTestCases) {
|
|
1299
1271
|
test(uaTestCase.desc, () => {
|
|
1300
1272
|
// @ts-ignore
|
|
1301
|
-
global.navigator =
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
};
|
|
1273
|
+
global.navigator = {
|
|
1274
|
+
userAgent: uaTestCase.ua,
|
|
1275
|
+
};
|
|
1305
1276
|
const originalRTCRtpTransceiver = global.RTCRtpTransceiver;
|
|
1306
1277
|
if (uaTestCase.expect === 'Safari12') {
|
|
1307
1278
|
global.RTCRtpTransceiver = class Dummy {
|