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 `prune,body,path,response`
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 common = require('nock/lib/common');
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 = common.normalizeClientRequestArgs(...args).options;
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: false
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
- pendingMocks[idx].record.path = requestPath;
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(['magic', 'prune']) ? expectedCassette : [...expectedCassette, ...pendingMocks.map(({
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.0.5",
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.21.1",
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",