node-tdd 3.0.5 → 3.1.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.
package/README.md
CHANGED
|
@@ -80,12 +80,13 @@ Can be used in the following ways:
|
|
|
80
80
|
|
|
81
81
|
- `--nock-heal`: Will try to heal ordering of nock cassette recordings
|
|
82
82
|
- `--nock-heal prune`: Will remove unmatched recordings from nock cassette
|
|
83
|
+
- `--nock-heal headers`: Will try to heal request headers of nock cassette recordings
|
|
83
84
|
- `--nock-heal body`: Will try to heal bodies of nock cassette recordings
|
|
84
85
|
- `--nock-heal path`: Will try to heal paths of nock cassette recordings
|
|
85
86
|
- `--nock-heal response`: Will try to heal responses
|
|
86
87
|
- `--nock-heal record`: Will record the next unmatched request
|
|
87
88
|
- `--nock-heal stub`: Will stub the next unmatched request
|
|
88
|
-
- `--nock-heal magic`: Shorthand for `
|
|
89
|
+
- `--nock-heal magic`: Shorthand for `headers,body,path,response`
|
|
89
90
|
|
|
90
91
|
Notes:
|
|
91
92
|
- Different flags can be combined as e.g. `--nock-heal body,path`
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const nockCommon = require('nock/lib/common');
|
|
4
4
|
|
|
5
|
-
const fns = ['setInterval', 'setTimeout'];
|
|
5
|
+
const fns = ['setInterval', 'setTimeout', 'deleteHeadersField'];
|
|
6
6
|
const originals = fns.reduce((p, c) => Object.assign(p, {
|
|
7
7
|
[c]: nockCommon[c]
|
|
8
8
|
}), {});
|
|
@@ -10,6 +10,10 @@ module.exports = {
|
|
|
10
10
|
patch: () => {
|
|
11
11
|
fns.forEach(fn => {
|
|
12
12
|
nockCommon[fn] = (...args) => {
|
|
13
|
+
if (fn === 'deleteHeadersField') {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
if (args[1] === 0) {
|
|
14
18
|
return args[0](...args.slice(2));
|
|
15
19
|
}
|
|
@@ -6,7 +6,7 @@ const http = require('http');
|
|
|
6
6
|
|
|
7
7
|
const https = require('https');
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const nockCommon = require('nock/lib/common');
|
|
10
10
|
|
|
11
11
|
let lastProtocol = null;
|
|
12
12
|
let lastOptions = null;
|
|
@@ -21,7 +21,7 @@ const wrapper = proto => {
|
|
|
21
21
|
|
|
22
22
|
const requestWrapper = (...args) => {
|
|
23
23
|
lastProtocol = proto;
|
|
24
|
-
lastOptions =
|
|
24
|
+
lastOptions = nockCommon.normalizeClientRequestArgs(...args).options;
|
|
25
25
|
lastBody.length = 0;
|
|
26
26
|
const result = requestOriginal.call(protocol, ...args);
|
|
27
27
|
const writeOriginal = result.write;
|
|
@@ -24,4 +24,12 @@ module.exports.convertHeaders = array => {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
return obj;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
module.exports.rewriteHeaders = (headers, fn = (k, v) => v) => {
|
|
30
|
+
if (headers === undefined) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return Object.fromEntries(Object.entries(headers).sort(([a], [b]) => a > b ? 1 : -1).map(([k, v]) => [k.toLowerCase(), fn(k, v)]));
|
|
27
35
|
};
|
|
@@ -16,6 +16,10 @@ const nock = require('nock');
|
|
|
16
16
|
|
|
17
17
|
const cloneDeep = require('lodash.clonedeep');
|
|
18
18
|
|
|
19
|
+
const compareUrls = require('compare-urls');
|
|
20
|
+
|
|
21
|
+
const nockCommon = require('nock/lib/common');
|
|
22
|
+
|
|
19
23
|
const nockListener = require('./request-recorder/nock-listener');
|
|
20
24
|
|
|
21
25
|
const nockMock = require('./request-recorder/nock-mock');
|
|
@@ -28,7 +32,8 @@ const {
|
|
|
28
32
|
buildKey,
|
|
29
33
|
tryParseJson,
|
|
30
34
|
nullAsString,
|
|
31
|
-
convertHeaders
|
|
35
|
+
convertHeaders,
|
|
36
|
+
rewriteHeaders
|
|
32
37
|
} = require('./request-recorder/util');
|
|
33
38
|
|
|
34
39
|
const requestInjector = require('./request-recorder/request-injector');
|
|
@@ -99,7 +104,7 @@ module.exports = opts => {
|
|
|
99
104
|
nockRecorder.rec({
|
|
100
105
|
output_objects: true,
|
|
101
106
|
dont_print: true,
|
|
102
|
-
enable_reqheaders_recording:
|
|
107
|
+
enable_reqheaders_recording: true
|
|
103
108
|
});
|
|
104
109
|
await new Promise(resolve => {
|
|
105
110
|
options.protocol = `${protocol}:`;
|
|
@@ -131,6 +136,7 @@ module.exports = opts => {
|
|
|
131
136
|
path: options.path,
|
|
132
137
|
body: tryParseJson(body),
|
|
133
138
|
status: 200,
|
|
139
|
+
reqheaders: rewriteHeaders(options.headers),
|
|
134
140
|
response: {},
|
|
135
141
|
responseIsBinary: false
|
|
136
142
|
});
|
|
@@ -141,6 +147,19 @@ module.exports = opts => {
|
|
|
141
147
|
records.push(cloneDeep(scope));
|
|
142
148
|
applyModifiers(scope, opts.modifiers); // eslint-disable-next-line no-param-reassign
|
|
143
149
|
|
|
150
|
+
scope.reqheaders = rewriteHeaders(scope.reqheaders, (k, valueRecording) => valueRequest => {
|
|
151
|
+
const match = nockCommon.matchStringOrRegexp(valueRequest, /^\^.*\$$/.test(valueRecording) ? new RegExp(valueRecording) : valueRecording);
|
|
152
|
+
|
|
153
|
+
if (!match && anyFlagPresent(['magic', 'headers'])) {
|
|
154
|
+
const idx = pendingMocks.findIndex(m => m.idx === scopeIdx); // overwrite existing headers
|
|
155
|
+
|
|
156
|
+
pendingMocks[idx].record.reqheaders[k] = valueRequest;
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return match;
|
|
161
|
+
}); // eslint-disable-next-line no-param-reassign
|
|
162
|
+
|
|
144
163
|
scope.filteringRequestBody = body => {
|
|
145
164
|
if (anyFlagPresent(['magic', 'body'])) {
|
|
146
165
|
const idx = pendingMocks.findIndex(m => m.idx === scopeIdx);
|
|
@@ -156,7 +175,11 @@ module.exports = opts => {
|
|
|
156
175
|
scope.filteringPath = requestPath => {
|
|
157
176
|
if (anyFlagPresent(['magic', 'path'])) {
|
|
158
177
|
const idx = pendingMocks.findIndex(m => m.idx === scopeIdx);
|
|
159
|
-
|
|
178
|
+
|
|
179
|
+
if (!compareUrls(pendingMocks[idx].record.path, requestPath)) {
|
|
180
|
+
pendingMocks[idx].record.path = requestPath;
|
|
181
|
+
}
|
|
182
|
+
|
|
160
183
|
return scope.path;
|
|
161
184
|
}
|
|
162
185
|
|
|
@@ -169,6 +192,13 @@ module.exports = opts => {
|
|
|
169
192
|
scope.on('request', (req, interceptor, requestBodyString) => {
|
|
170
193
|
const idx = pendingMocks.findIndex(e => e.idx === scopeIdx);
|
|
171
194
|
|
|
195
|
+
if (anyFlagPresent(['magic', 'headers'])) {
|
|
196
|
+
// add new headers
|
|
197
|
+
pendingMocks[idx].record.reqheaders = { ...rewriteHeaders(req.headers),
|
|
198
|
+
...rewriteHeaders(pendingMocks[idx].record.reqheaders)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
172
202
|
if (anyFlagPresent(['magic', 'response'])) {
|
|
173
203
|
const responseBody = tryParseJson([healSqsSendMessageBatch].reduce((respBody, fn) => fn(requestBodyString, respBody, scope), interceptor.body)); // eslint-disable-next-line no-param-reassign
|
|
174
204
|
|
|
@@ -187,7 +217,8 @@ module.exports = opts => {
|
|
|
187
217
|
},
|
|
188
218
|
afterRecord: recordings => JSON.stringify(recordings.map(r => ({ ...r,
|
|
189
219
|
body: tryParseJson(r.body),
|
|
190
|
-
rawHeaders: opts.stripHeaders === true ? undefined : r.rawHeaders
|
|
220
|
+
rawHeaders: opts.stripHeaders === true ? undefined : r.rawHeaders,
|
|
221
|
+
reqheaders: rewriteHeaders(r.reqheaders)
|
|
191
222
|
})), null, 2)
|
|
192
223
|
}, resolve));
|
|
193
224
|
requestInjector.inject();
|
|
@@ -195,10 +226,6 @@ module.exports = opts => {
|
|
|
195
226
|
release: async () => {
|
|
196
227
|
assert(nockDone !== null);
|
|
197
228
|
requestInjector.release();
|
|
198
|
-
nockDone();
|
|
199
|
-
nockDone = null;
|
|
200
|
-
nockListener.unsubscribeAll('no match');
|
|
201
|
-
nockMock.unpatch();
|
|
202
229
|
|
|
203
230
|
for (let idx = 0; idx < expectedCassette.length; idx += 1) {
|
|
204
231
|
if (typeof expectedCassette[idx] === 'function') {
|
|
@@ -208,8 +235,13 @@ module.exports = opts => {
|
|
|
208
235
|
}
|
|
209
236
|
}
|
|
210
237
|
|
|
238
|
+
nockDone();
|
|
239
|
+
nockDone = null;
|
|
240
|
+
nockListener.unsubscribeAll('no match');
|
|
241
|
+
nockMock.unpatch();
|
|
242
|
+
|
|
211
243
|
if (opts.heal !== false) {
|
|
212
|
-
fs.smartWrite(cassetteFilePath, anyFlagPresent(['
|
|
244
|
+
fs.smartWrite(cassetteFilePath, anyFlagPresent(['prune']) ? expectedCassette : [...expectedCassette, ...pendingMocks.map(({
|
|
213
245
|
record
|
|
214
246
|
}) => record)], {
|
|
215
247
|
keepOrder: outOfOrderErrors.length === 0 && pendingMocks.length === 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-tdd",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"description": "Drop in extension for mocha to abstract commonly used test setups",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@blackflux/robo-config-plugin": "5.3.0",
|
|
49
49
|
"aws-sdk": "2.981.0",
|
|
50
50
|
"aws-sdk-wrap": "9.6.0",
|
|
51
|
-
"axios": "0.
|
|
51
|
+
"axios": "0.24.0",
|
|
52
52
|
"babel-eslint": "10.1.0",
|
|
53
53
|
"babel-preset-latest-node": "5.5.1",
|
|
54
54
|
"chai": "4.3.4",
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
],
|
|
110
110
|
"dependencies": {
|
|
111
111
|
"callsites": "3.1.0",
|
|
112
|
+
"compare-urls": "2.0.0",
|
|
112
113
|
"joi-strict": "2.0.0",
|
|
113
114
|
"lodash.clonedeep": "4.5.0",
|
|
114
115
|
"lodash.get": "4.4.2",
|