mediasoup-client 3.7.0 → 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.
Files changed (105) 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 +43 -42
  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 +14 -10
  22. package/lib/Transport.d.ts.map +1 -1
  23. package/lib/Transport.js +71 -53
  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 +64 -57
  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 +75 -62
  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 +77 -65
  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 +68 -60
  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 +65 -58
  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 +43 -37
  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 +19 -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 +65 -52
  50. package/lib/handlers/HandlerInterface.d.ts.map +1 -1
  51. package/lib/handlers/ReactNative.d.ts +4 -4
  52. package/lib/handlers/ReactNative.d.ts.map +1 -1
  53. package/lib/handlers/ReactNative.js +76 -64
  54. package/lib/handlers/ReactNativeUnifiedPlan.d.ts +4 -4
  55. package/lib/handlers/ReactNativeUnifiedPlan.d.ts.map +1 -1
  56. package/lib/handlers/ReactNativeUnifiedPlan.js +65 -58
  57. package/lib/handlers/Safari11.d.ts +4 -4
  58. package/lib/handlers/Safari11.d.ts.map +1 -1
  59. package/lib/handlers/Safari11.js +74 -61
  60. package/lib/handlers/Safari12.d.ts +4 -4
  61. package/lib/handlers/Safari12.d.ts.map +1 -1
  62. package/lib/handlers/Safari12.js +65 -57
  63. package/lib/handlers/ortc/edgeUtils.d.ts.map +1 -1
  64. package/lib/handlers/ortc/utils.d.ts.map +1 -1
  65. package/lib/handlers/ortc/utils.js +2 -2
  66. package/lib/handlers/sdp/MediaSection.d.ts +5 -5
  67. package/lib/handlers/sdp/MediaSection.d.ts.map +1 -1
  68. package/lib/handlers/sdp/MediaSection.js +287 -305
  69. package/lib/handlers/sdp/RemoteSdp.d.ts +5 -5
  70. package/lib/handlers/sdp/RemoteSdp.d.ts.map +1 -1
  71. package/lib/handlers/sdp/RemoteSdp.js +28 -30
  72. package/lib/handlers/sdp/commonUtils.d.ts +4 -4
  73. package/lib/handlers/sdp/commonUtils.d.ts.map +1 -1
  74. package/lib/handlers/sdp/commonUtils.js +41 -46
  75. package/lib/handlers/sdp/plainRtpUtils.d.ts +2 -2
  76. package/lib/handlers/sdp/plainRtpUtils.d.ts.map +1 -1
  77. package/lib/handlers/sdp/plainRtpUtils.js +5 -7
  78. package/lib/handlers/sdp/planBUtils.d.ts +2 -2
  79. package/lib/handlers/sdp/planBUtils.d.ts.map +1 -1
  80. package/lib/handlers/sdp/planBUtils.js +11 -14
  81. package/lib/handlers/sdp/unifiedPlanUtils.d.ts +2 -2
  82. package/lib/handlers/sdp/unifiedPlanUtils.d.ts.map +1 -1
  83. package/lib/handlers/sdp/unifiedPlanUtils.js +11 -14
  84. package/lib/index.d.ts +1 -1
  85. package/lib/index.js +1 -1
  86. package/lib/ortc.d.ts.map +1 -1
  87. package/lib/ortc.js +90 -92
  88. package/lib/scalabilityModes.d.ts.map +1 -1
  89. package/lib/scalabilityModes.js +2 -2
  90. package/lib/{tests → test}/fakeParameters.d.ts +2 -2
  91. package/lib/test/fakeParameters.d.ts.map +1 -0
  92. package/lib/test/fakeParameters.js +645 -0
  93. package/lib/{tests → test}/test.d.ts.map +1 -1
  94. package/lib/{tests → test}/test.js +466 -495
  95. package/lib/test/uaTestCases.d.ts.map +1 -0
  96. package/lib/{tests → test}/uaTestCases.js +17 -17
  97. package/lib/types.d.ts.map +1 -1
  98. package/lib/utils.d.ts.map +1 -1
  99. package/npm-scripts.mjs +72 -98
  100. package/package.json +93 -90
  101. package/lib/tests/fakeParameters.d.ts.map +0 -1
  102. package/lib/tests/fakeParameters.js +0 -662
  103. package/lib/tests/uaTestCases.d.ts.map +0 -1
  104. /package/lib/{tests → test}/test.d.ts +0 -0
  105. /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,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(() => 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 already.
311
+ expect(connectEventNumTimesCalled).toBe(0);
269
312
  expect(produceEventNumTimesCalled).toBe(1);
270
313
  expect(typeof audioProducer).toBe('object');
271
- expect(audioProducer.id).toBe(audioProducerId);
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 sendTransport.produce({
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(1);
371
+ expect(connectEventNumTimesCalled).toBe(0);
334
372
  expect(produceEventNumTimesCalled).toBe(2);
335
373
  expect(typeof videoProducer).toBe('object');
336
- expect(videoProducer.id).toBe(videoProducerId);
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
- await expect(sendTransport.produce({ track, appData: true }))
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({ 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);
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
- audioConsumer = await recvTransport.consume({
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
- expect(connectEventNumTimesCalled).toBe(1);
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 = audioProducer.rtpParameters.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 recvTransport.consume({
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(1);
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({ codecMimeType: 'video/VP8' });
619
- const videoConsumerRemoteParameters2 = fakeParameters.generateConsumerRemoteParameters({ codecMimeType: 'video/VP8' });
620
- const pushSpy = jest.spyOn(recvTransport._awaitQueue, 'push');
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((resolve) => {
623
- recvTransport.observer.on('newconsumer', (consumer) => {
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
- recvTransport.consume({
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
- recvTransport.consume({
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
- .rejects
661
- .toThrow(TypeError);
686
+ await expect(ctx.recvTransport.consume({ id: '1234' })).rejects.toThrow(TypeError);
687
+ await expect(
662
688
  // @ts-ignore
663
- await expect(recvTransport.consume({ id: '1234', producerId: '4444' }))
664
- .rejects
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
- .rejects
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({ codecMimeType: 'audio/opus' });
687
- await expect(sendTransport.consume({
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({ codecMimeType: 'audio/ISAC' });
698
- await expect(sendTransport.consume({
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({ codecMimeType: 'audio/opus' });
728
+ const consumerRemoteParameters = fakeParameters.generateConsumerRemoteParameters({
729
+ codecMimeType: 'audio/opus',
730
+ });
731
+ await expect(
709
732
  // @ts-ignore
710
- await expect(recvTransport.consume({ consumerRemoteParameters, appData: true }))
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
- // eslint-disable-next-line no-unused-vars
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 sendTransport.produceData({
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(dataProducerId);
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
- await expect(sendTransport.produceData({ appData: true }))
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 recvTransport.consumeData({
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
- .rejects
790
- .toThrow(TypeError);
792
+ await expect(ctx.recvTransport.consumeData({ id: '1234' })).rejects.toThrow(TypeError);
793
+ await expect(
791
794
  // @ts-ignore
792
- await expect(recvTransport.consumeData({ id: '1234', dataProducerId: '4444' }))
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
- // @ts-ignore
809
- await expect(recvTransport.consumeData({ dataConsumerRemoteParameters, appData: true }))
810
- .rejects
811
- .toThrow(TypeError);
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', (iceGatheringState) => {
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', (connectionState) => {
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', (connectionState) => {
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
- // Track will be still enabled due to disableTrackOnPause: false.
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
- .resolves
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
- .resolves
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
- .rejects
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
- await expect(videoProducer.setMaxSpatialLayer('chicken'))
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
- await expect(audioProducer.replaceTrack({ track: audioTrack }))
1022
- .rejects
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
- await expect(audioProducer.getStats())
1028
- .rejects
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
- await expect(audioConsumer.getStats())
1038
- .rejects
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
- // Audio Producer was already closed.
1069
- expect(audioProducerTrackendedEventCalled).toBe(false);
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(true);
1035
+ ctx.videoProducer.track.remoteStop();
1036
+ expect(videoProducerTrackendedEventCalled).toBe(false);
1073
1037
  // @ts-ignore
1074
- audioConsumer.track.remoteStop();
1075
- // Audio Consumer was already closed.
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
- // 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);
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
- // 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();
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
- // 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);
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(recvTransport.consume({}))
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
- // 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');
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(recvTransport.consumeData({}))
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
- await expect(sendTransport.getStats())
1159
- .rejects
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
- await expect(sendTransport.restartIce({ ieParameters: {} }))
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
- await expect(sendTransport.updateIceServers({ iceServers: [] }))
1170
- .rejects
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
- // eslint-disable-next-line no-unused-vars
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
- sendTransport.handler.setConnectionState('disconnected');
1116
+ ctx.connectedSendTransport.handler.setConnectionState('disconnected');
1181
1117
  expect(connectionStateChangeEventNumTimesCalled).toBe(0);
1182
- expect(sendTransport.connectionState).toBe('disconnected');
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({ codecMimeType: 'video/VP8' }).rtpParameters,
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({ codecMimeType: 'video/H264' }).rtpParameters,
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({ codecMimeType: 'video/H264' }).rtpParameters
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({ codecMimeType: 'video/VP8' }).rtpParameters,
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({ codecMimeType: 'video/VP8' }).rtpParameters,
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({ 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 });
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
- userAgent: uaTestCase.ua
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 {