node-tdd 3.0.4 → 3.1.1

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).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
 
@@ -195,10 +225,6 @@ module.exports = opts => {
195
225
  release: async () => {
196
226
  assert(nockDone !== null);
197
227
  requestInjector.release();
198
- nockDone();
199
- nockDone = null;
200
- nockListener.unsubscribeAll('no match');
201
- nockMock.unpatch();
202
228
 
203
229
  for (let idx = 0; idx < expectedCassette.length; idx += 1) {
204
230
  if (typeof expectedCassette[idx] === 'function') {
@@ -208,8 +234,13 @@ module.exports = opts => {
208
234
  }
209
235
  }
210
236
 
237
+ nockDone();
238
+ nockDone = null;
239
+ nockListener.unsubscribeAll('no match');
240
+ nockMock.unpatch();
241
+
211
242
  if (opts.heal !== false) {
212
- fs.smartWrite(cassetteFilePath, anyFlagPresent(['magic', 'prune']) ? expectedCassette : [...expectedCassette, ...pendingMocks.map(({
243
+ fs.smartWrite(cassetteFilePath, anyFlagPresent(['prune']) ? expectedCassette : [...expectedCassette, ...pendingMocks.map(({
213
244
  record
214
245
  }) => record)], {
215
246
  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.4",
3
+ "version": "3.1.1",
4
4
  "description": "Drop in extension for mocha to abstract commonly used test setups",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -41,29 +41,29 @@
41
41
  },
42
42
  "homepage": "https://github.com/blackflux/node-tdd#readme",
43
43
  "devDependencies": {
44
- "@babel/cli": "7.13.10",
45
- "@babel/core": "7.13.10",
46
- "@babel/register": "7.13.8",
44
+ "@babel/cli": "7.14.8",
45
+ "@babel/core": "7.15.0",
46
+ "@babel/register": "7.15.3",
47
47
  "@blackflux/eslint-plugin-rules": "2.0.3",
48
- "@blackflux/robo-config-plugin": "5.0.0",
49
- "aws-sdk": "2.865.0",
50
- "aws-sdk-wrap": "9.2.4",
51
- "axios": "0.21.1",
48
+ "@blackflux/robo-config-plugin": "5.3.0",
49
+ "aws-sdk": "2.981.0",
50
+ "aws-sdk-wrap": "9.6.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",
55
- "coveralls": "3.1.0",
56
- "eslint": "7.22.0",
55
+ "coveralls": "3.1.1",
56
+ "eslint": "7.32.0",
57
57
  "eslint-config-airbnb-base": "14.2.1",
58
- "eslint-plugin-import": "2.22.1",
59
- "eslint-plugin-json": "2.1.2",
60
- "eslint-plugin-markdown": "2.0.0",
61
- "eslint-plugin-mocha": "8.1.0",
58
+ "eslint-plugin-import": "2.24.2",
59
+ "eslint-plugin-json": "3.1.0",
60
+ "eslint-plugin-markdown": "2.2.0",
61
+ "eslint-plugin-mocha": "9.0.0",
62
62
  "fancy-log": "1.3.3",
63
- "js-gardener": "3.0.1",
63
+ "js-gardener": "3.0.3",
64
64
  "lambda-monitor-logger": "3.0.0",
65
65
  "nyc": "15.1.0",
66
- "semantic-release": "17.4.2"
66
+ "semantic-release": "17.4.7"
67
67
  },
68
68
  "licenses": [
69
69
  {
@@ -109,12 +109,13 @@
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",
115
116
  "minimist": "1.2.5",
116
- "nock": "13.0.11",
117
- "object-scan": "14.0.0",
117
+ "nock": "13.1.3",
118
+ "object-scan": "17.0.0",
118
119
  "smart-fs": "2.0.2",
119
120
  "timekeeper": "2.2.0",
120
121
  "tmp": "0.2.1",