nock 14.0.0 → 14.0.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 (2) hide show
  1. package/lib/recorder.js +86 -115
  2. package/package.json +3 -3
package/lib/recorder.js CHANGED
@@ -6,7 +6,6 @@ const { inspect } = require('util')
6
6
 
7
7
  const common = require('./common')
8
8
  const { restoreOverriddenClientRequest } = require('./intercept')
9
- const { EventEmitter } = require('stream')
10
9
  const { gzipSync, brotliCompressSync, deflateSync } = require('zlib')
11
10
  const {
12
11
  default: nodeInterceptors,
@@ -225,134 +224,106 @@ function record(recOptions) {
225
224
  // We override the requests so that we can save information on them before executing.
226
225
  clientRequestInterceptor.apply()
227
226
  fetchRequestInterceptor.apply()
228
- clientRequestInterceptor.on('request', async function ({ request }) {
229
- await recordRequest(request)
230
- })
231
- fetchRequestInterceptor.on('request', async function ({ request }) {
232
- await recordRequest(request)
233
- })
227
+ clientRequestInterceptor.on(
228
+ 'response',
229
+ async function ({ request, response }) {
230
+ await recordResponse(request, response)
231
+ },
232
+ )
233
+ fetchRequestInterceptor.on(
234
+ 'response',
235
+ async function ({ request, response }) {
236
+ // fetch decompresses the body automatically, so we need to recompress it
237
+ const codings =
238
+ response.headers
239
+ .get('content-encoding')
240
+ ?.toLowerCase()
241
+ .split(',')
242
+ .map(c => c.trim()) || []
243
+
244
+ let body = await response.arrayBuffer()
245
+ for (const coding of codings) {
246
+ if (coding === 'gzip') {
247
+ body = gzipSync(body)
248
+ } else if (coding === 'deflate') {
249
+ body = deflateSync(body)
250
+ } else if (coding === 'br') {
251
+ body = brotliCompressSync(body)
252
+ }
253
+ }
234
254
 
235
- async function recordRequest(mswRequest) {
255
+ await recordResponse(request, new Response(body, response))
256
+ },
257
+ )
258
+
259
+ async function recordResponse(mswRequest, mswResponse) {
236
260
  const request = mswRequest.clone()
261
+ const response = mswResponse.clone()
237
262
  const { options } = common.normalizeClientRequestArgs(request.url)
238
263
  options.method = request.method
239
264
  const proto = options.protocol.slice(0, -1)
265
+ if (proto === 'https') {
266
+ options.proto = 'https'
267
+ }
268
+ debug(thisRecordingId, proto, 'intercepted request ended')
269
+
270
+ let reqheaders
271
+ // Ignore request headers completely unless it was explicitly enabled by the user (see README)
272
+ if (enableReqHeadersRecording) {
273
+ // We never record user-agent headers as they are worse than useless -
274
+ // they actually make testing more difficult without providing any benefit (see README)
275
+ reqheaders = Object.fromEntries(request.headers.entries())
276
+ common.deleteHeadersField(reqheaders, 'user-agent')
277
+ }
240
278
 
241
- // Node 0.11 https.request calls http.request -- don't want to record things
242
- // twice.
243
- /* istanbul ignore if */
244
- if (options._recording) {
245
- return
279
+ const headers = Object.fromEntries(response.headers.entries())
280
+ const res = {
281
+ statusCode: response.status,
282
+ headers,
283
+ rawHeaders: headers,
246
284
  }
247
- options._recording = true
248
-
249
- const req = new EventEmitter()
250
- req.on('response', function () {
251
- debug(thisRecordingId, 'intercepting', proto, 'request to record')
252
-
253
- clientRequestInterceptor.once('response', async function ({ response }) {
254
- await recordResponse(response)
255
- })
256
- fetchRequestInterceptor.once('response', async function ({ response }) {
257
- // fetch decompresses the body automatically, so we need to recompress it
258
- const codings =
259
- response.headers
260
- .get('content-encoding')
261
- ?.toLowerCase()
262
- .split(',')
263
- .map(c => c.trim()) || []
264
-
265
- let body = await response.arrayBuffer()
266
- for (const coding of codings) {
267
- if (coding === 'gzip') {
268
- body = gzipSync(body)
269
- } else if (coding === 'deflate') {
270
- body = deflateSync(body)
271
- } else if (coding === 'br') {
272
- body = brotliCompressSync(body)
273
- }
274
- }
275
285
 
276
- await recordResponse(new Response(body, response))
277
- })
278
-
279
- // Intercept "res.once('end', ...)"-like event
280
- async function recordResponse(mswResponse) {
281
- const response = mswResponse.clone()
282
- debug(thisRecordingId, proto, 'intercepted request ended')
283
-
284
- let reqheaders
285
- // Ignore request headers completely unless it was explicitly enabled by the user (see README)
286
- if (enableReqHeadersRecording) {
287
- // We never record user-agent headers as they are worse than useless -
288
- // they actually make testing more difficult without providing any benefit (see README)
289
- reqheaders = Object.fromEntries(request.headers.entries())
290
- common.deleteHeadersField(reqheaders, 'user-agent')
291
- }
286
+ const generateFn = outputObjects
287
+ ? generateRequestAndResponseObject
288
+ : generateRequestAndResponse
289
+ let out = generateFn({
290
+ req: options,
291
+ bodyChunks: [Buffer.from(await request.arrayBuffer())],
292
+ options,
293
+ res,
294
+ dataChunks: [Buffer.from(await response.arrayBuffer())],
295
+ reqheaders,
296
+ })
292
297
 
293
- const headers = Object.fromEntries(response.headers.entries())
294
- const res = {
295
- statusCode: response.status,
296
- headers,
297
- rawHeaders: headers,
298
- }
298
+ debug('out:', out)
299
+
300
+ // Check that the request was made during the current recording.
301
+ // If it hasn't then skip it. There is no other simple way to handle
302
+ // this as it depends on the timing of requests and responses. Throwing
303
+ // will make some recordings/unit tests fail randomly depending on how
304
+ // fast/slow the response arrived.
305
+ // If you are seeing this error then you need to make sure that all
306
+ // the requests made during a single recording session finish before
307
+ // ending the same recording session.
308
+ if (thisRecordingId !== currentRecordingId) {
309
+ debug('skipping recording of an out-of-order request', out)
310
+ return
311
+ }
299
312
 
300
- const generateFn = outputObjects
301
- ? generateRequestAndResponseObject
302
- : generateRequestAndResponse
303
- let out = generateFn({
304
- req: options,
305
- bodyChunks: [Buffer.from(await request.arrayBuffer())],
306
- options,
307
- res,
308
- dataChunks: [Buffer.from(await response.arrayBuffer())],
309
- reqheaders,
310
- })
311
-
312
- debug('out:', out)
313
-
314
- // Check that the request was made during the current recording.
315
- // If it hasn't then skip it. There is no other simple way to handle
316
- // this as it depends on the timing of requests and responses. Throwing
317
- // will make some recordings/unit tests fail randomly depending on how
318
- // fast/slow the response arrived.
319
- // If you are seeing this error then you need to make sure that all
320
- // the requests made during a single recording session finish before
321
- // ending the same recording session.
322
- if (thisRecordingId !== currentRecordingId) {
323
- debug('skipping recording of an out-of-order request', out)
324
- return
325
- }
313
+ outputs.push(out)
326
314
 
327
- outputs.push(out)
328
-
329
- if (!dontPrint) {
330
- if (useSeparator) {
331
- if (typeof out !== 'string') {
332
- out = JSON.stringify(out, null, 2)
333
- }
334
- logging(SEPARATOR + out + SEPARATOR)
335
- } else {
336
- logging(out)
337
- }
315
+ if (!dontPrint) {
316
+ if (useSeparator) {
317
+ if (typeof out !== 'string') {
318
+ out = JSON.stringify(out, null, 2)
338
319
  }
320
+ logging(SEPARATOR + out + SEPARATOR)
321
+ } else {
322
+ logging(out)
339
323
  }
324
+ }
340
325
 
341
- debug('finished setting up intercepting')
342
-
343
- // We override both the http and the https modules; when we are
344
- // serializing the request, we need to know which was called.
345
- // By stuffing the state, we can make sure that nock records
346
- // the intended protocol.
347
- if (proto === 'https') {
348
- options.proto = 'https'
349
- }
350
- })
351
-
352
- // This is a massive change, we are trying to change minimum code, so we emit end event here
353
- // because mswjs take care for these events
354
- // TODO: refactor the recorder, we no longer need all the listeners and can just record the request we get from MSW
355
- req.emit('response')
326
+ debug('finished setting up intercepting')
356
327
  }
357
328
  }
358
329
 
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "testing",
8
8
  "isolation"
9
9
  ],
10
- "version": "14.0.0",
10
+ "version": "14.0.2",
11
11
  "author": "Pedro Teixeira <pedro.teixeira@gmail.com>",
12
12
  "repository": {
13
13
  "type": "git",
@@ -17,12 +17,12 @@
17
17
  "url": "https://github.com/nock/nock/issues"
18
18
  },
19
19
  "engines": {
20
- "node": ">= 18"
20
+ "node": ">=18.20.0 <20 || >=20.12.1"
21
21
  },
22
22
  "main": "./index.js",
23
23
  "types": "types",
24
24
  "dependencies": {
25
- "@mswjs/interceptors": "^0.37.3",
25
+ "@mswjs/interceptors": "^0.38.0",
26
26
  "json-stringify-safe": "^5.0.1",
27
27
  "propagate": "^2.0.0"
28
28
  },