nock 13.1.4 → 13.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/lib/back.js +57 -0
- package/lib/common.js +18 -10
- package/lib/intercepted_request_router.js +12 -6
- package/lib/interceptor.js +15 -4
- package/lib/playback_interceptor.js +2 -2
- package/lib/recorder.js +1 -1
- package/package.json +14 -15
- package/types/index.d.ts +1 -1
- package/CHANGELOG.md +0 -6
package/README.md
CHANGED
|
@@ -1323,6 +1323,18 @@ const interceptor = nock('http://example.org').get('somePath')
|
|
|
1323
1323
|
nock.removeInterceptor(interceptor)
|
|
1324
1324
|
```
|
|
1325
1325
|
|
|
1326
|
+
**Note** `.reply(...)` method returns Scope, not Interceptor, and so it is not a valid argument for `nock.removeInterceptor`. So if your method chain ends with `.reply` to be used with `nock.removeInterceptor` the chain need to be break in between:
|
|
1327
|
+
|
|
1328
|
+
```js
|
|
1329
|
+
// this will NOT work
|
|
1330
|
+
const interceptor = nock('http://example.org').get('somePath').reply(200, 'OK')
|
|
1331
|
+
nock.removeInterceptor(interceptor)
|
|
1332
|
+
// this is how it should be
|
|
1333
|
+
const interceptor = nock('http://example.org').get('somePath')
|
|
1334
|
+
interceptor.reply(200, 'OK')
|
|
1335
|
+
nock.removeInterceptor(interceptor)
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1326
1338
|
## Events
|
|
1327
1339
|
|
|
1328
1340
|
A scope emits the following events:
|
|
@@ -1459,6 +1471,8 @@ To set the mode call `nockBack.setMode(mode)` or run the tests with the `NOCK_BA
|
|
|
1459
1471
|
|
|
1460
1472
|
- record: use recorded nocks, record new nocks
|
|
1461
1473
|
|
|
1474
|
+
- update: remove recorded nocks, record nocks
|
|
1475
|
+
|
|
1462
1476
|
- lockdown: use recorded nocks, disables all http calls even when not nocked, doesn't record
|
|
1463
1477
|
|
|
1464
1478
|
## Common issues
|
|
@@ -1591,6 +1605,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/all-contri
|
|
|
1591
1605
|
<td align="center"><a href="https://github.com/benrki"><img src="https://avatars0.githubusercontent.com/u/4446950?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Ki</b></sub></a><br /><a href="#financial-benrki" title="Financial">💵</a></td>
|
|
1592
1606
|
<td align="center"><a href="http://chadf.ca"><img src="https://avatars2.githubusercontent.com/u/3250463?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chad Fawcett</b></sub></a><br /><a href="#financial-chadfawcett" title="Financial">💵</a></td>
|
|
1593
1607
|
<td align="center"><a href="http://www.laurencemyers.com.au"><img src="https://avatars.githubusercontent.com/u/6336048?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Laurence Dougal Myers</b></sub></a><br /><a href="https://github.com/nock/nock/commits?author=laurence-myers" title="Code">💻</a></td>
|
|
1608
|
+
<td align="center"><a href="https://github.com/Beretta1979"><img src="https://avatars.githubusercontent.com/u/10073962?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sébastien Van Bruaene</b></sub></a><br /><a href="https://github.com/nock/nock/commits?author=Beretta1979" title="Code">💻</a> <a href="https://github.com/nock/nock/commits?author=Beretta1979" title="Tests">⚠️</a></td>
|
|
1594
1609
|
</tr>
|
|
1595
1610
|
</table>
|
|
1596
1611
|
|
package/lib/back.js
CHANGED
|
@@ -175,6 +175,47 @@ const record = {
|
|
|
175
175
|
},
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
const update = {
|
|
179
|
+
setup: function () {
|
|
180
|
+
recorder.restore()
|
|
181
|
+
recorder.clear()
|
|
182
|
+
cleanAll()
|
|
183
|
+
activate()
|
|
184
|
+
disableNetConnect()
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
start: function (fixture, options) {
|
|
188
|
+
if (!fs) {
|
|
189
|
+
throw new Error('no fs')
|
|
190
|
+
}
|
|
191
|
+
const context = removeFixture(fixture)
|
|
192
|
+
recorder.record({
|
|
193
|
+
dont_print: true,
|
|
194
|
+
output_objects: true,
|
|
195
|
+
...options.recorder,
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
context.isRecording = true
|
|
199
|
+
|
|
200
|
+
return context
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
finish: function (fixture, options, context) {
|
|
204
|
+
let outputs = recorder.outputs()
|
|
205
|
+
|
|
206
|
+
if (typeof options.afterRecord === 'function') {
|
|
207
|
+
outputs = options.afterRecord(outputs)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
outputs =
|
|
211
|
+
typeof outputs === 'string' ? outputs : JSON.stringify(outputs, null, 4)
|
|
212
|
+
debug('recorder outputs:', outputs)
|
|
213
|
+
|
|
214
|
+
fs.mkdirSync(path.dirname(fixture), { recursive: true })
|
|
215
|
+
fs.writeFileSync(fixture, outputs)
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
|
|
178
219
|
const lockdown = {
|
|
179
220
|
setup: function () {
|
|
180
221
|
recorder.restore()
|
|
@@ -215,6 +256,20 @@ function load(fixture, options) {
|
|
|
215
256
|
return context
|
|
216
257
|
}
|
|
217
258
|
|
|
259
|
+
function removeFixture(fixture, options) {
|
|
260
|
+
const context = {
|
|
261
|
+
scopes: [],
|
|
262
|
+
assertScopesFinished: function () {},
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (fixture && fixtureExists(fixture)) {
|
|
266
|
+
/* istanbul ignore next - fs.unlinkSync is for node 10 support */
|
|
267
|
+
fs.rmSync ? fs.rmSync(fixture) : fs.unlinkSync(fixture)
|
|
268
|
+
}
|
|
269
|
+
context.isLoaded = false
|
|
270
|
+
return context
|
|
271
|
+
}
|
|
272
|
+
|
|
218
273
|
function applyHook(scopes, fn) {
|
|
219
274
|
if (!fn) {
|
|
220
275
|
return
|
|
@@ -258,6 +313,8 @@ const Modes = {
|
|
|
258
313
|
|
|
259
314
|
record, // use recorded nocks, record new nocks
|
|
260
315
|
|
|
316
|
+
update, // allow http calls, record all nocks, don't use recorded nocks
|
|
317
|
+
|
|
261
318
|
lockdown, // use recorded nocks, disables all http calls even when not nocked, doesnt record
|
|
262
319
|
}
|
|
263
320
|
|
package/lib/common.js
CHANGED
|
@@ -194,7 +194,7 @@ function isJSONContent(headers) {
|
|
|
194
194
|
*
|
|
195
195
|
* Duplicates throw an error.
|
|
196
196
|
*/
|
|
197
|
-
function headersFieldNamesToLowerCase(headers) {
|
|
197
|
+
function headersFieldNamesToLowerCase(headers, throwOnDuplicate) {
|
|
198
198
|
if (!isPlainObject(headers)) {
|
|
199
199
|
throw Error('Headers must be provided as an object')
|
|
200
200
|
}
|
|
@@ -203,9 +203,15 @@ function headersFieldNamesToLowerCase(headers) {
|
|
|
203
203
|
Object.entries(headers).forEach(([fieldName, fieldValue]) => {
|
|
204
204
|
const key = fieldName.toLowerCase()
|
|
205
205
|
if (lowerCaseHeaders[key] !== undefined) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
if (throwOnDuplicate) {
|
|
207
|
+
throw Error(
|
|
208
|
+
`Failed to convert header keys to lower case due to field name conflict: ${key}`
|
|
209
|
+
)
|
|
210
|
+
} else {
|
|
211
|
+
debug(
|
|
212
|
+
`Duplicate header provided in request: ${key}. Only the last value can be matched.`
|
|
213
|
+
)
|
|
214
|
+
}
|
|
209
215
|
}
|
|
210
216
|
lowerCaseHeaders[key] = fieldValue
|
|
211
217
|
})
|
|
@@ -547,7 +553,7 @@ function urlToOptions(url) {
|
|
|
547
553
|
* Used for comparing decoded search parameters, request body JSON objects,
|
|
548
554
|
* and URL decoded request form bodies.
|
|
549
555
|
*
|
|
550
|
-
* Performs a general recursive strict
|
|
556
|
+
* Performs a general recursive strict comparison with two caveats:
|
|
551
557
|
* - The expected data can use regexp to compare values
|
|
552
558
|
* - JSON path notation and nested objects are considered equal
|
|
553
559
|
*/
|
|
@@ -651,11 +657,13 @@ const timeouts = []
|
|
|
651
657
|
const intervals = []
|
|
652
658
|
const immediates = []
|
|
653
659
|
|
|
654
|
-
const wrapTimer =
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
660
|
+
const wrapTimer =
|
|
661
|
+
(timer, ids) =>
|
|
662
|
+
(...args) => {
|
|
663
|
+
const id = timer(...args)
|
|
664
|
+
ids.push(id)
|
|
665
|
+
return id
|
|
666
|
+
}
|
|
659
667
|
|
|
660
668
|
const setTimeout = wrapTimer(timers.setTimeout, timeouts)
|
|
661
669
|
const setInterval = wrapTimer(timers.setInterval, intervals)
|
|
@@ -40,7 +40,10 @@ class InterceptedRequestRouter {
|
|
|
40
40
|
// affecting the user so we use a clone of the object.
|
|
41
41
|
...options,
|
|
42
42
|
// We use lower-case header field names throughout Nock.
|
|
43
|
-
headers: common.headersFieldNamesToLowerCase(
|
|
43
|
+
headers: common.headersFieldNamesToLowerCase(
|
|
44
|
+
options.headers || {},
|
|
45
|
+
false
|
|
46
|
+
),
|
|
44
47
|
}
|
|
45
48
|
this.interceptors = interceptors
|
|
46
49
|
|
|
@@ -48,8 +51,12 @@ class InterceptedRequestRouter {
|
|
|
48
51
|
|
|
49
52
|
// support setting `timeout` using request `options`
|
|
50
53
|
// https://nodejs.org/docs/latest-v12.x/api/http.html#http_http_request_url_options_callback
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
// any timeout in the request options override any timeout in the agent options.
|
|
55
|
+
// per https://github.com/nodejs/node/pull/21204
|
|
56
|
+
const timeout =
|
|
57
|
+
options.timeout || (options.agent && options.agent.options.timeout)
|
|
58
|
+
if (timeout) {
|
|
59
|
+
this.socket.setTimeout(timeout)
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
this.response = new IncomingMessage(this.socket)
|
|
@@ -279,9 +286,8 @@ class InterceptedRequestRouter {
|
|
|
279
286
|
const requestBodyBuffer = Buffer.concat(this.requestBodyBuffers)
|
|
280
287
|
// When request body is a binary buffer we internally use in its hexadecimal
|
|
281
288
|
// representation.
|
|
282
|
-
const requestBodyIsUtf8Representable =
|
|
283
|
-
requestBodyBuffer
|
|
284
|
-
)
|
|
289
|
+
const requestBodyIsUtf8Representable =
|
|
290
|
+
common.isUtf8Representable(requestBodyBuffer)
|
|
285
291
|
const requestBodyString = requestBodyBuffer.toString(
|
|
286
292
|
requestBodyIsUtf8Representable ? 'utf8' : 'hex'
|
|
287
293
|
)
|
package/lib/interceptor.js
CHANGED
|
@@ -66,7 +66,8 @@ module.exports = class Interceptor {
|
|
|
66
66
|
|
|
67
67
|
// We use lower-case header field names throughout Nock.
|
|
68
68
|
this.reqheaders = common.headersFieldNamesToLowerCase(
|
|
69
|
-
scope.scopeOptions.reqheaders || {}
|
|
69
|
+
scope.scopeOptions.reqheaders || {},
|
|
70
|
+
true
|
|
70
71
|
)
|
|
71
72
|
this.badheaders = common.headersFieldsArrayToLowerCase(
|
|
72
73
|
scope.scopeOptions.badheaders || []
|
|
@@ -155,7 +156,7 @@ module.exports = class Interceptor {
|
|
|
155
156
|
)
|
|
156
157
|
|
|
157
158
|
// If the content is not encoded we may need to transform the response body.
|
|
158
|
-
// Otherwise we leave it as it is.
|
|
159
|
+
// Otherwise, we leave it as it is.
|
|
159
160
|
if (
|
|
160
161
|
body &&
|
|
161
162
|
typeof body !== 'string' &&
|
|
@@ -173,10 +174,14 @@ module.exports = class Interceptor {
|
|
|
173
174
|
// https://tools.ietf.org/html/rfc7231#section-3.1.1.5
|
|
174
175
|
this.rawHeaders.push('Content-Type', 'application/json')
|
|
175
176
|
}
|
|
177
|
+
}
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
if (this.scope.contentLen) {
|
|
180
|
+
// https://tools.ietf.org/html/rfc7230#section-3.3.2
|
|
181
|
+
if (typeof body === 'string') {
|
|
179
182
|
this.rawHeaders.push('Content-Length', body.length)
|
|
183
|
+
} else if (Buffer.isBuffer(body)) {
|
|
184
|
+
this.rawHeaders.push('Content-Length', body.byteLength)
|
|
180
185
|
}
|
|
181
186
|
}
|
|
182
187
|
|
|
@@ -412,6 +417,12 @@ module.exports = class Interceptor {
|
|
|
412
417
|
}
|
|
413
418
|
|
|
414
419
|
matchHostName(options) {
|
|
420
|
+
const { basePath } = this.scope
|
|
421
|
+
|
|
422
|
+
if (basePath instanceof RegExp) {
|
|
423
|
+
return basePath.test(options.hostname)
|
|
424
|
+
}
|
|
425
|
+
|
|
415
426
|
return options.hostname === this.scope.urlParts.hostname
|
|
416
427
|
}
|
|
417
428
|
|
|
@@ -79,7 +79,7 @@ class ReadableBuffers extends stream.Readable {
|
|
|
79
79
|
this.buffers = buffers
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
_read(
|
|
82
|
+
_read(_size) {
|
|
83
83
|
while (this.buffers.length) {
|
|
84
84
|
if (!this.push(this.buffers.shift())) {
|
|
85
85
|
return
|
|
@@ -315,7 +315,7 @@ function playbackInterceptor({
|
|
|
315
315
|
|
|
316
316
|
// Calling `start` immediately could take the request all the way to the connection delay
|
|
317
317
|
// during a single microtask execution. This setImmediate stalls the playback to ensure the
|
|
318
|
-
// correct events are emitted first ('socket', 'finish') and any aborts in the
|
|
318
|
+
// correct events are emitted first ('socket', 'finish') and any aborts in the queue or
|
|
319
319
|
// called during a 'finish' listener can be called.
|
|
320
320
|
common.setImmediate(() => {
|
|
321
321
|
if (!common.isRequestDestroyed(req)) {
|
package/lib/recorder.js
CHANGED
|
@@ -168,7 +168,7 @@ let currentRecordingId = 0
|
|
|
168
168
|
const defaultRecordOptions = {
|
|
169
169
|
dont_print: false,
|
|
170
170
|
enable_reqheaders_recording: false,
|
|
171
|
-
logging: console.log,
|
|
171
|
+
logging: console.log, // eslint-disable-line no-console
|
|
172
172
|
output_objects: false,
|
|
173
173
|
use_separator: true,
|
|
174
174
|
}
|
package/package.json
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
"testing",
|
|
8
8
|
"isolation"
|
|
9
9
|
],
|
|
10
|
-
"version": "13.
|
|
10
|
+
"version": "13.2.3",
|
|
11
11
|
"author": "Pedro Teixeira <pedro.teixeira@gmail.com>",
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
14
|
"url": "https://github.com/nock/nock.git"
|
|
15
15
|
},
|
|
16
16
|
"bugs": {
|
|
17
|
-
"url": "
|
|
17
|
+
"url": "https://github.com/nock/nock/issues"
|
|
18
18
|
},
|
|
19
19
|
"engines": {
|
|
20
20
|
"node": ">= 10.13"
|
|
@@ -28,30 +28,29 @@
|
|
|
28
28
|
"propagate": "^2.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@
|
|
31
|
+
"@definitelytyped/dtslint": "^0.0.103",
|
|
32
|
+
"@sinonjs/fake-timers": "^9.0.0",
|
|
32
33
|
"assert-rejects": "^1.0.0",
|
|
33
34
|
"chai": "^4.1.2",
|
|
34
35
|
"dirty-chai": "^2.0.1",
|
|
35
|
-
"
|
|
36
|
-
"eslint": "^7.3.1",
|
|
36
|
+
"eslint": "^8.8.0",
|
|
37
37
|
"eslint-config-prettier": "^8.1.0",
|
|
38
|
-
"eslint-config-standard": "^
|
|
38
|
+
"eslint-config-standard": "^17.0.0-0",
|
|
39
39
|
"eslint-plugin-import": "^2.16.0",
|
|
40
|
-
"eslint-plugin-mocha": "^
|
|
40
|
+
"eslint-plugin-mocha": "^10.0.3",
|
|
41
41
|
"eslint-plugin-node": "^11.0.0",
|
|
42
|
-
"eslint-plugin-promise": "^
|
|
43
|
-
"eslint-plugin-standard": "^5.0.0",
|
|
42
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
44
43
|
"form-data": "^4.0.0",
|
|
45
44
|
"got": "^11.3.0",
|
|
46
|
-
"mocha": "^
|
|
45
|
+
"mocha": "^9.1.3",
|
|
47
46
|
"npm-run-all": "^4.1.5",
|
|
48
47
|
"nyc": "^15.0.0",
|
|
49
|
-
"prettier": "2.
|
|
48
|
+
"prettier": "2.5.1",
|
|
50
49
|
"proxyquire": "^2.1.0",
|
|
51
50
|
"rimraf": "^3.0.0",
|
|
52
|
-
"semantic-release": "^
|
|
53
|
-
"sinon": "^
|
|
54
|
-
"sinon-chai": "^3.
|
|
51
|
+
"semantic-release": "^18.0.1",
|
|
52
|
+
"sinon": "^13.0.1",
|
|
53
|
+
"sinon-chai": "^3.7.0",
|
|
55
54
|
"typescript": "^4.2.2"
|
|
56
55
|
},
|
|
57
56
|
"scripts": {
|
|
@@ -61,7 +60,7 @@
|
|
|
61
60
|
"lint:js": "eslint --cache --cache-location './.cache/eslint' '**/*.js'",
|
|
62
61
|
"lint:js:fix": "eslint --cache --cache-location './.cache/eslint' --fix '**/*.js'",
|
|
63
62
|
"lint:ts": "dtslint types",
|
|
64
|
-
"test": "nyc mocha tests",
|
|
63
|
+
"test": "nyc --reporter=lcov --reporter=text mocha tests",
|
|
65
64
|
"test:coverage": "open coverage/lcov-report/index.html"
|
|
66
65
|
},
|
|
67
66
|
"license": "MIT",
|
package/types/index.d.ts
CHANGED
package/CHANGELOG.md
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
Nock’s changelog can be found directly in the [GitHub release notes](https://github.com/nock/nock/releases).
|
|
4
|
-
These are automatically created by [semantic-release](https://github.com/semantic-release/semantic-release) based on their [commit message conventions](https://semantic-release.gitbook.io/semantic-release#commit-message-format).
|
|
5
|
-
|
|
6
|
-
Migration guides are available for major versions in the [migration guides directory](https://github.com/nock/nock/tree/main/migration_guides).
|