@jsenv/snapshot 2.14.1 → 2.15.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/snapshot",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"description": "Snapshot testing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
],
|
|
32
32
|
"sideEffects": false,
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@jsenv/assert": "4.4.
|
|
35
|
-
"@jsenv/ast": "6.6.
|
|
34
|
+
"@jsenv/assert": "4.4.6",
|
|
35
|
+
"@jsenv/ast": "6.6.9",
|
|
36
36
|
"@jsenv/exception": "1.1.7",
|
|
37
|
-
"@jsenv/humanize": "1.
|
|
38
|
-
"@jsenv/filesystem": "4.
|
|
39
|
-
"@jsenv/terminal-recorder": "1.5.
|
|
40
|
-
"@jsenv/urls": "2.7.
|
|
37
|
+
"@jsenv/humanize": "1.5.0",
|
|
38
|
+
"@jsenv/filesystem": "4.15.0",
|
|
39
|
+
"@jsenv/terminal-recorder": "1.5.14",
|
|
40
|
+
"@jsenv/urls": "2.7.2",
|
|
41
41
|
"@jsenv/utils": "2.3.0",
|
|
42
42
|
"ansi-regex": "6.1.0",
|
|
43
43
|
"pixelmatch": "7.1.0",
|
package/readme.md
CHANGED
|
@@ -2,38 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@jsenv/snapshot)
|
|
4
4
|
|
|
5
|
-
A
|
|
5
|
+
A powerful snapshot testing tool for JavaScript applications.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Introduction to Snapshot Testing
|
|
8
8
|
|
|
9
|
-
Snapshot testing
|
|
9
|
+
Snapshot testing is a technique that:
|
|
10
10
|
|
|
11
|
-
1.
|
|
12
|
-
2.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
1. Captures the output of code execution into files (snapshots)
|
|
12
|
+
2. Validates future code changes by:
|
|
13
|
+
- Reading the existing snapshot
|
|
14
|
+
- Executing the code
|
|
15
|
+
- Generating a new snapshot
|
|
16
|
+
- Comparing the two snapshots and reporting differences
|
|
17
17
|
|
|
18
|
-
This
|
|
18
|
+
This approach ensures your code continues to behave as expected by verifying its outputs remain consistent over time.
|
|
19
19
|
|
|
20
|
-
## How
|
|
20
|
+
## How `@jsenv/snapshot` Works
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
When running tests:
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
- **First run**: If no snapshot exists, one will be generated without comparison
|
|
25
|
+
- **Subsequent runs**: Snapshots are compared with the following behavior:
|
|
26
|
+
- In CI environments (`process.env.CI` is set): An error is thrown if differences are detected
|
|
27
|
+
- Locally: No error is thrown, allowing you to review changes with tools like git diff
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
> **Note**: All functions accept a throwWhenDiff parameter to force errors even in local environments.
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
- Otherwise nothing special happens (it's your job to review eventual diff in the snapshots, using `git diff` for example)
|
|
31
|
+
## API Reference
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
### takeFileSnapshot(fileUrl)
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
The code below ensure `writeFileTxt` write `content` into "./file.txt".
|
|
36
|
-
Changing that behaviour would fail snapshot comparison.
|
|
35
|
+
Captures and compares the state of a specific file.
|
|
37
36
|
|
|
38
37
|
```js
|
|
39
38
|
import { writeFileSync } from "node:fs";
|
|
@@ -51,10 +50,9 @@ writeFileTxt("Hello world");
|
|
|
51
50
|
fileSnapshot.compare();
|
|
52
51
|
```
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
### takeDirectorySnapshot(directoryUrl)
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
Changing that behaviour would fail snapshot comparison.
|
|
55
|
+
Captures and compares the state of an entire directory.
|
|
58
56
|
|
|
59
57
|
```js
|
|
60
58
|
import { writeFileSync } from "node:fs";
|
|
@@ -73,9 +71,9 @@ writeFileTxt(directoryUrl);
|
|
|
73
71
|
directorySnapshot.compare();
|
|
74
72
|
```
|
|
75
73
|
|
|
76
|
-
|
|
74
|
+
### snapshotTests(testFileUrl, fnRegistertingTests, options)
|
|
77
75
|
|
|
78
|
-
|
|
76
|
+
The most powerful feature of this library - creates readable markdown snapshots of test executions.
|
|
79
77
|
|
|
80
78
|
```js
|
|
81
79
|
import { snapshotTests } from "@jsenv/snapshot";
|
|
@@ -104,46 +102,38 @@ await snapshotTests(import.meta.url, ({ test }) => {
|
|
|
104
102
|
});
|
|
105
103
|
```
|
|
106
104
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
See the markdown at [./docs/\_circle_area.test.js/circle_area.test.js.md](./docs/_circle_area.test.js/circle_area.test.js.md)
|
|
105
|
+
This generates a markdown file documenting how your code behaves in different scenarios.
|
|
106
|
+
See an example at [./docs/\_circle_area.test.js/circle_area.test.js.md](./docs/_circle_area.test.js/circle_area.test.js.md)
|
|
111
107
|
|
|
112
|
-
Why
|
|
108
|
+
## Why Use snapshotTests?
|
|
113
109
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
110
|
+
- **Assertion-free testing**: Simply call your functions and let the snapshots document their behavior
|
|
111
|
+
- **Self-documenting tests**: Markdown files serve as both test validation and documentation
|
|
112
|
+
- **Visual change reviews**: Code changes are reflected in snapshots, making reviews easy
|
|
113
|
+
- **Side effect tracking**: Automatically captures and documents:
|
|
118
114
|
|
|
119
|
-
|
|
115
|
+
- Console logs [example](./docs/_log.test.js/log.test.js.md)
|
|
116
|
+
- Filesystem operations [example](./docs/_filesystem.test.js/filesystem.test.js.md)
|
|
117
|
+
- And more
|
|
120
118
|
|
|
121
|
-
- Log side effects are catched, see [./docs/\_logs.test.js/log.test.js.md](./docs/_log.test.js/log.test.js.md)
|
|
122
|
-
- Filesystem side effects are catched and undone, see [./docs/\_filesystem.test.js/filesystem.test.js.md](./docs/_filesystem.test.js/filesystem.test.js.md)
|
|
123
119
|
- Fluctuating values are replaced with stable values, see [#Fluctuating values replacement](#fluctuating-values-replacement)
|
|
124
120
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
- Tests how `assert` throw in many different ways: [@jsenv/assert/tests/array.test.js.md](../assert/tests/_array.test.js/array.test.js.md).
|
|
128
|
-
- Tests generating build files, starting a server and executing build files in a browser: [@jsenv/core/tests/script_type_module_basic.test.mjs](../../../tests/build/basics/script_type_module_basic/_script_type_module_basic.test.mjs/script_type_module_basic.test.mjs.md).
|
|
121
|
+
## Stable Snapshots Across Environments
|
|
129
122
|
|
|
130
|
-
|
|
123
|
+
To ensure snapshots remain consistent across different machines and CI environments, `@jsenv/snapshot` automatically normalizes fluctuating values:
|
|
131
124
|
|
|
132
|
-
|
|
125
|
+
- Time values like "2s" become "Xs"
|
|
126
|
+
- Filesystem paths are standardized
|
|
127
|
+
- Network ports in URLs are removed
|
|
128
|
+
- And much more...
|
|
133
129
|
|
|
134
|
-
|
|
130
|
+
This ensures your snapshot tests remain stable regardless of when or where they run.
|
|
135
131
|
|
|
136
|
-
|
|
137
|
-
- operating system
|
|
138
|
-
- filesystem location
|
|
139
|
-
- available ressources,
|
|
140
|
-
- and so on...
|
|
132
|
+
## Advanced Examples
|
|
141
133
|
|
|
142
|
-
|
|
134
|
+
- Testing complex assertion behavior: [@jsenv/assert/tests/array.test.js.md](../assert/tests/_array.test.js/array.test.js.md)
|
|
135
|
+
- Testing server-side builds with browser execution: [@jsenv/core/tests/script_type_module_basic.test.mjs](../../../tests/build/basics/script_type_module_basic/_script_type_module_basic.test.mjs/script_type_module_basic.test.mjs.md)
|
|
143
136
|
|
|
144
|
-
|
|
145
|
-
- Filesystem urls dynamic parts are replaced
|
|
146
|
-
- Port in https urls is removed
|
|
147
|
-
- and so on...
|
|
137
|
+
## Contributing
|
|
148
138
|
|
|
149
|
-
If
|
|
139
|
+
If you encounter unstable snapshots due to fluctuating values not being properly normalized, please open an issue or submit a pull request.
|
|
@@ -9,6 +9,8 @@ const executionEffectsDefault = {
|
|
|
9
9
|
return: true,
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
let currentCapture = false;
|
|
13
|
+
|
|
12
14
|
export const createCaptureSideEffects = ({
|
|
13
15
|
sourceFileUrl,
|
|
14
16
|
logEffects = true,
|
|
@@ -50,6 +52,7 @@ export const createCaptureSideEffects = ({
|
|
|
50
52
|
replaceFilesystemWellKnownValues,
|
|
51
53
|
};
|
|
52
54
|
let functionExecutingCount = 0;
|
|
55
|
+
let ignored = false;
|
|
53
56
|
const capture = (fn, { callSite, baseDirectory } = {}) => {
|
|
54
57
|
const unicodeSupported = UNICODE.supported;
|
|
55
58
|
const ansiSupported = ANSI.supported;
|
|
@@ -74,6 +77,7 @@ export const createCaptureSideEffects = ({
|
|
|
74
77
|
};
|
|
75
78
|
const onSideEffectRemoved = () => {};
|
|
76
79
|
const addSideEffect = (sideEffect) => {
|
|
80
|
+
if (ignored) return null;
|
|
77
81
|
sideEffects.push(sideEffect);
|
|
78
82
|
onSideEffectAdded(sideEffect);
|
|
79
83
|
return sideEffect;
|
|
@@ -286,6 +290,7 @@ export const createCaptureSideEffects = ({
|
|
|
286
290
|
});
|
|
287
291
|
};
|
|
288
292
|
const onFinally = () => {
|
|
293
|
+
currentCapture = null;
|
|
289
294
|
delete process.env.CAPTURING_SIDE_EFFECTS;
|
|
290
295
|
UNICODE.supported = unicodeSupported;
|
|
291
296
|
ANSI.supported = ansiSupported;
|
|
@@ -326,6 +331,13 @@ export const createCaptureSideEffects = ({
|
|
|
326
331
|
process.env.CAPTURING_SIDE_EFFECTS = "1";
|
|
327
332
|
functionExecutingCount++;
|
|
328
333
|
let returnedPromise = false;
|
|
334
|
+
currentCapture = {
|
|
335
|
+
ignoreWhile: (fn) => {
|
|
336
|
+
ignored = true;
|
|
337
|
+
fn();
|
|
338
|
+
ignored = false;
|
|
339
|
+
},
|
|
340
|
+
};
|
|
329
341
|
try {
|
|
330
342
|
const valueReturned = fn();
|
|
331
343
|
if (valueReturned && typeof valueReturned.then === "function") {
|
|
@@ -355,7 +367,17 @@ export const createCaptureSideEffects = ({
|
|
|
355
367
|
}
|
|
356
368
|
}
|
|
357
369
|
};
|
|
370
|
+
capture.ignoreSideEffects = ignoreSideEffects;
|
|
371
|
+
|
|
358
372
|
return capture;
|
|
359
373
|
};
|
|
360
374
|
|
|
375
|
+
export const ignoreSideEffects = (fn) => {
|
|
376
|
+
if (!currentCapture) {
|
|
377
|
+
console.warn(`ignoreSideEffects called outside of captureSideEffects`);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
currentCapture.ignoreWhile(fn);
|
|
381
|
+
};
|
|
382
|
+
|
|
361
383
|
const RETURN_PROMISE = {};
|
|
@@ -2,7 +2,10 @@ import { writeFileSync } from "@jsenv/filesystem";
|
|
|
2
2
|
import { urlToBasename, urlToFilename, urlToRelativeUrl } from "@jsenv/urls";
|
|
3
3
|
import { takeDirectorySnapshot } from "../filesystem_snapshot.js";
|
|
4
4
|
import { getCallerLocation } from "../get_caller_location.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
createCaptureSideEffects,
|
|
7
|
+
ignoreSideEffects,
|
|
8
|
+
} from "./create_capture_side_effects.js";
|
|
6
9
|
import { renderSideEffects, renderSmallLink } from "./render_side_effects.js";
|
|
7
10
|
|
|
8
11
|
/**
|
|
@@ -235,11 +238,12 @@ export const snapshotTests = async (
|
|
|
235
238
|
// snapshotTests.prefConfigure(options)
|
|
236
239
|
// snapshotTests(import.meta.url, ({ test }) => { })
|
|
237
240
|
// which are equivalent
|
|
238
|
-
|
|
239
241
|
snapshotTests.prefConfigure = (options) => {
|
|
240
242
|
preconfiguredOptions = options;
|
|
241
243
|
};
|
|
242
244
|
|
|
245
|
+
snapshotTests.ignoreSideEffects = ignoreSideEffects;
|
|
246
|
+
|
|
243
247
|
// see https://github.com/parshap/node-sanitize-filename/blob/master/index.js
|
|
244
248
|
const asValidFilename = (string) => {
|
|
245
249
|
return string
|