http-snapshotter 0.6.1-beta.2 → 0.6.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 (4) hide show
  1. package/README.md +25 -0
  2. package/index.d.ts +22 -0
  3. package/index.js +61 -11
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -230,3 +230,28 @@ resetSnapshotIgnoreRules();
230
230
  **Behavior varies by mode:**
231
231
  - `SNAPSHOT=update/append`: Ignored requests make real network calls but don't create snapshots
232
232
  - `SNAPSHOT=read`: Ignored requests throw an error (tests shouldn't make real network calls)
233
+
234
+ ## Passthrough requests from snapshots
235
+
236
+ If a request should explicitly be allowed to hit the real network in every mode, including
237
+ `SNAPSHOT=read`, use `attachSnapshotPassthroughRules()` instead:
238
+
239
+ ```js
240
+ import {
241
+ attachSnapshotPassthroughRules,
242
+ resetSnapshotPassthroughRules,
243
+ } from "http-snapshotter";
244
+
245
+ attachSnapshotPassthroughRules((request) => {
246
+ const url = new URL(request.url);
247
+ return url.hostname === "portal.sso.eu-west-1.amazonaws.com"
248
+ && url.pathname === "/federation/credentials";
249
+ });
250
+
251
+ resetSnapshotPassthroughRules();
252
+ ```
253
+
254
+ **Behavior:**
255
+ - Requests matching passthrough rules always make real network calls
256
+ - Requests matching passthrough rules never create or read snapshots
257
+ - Passthrough rules take precedence over ignore rules
package/index.d.ts CHANGED
@@ -125,6 +125,28 @@ export function defaultSnapshotIgnoreRules(_request: Request): boolean;
125
125
  export function attachSnapshotIgnoreRules(func: (req: Request) => boolean): void;
126
126
  /** Reset snapshot ignore rules to default (no requests ignored) */
127
127
  export function resetSnapshotIgnoreRules(): void;
128
+ /**
129
+ * Default snapshot passthrough rules - by default no requests bypass snapshotting
130
+ * @param {Request} _request
131
+ * @returns {boolean}
132
+ */
133
+ export function defaultSnapshotPassthroughRules(_request: Request): boolean;
134
+ /**
135
+ * Attach snapshot passthrough rules function
136
+ *
137
+ * Use this when a request should explicitly bypass snapshotting and always be allowed to hit
138
+ * the real network, regardless of SNAPSHOT mode.
139
+ *
140
+ * Passthrough rules take precedence over ignore rules.
141
+ *
142
+ * WARNING: Attaching a function on a per-test basis may not be concurrent safe. i.e. If your tests
143
+ * run sequentially, then it is safe. But if your test runner runs test suites concurrently,
144
+ * then it is better to attach a function only once ever.
145
+ * @param {(req: Request) => boolean} func
146
+ */
147
+ export function attachSnapshotPassthroughRules(func: (req: Request) => boolean): void;
148
+ /** Reset snapshot passthrough rules to default (no requests bypass snapshotting) */
149
+ export function resetSnapshotPassthroughRules(): void;
128
150
  /**
129
151
  * Start the interceptor
130
152
  * @param {object} opts
package/index.js CHANGED
@@ -179,6 +179,15 @@ function defaultSnapshotIgnoreRules(_request) {
179
179
  return false;
180
180
  }
181
181
 
182
+ /**
183
+ * Default snapshot passthrough rules - by default no requests bypass snapshotting
184
+ * @param {Request} _request
185
+ * @returns {boolean}
186
+ */
187
+ function defaultSnapshotPassthroughRules(_request) {
188
+ return false;
189
+ }
190
+
182
191
  // Dynamically changeable props
183
192
  /**
184
193
  * @type {(req: Request) => Promise<{ filePrefix: string, fileSuffixKey: string }>}
@@ -190,6 +199,10 @@ let snapshotSubDirectory = '';
190
199
  * @type {(req: Request) => boolean}
191
200
  */
192
201
  let snapshotIgnoreRules = defaultSnapshotIgnoreRules;
202
+ /**
203
+ * @type {(req: Request) => boolean}
204
+ */
205
+ let snapshotPassthroughRules = defaultSnapshotPassthroughRules;
193
206
 
194
207
  /**
195
208
  * @typedef SnapshotFileInfo
@@ -674,6 +687,28 @@ function resetSnapshotIgnoreRules() {
674
687
  snapshotIgnoreRules = defaultSnapshotIgnoreRules;
675
688
  }
676
689
 
690
+ /**
691
+ * Attach snapshot passthrough rules function
692
+ *
693
+ * Use this when a request should explicitly bypass snapshotting and always be allowed to hit
694
+ * the real network, regardless of SNAPSHOT mode.
695
+ *
696
+ * Passthrough rules take precedence over ignore rules.
697
+ *
698
+ * WARNING: Attaching a function on a per-test basis may not be concurrent safe. i.e. If your tests
699
+ * run sequentially, then it is safe. But if your test runner runs test suites concurrently,
700
+ * then it is better to attach a function only once ever.
701
+ * @param {(req: Request) => boolean} func
702
+ */
703
+ function attachSnapshotPassthroughRules(func) {
704
+ snapshotPassthroughRules = func;
705
+ }
706
+
707
+ /** Reset snapshot passthrough rules to default (no requests bypass snapshotting) */
708
+ function resetSnapshotPassthroughRules() {
709
+ snapshotPassthroughRules = defaultSnapshotPassthroughRules;
710
+ }
711
+
677
712
  /**
678
713
  * Start the interceptor
679
714
  * @param {object} opts
@@ -701,9 +736,16 @@ function start({
701
736
 
702
737
  const cache = /** @type {WeakMap<Request, SnapshotFileInfo>} */ (new WeakMap());
703
738
  const ignoredRequests = /** @type {WeakSet<Request>} */ (new WeakSet());
739
+ const passthroughRequests = /** @type {WeakSet<Request>} */ (new WeakSet());
704
740
 
705
741
  //@ts-ignore
706
742
  interceptor.on('request', async ({ request, controller }) => {
743
+ const shouldPassthroughSnapshot = snapshotPassthroughRules(request);
744
+ if (shouldPassthroughSnapshot) {
745
+ passthroughRequests.add(request);
746
+ return;
747
+ }
748
+
707
749
  // Check if request should be ignored from snapshotting using ignore rules
708
750
  const shouldIgnoreSnapshot = snapshotIgnoreRules(request);
709
751
 
@@ -739,19 +781,22 @@ function start({
739
781
  'response',
740
782
  /** @type {(params: { request: Request, response: Response }) => Promise<void>} */
741
783
  async ({ request, response }) => {
784
+ const shouldPassthroughSnapshot = passthroughRequests.has(request);
742
785
  // Check if this request was marked to ignore snapshots
743
786
  const shouldIgnoreSnapshot = ignoredRequests.has(request);
744
-
745
- const snapshotFileInfo = cache.get(request) || (await getSnapshotFileInfo(request));
787
+
788
+ const snapshotFileInfo = shouldPassthroughSnapshot
789
+ ? null
790
+ : (cache.get(request) || (await getSnapshotFileInfo(request)));
746
791
  cache.delete(request);
747
-
748
- const {
749
- // absoluteFilePath,
750
- fileName,
751
- fileSuffixKey,
752
- } = snapshotFileInfo;
792
+
793
+ const fileName = snapshotFileInfo?.fileName;
794
+ const fileSuffixKey = snapshotFileInfo?.fileSuffixKey;
753
795
  if (LOG_REQ) {
754
796
  const summary = `----------\n${request.method} ${request.url}\n${
797
+ shouldPassthroughSnapshot
798
+ ? 'passed through by passthrough rules'
799
+ :
755
800
  shouldIgnoreSnapshot
756
801
  ? 'ignored from snapshotting by ignore rules'
757
802
  : `Would use file name: ${fileName}`
@@ -776,12 +821,14 @@ function start({
776
821
  });
777
822
  }
778
823
  }
779
- if (!shouldIgnoreSnapshot && (SNAPSHOT === 'update' || (SNAPSHOT === 'append' && !readFiles.has(fileName)))) {
824
+ if (!shouldPassthroughSnapshot
825
+ && !shouldIgnoreSnapshot
826
+ && (SNAPSHOT === 'update' || (SNAPSHOT === 'append' && !readFiles.has(fileName)))) {
780
827
  if (!dirCreatePromise) {
781
828
  dirCreatePromise = fs.mkdir( /** @type {string} */(snapshotDirectory), { recursive: true });
782
829
  }
783
830
  await dirCreatePromise;
784
- await saveSnapshot(request, response, snapshotFileInfo);
831
+ await saveSnapshot(request, response, /** @type {SnapshotFileInfo} */ (snapshotFileInfo));
785
832
  }
786
833
  },
787
834
  );
@@ -806,6 +853,9 @@ module.exports = {
806
853
  defaultSnapshotIgnoreRules,
807
854
  attachSnapshotIgnoreRules,
808
855
  resetSnapshotIgnoreRules,
856
+ defaultSnapshotPassthroughRules,
857
+ attachSnapshotPassthroughRules,
858
+ resetSnapshotPassthroughRules,
809
859
  start,
810
860
  stop,
811
- };
861
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "http-snapshotter",
3
- "version": "0.6.1-beta.2",
3
+ "version": "0.6.2",
4
4
  "description": "Snapshot HTTP requests for tests (node.js)",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",