mediasoup-client 3.7.1 → 3.7.3

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