@mswjs/interceptors 0.22.11 → 0.22.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/node/RemoteHttpInterceptor.js +2 -2
- package/lib/node/RemoteHttpInterceptor.mjs +1 -1
- package/lib/node/{chunk-7XU7Q63W.js → chunk-BGW7OOI4.js} +19 -18
- package/lib/node/{chunk-XVHIXGXD.mjs → chunk-JRKMZWAD.mjs} +19 -18
- package/lib/node/interceptors/ClientRequest/index.js +2 -2
- package/lib/node/interceptors/ClientRequest/index.mjs +1 -1
- package/lib/node/presets/node.js +2 -2
- package/lib/node/presets/node.mjs +1 -1
- package/package.json +2 -2
- package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +37 -30
- package/src/interceptors/ClientRequest/NodeClientRequest.ts +40 -30
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var _chunkRJMXHEGJjs = require('./chunk-RJMXHEGJ.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var _chunkBGW7OOI4js = require('./chunk-BGW7OOI4.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
var _chunk2OJRZCGSjs = require('./chunk-2OJRZCGS.js');
|
|
@@ -23,7 +23,7 @@ var RemoteHttpInterceptor = class extends _chunkRJMXHEGJjs.BatchInterceptor {
|
|
|
23
23
|
super({
|
|
24
24
|
name: "remote-interceptor",
|
|
25
25
|
interceptors: [
|
|
26
|
-
new (0,
|
|
26
|
+
new (0, _chunkBGW7OOI4js.ClientRequestInterceptor)(),
|
|
27
27
|
new (0, _chunk2OJRZCGSjs.XMLHttpRequestInterceptor)()
|
|
28
28
|
]
|
|
29
29
|
});
|
|
@@ -323,6 +323,11 @@ var _NodeClientRequest = class extends _http.ClientRequest {
|
|
|
323
323
|
}
|
|
324
324
|
respondWith(mockedResponse) {
|
|
325
325
|
this.logger.info("responding with a mocked response...", mockedResponse);
|
|
326
|
+
Object.defineProperties(this, {
|
|
327
|
+
writableFinished: { value: true },
|
|
328
|
+
writableEnded: { value: true }
|
|
329
|
+
});
|
|
330
|
+
this.emit("finish");
|
|
326
331
|
const { status, statusText, headers, body } = mockedResponse;
|
|
327
332
|
this.response.statusCode = status;
|
|
328
333
|
this.response.statusMessage = statusText;
|
|
@@ -336,37 +341,33 @@ var _NodeClientRequest = class extends _http.ClientRequest {
|
|
|
336
341
|
});
|
|
337
342
|
}
|
|
338
343
|
this.logger.info("mocked response headers ready:", headers);
|
|
339
|
-
const
|
|
340
|
-
const
|
|
341
|
-
this.logger.info("
|
|
342
|
-
|
|
343
|
-
this.response.complete = true;
|
|
344
|
-
isResponseStreamRead.resolve();
|
|
345
|
-
this.logger.info("closed response stream!");
|
|
344
|
+
const isResponseStreamFinished = new (0, _deferredpromise.DeferredPromise)();
|
|
345
|
+
const finishResponseStream = () => {
|
|
346
|
+
this.logger.info("finished response stream!");
|
|
347
|
+
isResponseStreamFinished.resolve();
|
|
346
348
|
};
|
|
347
349
|
if (body) {
|
|
348
350
|
const bodyReader = body.getReader();
|
|
349
351
|
const readNextChunk = async () => {
|
|
350
352
|
const { done, value } = await bodyReader.read();
|
|
351
353
|
if (done) {
|
|
352
|
-
|
|
354
|
+
finishResponseStream();
|
|
353
355
|
return;
|
|
354
356
|
}
|
|
355
|
-
this.response.
|
|
357
|
+
this.response.emit("data", value);
|
|
356
358
|
return readNextChunk();
|
|
357
359
|
};
|
|
358
360
|
readNextChunk();
|
|
359
361
|
} else {
|
|
360
|
-
|
|
362
|
+
finishResponseStream();
|
|
361
363
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
this.emit("
|
|
369
|
-
this.emit("response", this.response);
|
|
364
|
+
this.res = this.response;
|
|
365
|
+
this.emit("response", this.response);
|
|
366
|
+
isResponseStreamFinished.then(() => {
|
|
367
|
+
this.logger.info("finalizing response...");
|
|
368
|
+
this.response.push(null);
|
|
369
|
+
this.response.complete = true;
|
|
370
|
+
this.response.emit("end");
|
|
370
371
|
this.terminate();
|
|
371
372
|
});
|
|
372
373
|
}
|
|
@@ -323,6 +323,11 @@ var _NodeClientRequest = class extends ClientRequest {
|
|
|
323
323
|
}
|
|
324
324
|
respondWith(mockedResponse) {
|
|
325
325
|
this.logger.info("responding with a mocked response...", mockedResponse);
|
|
326
|
+
Object.defineProperties(this, {
|
|
327
|
+
writableFinished: { value: true },
|
|
328
|
+
writableEnded: { value: true }
|
|
329
|
+
});
|
|
330
|
+
this.emit("finish");
|
|
326
331
|
const { status, statusText, headers, body } = mockedResponse;
|
|
327
332
|
this.response.statusCode = status;
|
|
328
333
|
this.response.statusMessage = statusText;
|
|
@@ -336,37 +341,33 @@ var _NodeClientRequest = class extends ClientRequest {
|
|
|
336
341
|
});
|
|
337
342
|
}
|
|
338
343
|
this.logger.info("mocked response headers ready:", headers);
|
|
339
|
-
const
|
|
340
|
-
const
|
|
341
|
-
this.logger.info("
|
|
342
|
-
|
|
343
|
-
this.response.complete = true;
|
|
344
|
-
isResponseStreamRead.resolve();
|
|
345
|
-
this.logger.info("closed response stream!");
|
|
344
|
+
const isResponseStreamFinished = new DeferredPromise();
|
|
345
|
+
const finishResponseStream = () => {
|
|
346
|
+
this.logger.info("finished response stream!");
|
|
347
|
+
isResponseStreamFinished.resolve();
|
|
346
348
|
};
|
|
347
349
|
if (body) {
|
|
348
350
|
const bodyReader = body.getReader();
|
|
349
351
|
const readNextChunk = async () => {
|
|
350
352
|
const { done, value } = await bodyReader.read();
|
|
351
353
|
if (done) {
|
|
352
|
-
|
|
354
|
+
finishResponseStream();
|
|
353
355
|
return;
|
|
354
356
|
}
|
|
355
|
-
this.response.
|
|
357
|
+
this.response.emit("data", value);
|
|
356
358
|
return readNextChunk();
|
|
357
359
|
};
|
|
358
360
|
readNextChunk();
|
|
359
361
|
} else {
|
|
360
|
-
|
|
362
|
+
finishResponseStream();
|
|
361
363
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
this.emit("
|
|
369
|
-
this.emit("response", this.response);
|
|
364
|
+
this.res = this.response;
|
|
365
|
+
this.emit("response", this.response);
|
|
366
|
+
isResponseStreamFinished.then(() => {
|
|
367
|
+
this.logger.info("finalizing response...");
|
|
368
|
+
this.response.push(null);
|
|
369
|
+
this.response.complete = true;
|
|
370
|
+
this.response.emit("end");
|
|
370
371
|
this.terminate();
|
|
371
372
|
});
|
|
372
373
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkBGW7OOI4js = require('../../chunk-BGW7OOI4.js');
|
|
4
4
|
require('../../chunk-ZJOF5MEZ.js');
|
|
5
5
|
require('../../chunk-6KJ5M2VR.js');
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
exports.ClientRequestInterceptor =
|
|
8
|
+
exports.ClientRequestInterceptor = _chunkBGW7OOI4js.ClientRequestInterceptor;
|
package/lib/node/presets/node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkBGW7OOI4js = require('../chunk-BGW7OOI4.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var _chunk2OJRZCGSjs = require('../chunk-2OJRZCGS.js');
|
|
@@ -11,7 +11,7 @@ require('../chunk-6KJ5M2VR.js');
|
|
|
11
11
|
|
|
12
12
|
// src/presets/node.ts
|
|
13
13
|
var node_default = [
|
|
14
|
-
new (0,
|
|
14
|
+
new (0, _chunkBGW7OOI4js.ClientRequestInterceptor)(),
|
|
15
15
|
new (0, _chunk2OJRZCGSjs.XMLHttpRequestInterceptor)()
|
|
16
16
|
];
|
|
17
17
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mswjs/interceptors",
|
|
3
3
|
"description": "Low-level HTTP/HTTPS/XHR/fetch request interception library.",
|
|
4
|
-
"version": "0.22.
|
|
4
|
+
"version": "0.22.13",
|
|
5
5
|
"main": "./lib/node/index.js",
|
|
6
6
|
"module": "./lib/node/index.mjs",
|
|
7
7
|
"types": "./lib/node/index.d.ts",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
"dependencies": {
|
|
140
140
|
"@open-draft/deferred-promise": "^2.1.0",
|
|
141
|
-
"@open-draft/logger": "^0.
|
|
141
|
+
"@open-draft/logger": "^0.3.0",
|
|
142
142
|
"@open-draft/until": "^2.0.0",
|
|
143
143
|
"headers-polyfill": "^3.1.0",
|
|
144
144
|
"outvariant": "^1.2.1",
|
|
@@ -62,22 +62,29 @@ it('gracefully finishes the request when it has a mocked response', async () =>
|
|
|
62
62
|
request.end()
|
|
63
63
|
|
|
64
64
|
const responseReceived = new DeferredPromise<IncomingMessage>()
|
|
65
|
+
|
|
65
66
|
request.on('response', async (response) => {
|
|
66
67
|
responseReceived.resolve(response)
|
|
67
68
|
})
|
|
68
69
|
const response = await responseReceived
|
|
69
70
|
|
|
70
|
-
// Request must be marked as finished.
|
|
71
|
-
expect(request.
|
|
72
|
-
expect(request.
|
|
73
|
-
expect(request.
|
|
74
|
-
expect(request.writableCorked).toEqual(0)
|
|
75
|
-
|
|
76
|
-
expect(response.statusCode).toEqual(301)
|
|
77
|
-
expect(response.headers).toHaveProperty('x-custom-header', 'yes')
|
|
71
|
+
// Request must be marked as finished as soon as it's sent.
|
|
72
|
+
expect(request.writableEnded).toBe(true)
|
|
73
|
+
expect(request.writableFinished).toBe(true)
|
|
74
|
+
expect(request.writableCorked).toBe(0)
|
|
78
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Consume the response body, which will handle the "data" and "end"
|
|
78
|
+
* events of the incoming message. After this point, the response is finished.
|
|
79
|
+
*/
|
|
79
80
|
const text = await getIncomingMessageBody(response)
|
|
80
|
-
|
|
81
|
+
|
|
82
|
+
// Response must be marked as finished as soon as its done.
|
|
83
|
+
expect(request['response'].complete).toBe(true)
|
|
84
|
+
|
|
85
|
+
expect(response.statusCode).toBe(301)
|
|
86
|
+
expect(response.headers).toHaveProperty('x-custom-header', 'yes')
|
|
87
|
+
expect(text).toBe('mocked-response')
|
|
81
88
|
})
|
|
82
89
|
|
|
83
90
|
it('responds with a mocked response when requesting an existing hostname', async () => {
|
|
@@ -102,10 +109,10 @@ it('responds with a mocked response when requesting an existing hostname', async
|
|
|
102
109
|
})
|
|
103
110
|
const response = await responseReceived
|
|
104
111
|
|
|
105
|
-
expect(response.statusCode).
|
|
112
|
+
expect(response.statusCode).toBe(201)
|
|
106
113
|
|
|
107
114
|
const text = await getIncomingMessageBody(response)
|
|
108
|
-
expect(text).
|
|
115
|
+
expect(text).toBe('mocked-response')
|
|
109
116
|
})
|
|
110
117
|
|
|
111
118
|
it('performs the request as-is given resolver returned no mocked response', async () => {
|
|
@@ -128,15 +135,15 @@ it('performs the request as-is given resolver returned no mocked response', asyn
|
|
|
128
135
|
})
|
|
129
136
|
const response = await responseReceived
|
|
130
137
|
|
|
131
|
-
expect(request.finished).
|
|
132
|
-
expect(request.writableEnded).
|
|
138
|
+
expect(request.finished).toBe(true)
|
|
139
|
+
expect(request.writableEnded).toBe(true)
|
|
133
140
|
|
|
134
|
-
expect(response.statusCode).
|
|
135
|
-
expect(response.statusMessage).
|
|
141
|
+
expect(response.statusCode).toBe(200)
|
|
142
|
+
expect(response.statusMessage).toBe('OK')
|
|
136
143
|
expect(response.headers).toHaveProperty('x-powered-by', 'Express')
|
|
137
144
|
|
|
138
145
|
const text = await getIncomingMessageBody(response)
|
|
139
|
-
expect(text).
|
|
146
|
+
expect(text).toBe('original-response')
|
|
140
147
|
})
|
|
141
148
|
|
|
142
149
|
it('emits the ENOTFOUND error connecting to a non-existing hostname given no mocked response', async () => {
|
|
@@ -153,8 +160,8 @@ it('emits the ENOTFOUND error connecting to a non-existing hostname given no moc
|
|
|
153
160
|
})
|
|
154
161
|
const error = await errorReceived
|
|
155
162
|
|
|
156
|
-
expect(error.code).
|
|
157
|
-
expect(error.syscall).
|
|
163
|
+
expect(error.code).toBe('ENOTFOUND')
|
|
164
|
+
expect(error.syscall).toBe('getaddrinfo')
|
|
158
165
|
})
|
|
159
166
|
|
|
160
167
|
it('emits the ECONNREFUSED error connecting to an inactive server given no mocked response', async () => {
|
|
@@ -177,10 +184,10 @@ it('emits the ECONNREFUSED error connecting to an inactive server given no mocke
|
|
|
177
184
|
|
|
178
185
|
const error = await errorReceived
|
|
179
186
|
|
|
180
|
-
expect(error.code).
|
|
181
|
-
expect(error.syscall).
|
|
182
|
-
expect(error.address).
|
|
183
|
-
expect(error.port).
|
|
187
|
+
expect(error.code).toBe('ECONNREFUSED')
|
|
188
|
+
expect(error.syscall).toBe('connect')
|
|
189
|
+
expect(error.address).toBe('127.0.0.1')
|
|
190
|
+
expect(error.port).toBe(12345)
|
|
184
191
|
})
|
|
185
192
|
|
|
186
193
|
it('does not emit ENOTFOUND error connecting to an inactive server given mocked response', async () => {
|
|
@@ -209,8 +216,8 @@ it('does not emit ENOTFOUND error connecting to an inactive server given mocked
|
|
|
209
216
|
const response = await responseReceived
|
|
210
217
|
|
|
211
218
|
expect(handleError).not.toHaveBeenCalled()
|
|
212
|
-
expect(response.statusCode).
|
|
213
|
-
expect(response.statusMessage).
|
|
219
|
+
expect(response.statusCode).toBe(200)
|
|
220
|
+
expect(response.statusMessage).toBe('Works')
|
|
214
221
|
})
|
|
215
222
|
|
|
216
223
|
it('does not emit ECONNREFUSED error connecting to an inactive server given mocked response', async () => {
|
|
@@ -241,8 +248,8 @@ it('does not emit ECONNREFUSED error connecting to an inactive server given mock
|
|
|
241
248
|
const response = await responseReceived
|
|
242
249
|
|
|
243
250
|
expect(handleError).not.toHaveBeenCalled()
|
|
244
|
-
expect(response.statusCode).
|
|
245
|
-
expect(response.statusMessage).
|
|
251
|
+
expect(response.statusCode).toBe(200)
|
|
252
|
+
expect(response.statusMessage).toBe('Works')
|
|
246
253
|
})
|
|
247
254
|
|
|
248
255
|
it('sends the request body to the server given no mocked response', async () => {
|
|
@@ -270,10 +277,10 @@ it('sends the request body to the server given no mocked response', async () =>
|
|
|
270
277
|
})
|
|
271
278
|
const response = await responseReceived
|
|
272
279
|
|
|
273
|
-
expect(response.statusCode).
|
|
280
|
+
expect(response.statusCode).toBe(200)
|
|
274
281
|
|
|
275
282
|
const text = await getIncomingMessageBody(response)
|
|
276
|
-
expect(text).
|
|
283
|
+
expect(text).toBe('onetwothree')
|
|
277
284
|
})
|
|
278
285
|
|
|
279
286
|
it('does not send request body to the original server given mocked response', async () => {
|
|
@@ -303,8 +310,8 @@ it('does not send request body to the original server given mocked response', as
|
|
|
303
310
|
})
|
|
304
311
|
const response = await responseReceived
|
|
305
312
|
|
|
306
|
-
expect(response.statusCode).
|
|
313
|
+
expect(response.statusCode).toBe(301)
|
|
307
314
|
|
|
308
315
|
const text = await getIncomingMessageBody(response)
|
|
309
|
-
expect(text).
|
|
316
|
+
expect(text).toBe('mock created!')
|
|
310
317
|
})
|
|
@@ -370,6 +370,20 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
370
370
|
private respondWith(mockedResponse: Response): void {
|
|
371
371
|
this.logger.info('responding with a mocked response...', mockedResponse)
|
|
372
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Mark the request as finished right before streaming back the response.
|
|
375
|
+
* This is not entirely conventional but this will allow the consumer to
|
|
376
|
+
* modify the outoging request in the interceptor.
|
|
377
|
+
*
|
|
378
|
+
* The request is finished when its headers and bodies have been sent.
|
|
379
|
+
* @see https://nodejs.org/api/http.html#event-finish
|
|
380
|
+
*/
|
|
381
|
+
Object.defineProperties(this, {
|
|
382
|
+
writableFinished: { value: true },
|
|
383
|
+
writableEnded: { value: true },
|
|
384
|
+
})
|
|
385
|
+
this.emit('finish')
|
|
386
|
+
|
|
373
387
|
const { status, statusText, headers, body } = mockedResponse
|
|
374
388
|
this.response.statusCode = status
|
|
375
389
|
this.response.statusMessage = statusText
|
|
@@ -392,18 +406,11 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
392
406
|
}
|
|
393
407
|
this.logger.info('mocked response headers ready:', headers)
|
|
394
408
|
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
const closeResponseStream = () => {
|
|
398
|
-
this.logger.info('closing response stream...')
|
|
399
|
-
|
|
400
|
-
// Push "null" to indicate that the response body is complete
|
|
401
|
-
// and shouldn't be written to anymore.
|
|
402
|
-
this.response.push(null)
|
|
403
|
-
this.response.complete = true
|
|
409
|
+
const isResponseStreamFinished = new DeferredPromise<void>()
|
|
404
410
|
|
|
405
|
-
|
|
406
|
-
this.logger.info('
|
|
411
|
+
const finishResponseStream = () => {
|
|
412
|
+
this.logger.info('finished response stream!')
|
|
413
|
+
isResponseStreamFinished.resolve()
|
|
407
414
|
}
|
|
408
415
|
|
|
409
416
|
if (body) {
|
|
@@ -412,38 +419,41 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
412
419
|
const { done, value } = await bodyReader.read()
|
|
413
420
|
|
|
414
421
|
if (done) {
|
|
415
|
-
|
|
422
|
+
finishResponseStream()
|
|
416
423
|
return
|
|
417
424
|
}
|
|
418
425
|
|
|
419
|
-
|
|
420
|
-
this.response.push(value)
|
|
426
|
+
this.response.emit('data', value)
|
|
421
427
|
|
|
422
428
|
return readNextChunk()
|
|
423
429
|
}
|
|
424
430
|
|
|
425
431
|
readNextChunk()
|
|
426
432
|
} else {
|
|
427
|
-
|
|
433
|
+
finishResponseStream()
|
|
428
434
|
}
|
|
429
435
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
436
|
+
/**
|
|
437
|
+
* Set the internal "res" property to the mocked "OutgoingMessage"
|
|
438
|
+
* to make the "ClientRequest" instance think there's data received
|
|
439
|
+
* from the socket.
|
|
440
|
+
* @see https://github.com/nodejs/node/blob/9c405f2591f5833d0247ed0fafdcd68c5b14ce7a/lib/_http_client.js#L501
|
|
441
|
+
*
|
|
442
|
+
* Set the response immediately so the interceptor could stream data
|
|
443
|
+
* chunks to the request client as they come in.
|
|
444
|
+
*/
|
|
445
|
+
// @ts-ignore
|
|
446
|
+
this.res = this.response
|
|
447
|
+
this.emit('response', this.response)
|
|
439
448
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
value: true,
|
|
443
|
-
})
|
|
449
|
+
isResponseStreamFinished.then(() => {
|
|
450
|
+
this.logger.info('finalizing response...')
|
|
444
451
|
|
|
445
|
-
|
|
446
|
-
|
|
452
|
+
// Push "null" to indicate that the response body is complete
|
|
453
|
+
// and shouldn't be written to anymore.
|
|
454
|
+
this.response.push(null)
|
|
455
|
+
this.response.complete = true
|
|
456
|
+
this.response.emit('end')
|
|
447
457
|
|
|
448
458
|
this.terminate()
|
|
449
459
|
})
|