@jsenv/snapshot v2.15.12
@jsenv/snapshot
A powerful snapshot testing tool for JavaScript applications.
šø Create readable, reliable test snapshots
š Document code behavior with markdown
š Track changes in code output over time
š§© Normalize fluctuating values for stable comparisons
Table of Contents
- @jsenv/snapshot
Introduction to Snapshot Testing
Snapshot testing is a technique that:
- Captures the output of code execution into files (snapshots)
- Validates future code changes by:
- Reading the existing snapshot
- Executing the code
- Generating a new snapshot
- Comparing the two snapshots and reporting differences
This approach ensures your code continues to behave as expected by verifying its outputs remain consistent over time.
Installation
npm install --save-dev @jsenv/snapshotHow @jsenv/snapshot Works
When running tests:
- First run: If no snapshot exists, one will be generated without comparison
- Subsequent runs: Snapshots are compared with the following behavior:
- In CI environments (
process.env.CIis set): An error is thrown if differences are detected - Locally: No error is thrown, allowing you to review changes with tools like git diff
- In CI environments (
Note: All functions accept a
throwWhenDiffparameter to force errors even in local environments.
API Reference
snapshotTests(testFileUrl, fnRegisteringTests, options)
The most powerful feature of this library - creates readable markdown snapshots of test executions.
import { snapshotTests } from "@jsenv/snapshot";
const getCircleArea = (circleRadius) => {
if (isNaN(circleRadius)) {
throw new TypeError(
`circleRadius must be a number, received ${circleRadius}`,
);
}
return circleRadius * circleRadius * Math.PI;
};
await snapshotTests(import.meta.url, ({ test }) => {
test("when radius is 2", () => {
return getCircleArea(2);
});
test("when radius is 10", () => {
return getCircleArea(10);
});
test("when radius is null", () => {
try {
return getCircleArea(null);
} catch (e) {
return e;
}
});
});This generates a markdown file documenting how your code behaves in different scenarios:
# getCircleArea
## when radius is 2
```js
getCircleArea(2);
```Returns:
12.566370614359172;when radius is 10
getCircleArea(10);Returns:
314.1592653589793;when radius is null
getCircleArea(null);Throws:
TypeError: circleRadius must be a number, received nullSee a full example at [./docs/\_circle_area.test.js/circle_area.test.js.md](./docs/_circle_area.test.js/circle_area.test.js.md)
#### snapshotTests Options
```js
await snapshotTests(import.meta.url, fnRegisteringTests, {
throwWhenDiff: true, // Force error on snapshot differences (default: false in local, true in CI)
formatValue: (value) => {}, // Custom formatter for values
trackingConfig: {}, // Track specific resources like network requests or file operations
});Why Use snapshotTests?
- Assertion-free testing: Simply call your functions and let the snapshots document their behavior
- Self-documenting tests: Markdown files serve as both test validation and documentation
- Visual change reviews: Code changes are reflected in snapshots, making reviews easy
- Side effect tracking: Automatically captures and documents:
takeFileSnapshot(fileUrl)
Captures and compares the state of a specific file.
import { writeFileSync } from "node:fs";
import { takeFileSnapshot } from "@jsenv/snapshot";
const fileTxtUrl = new URL("./file.txt", import.meta.url);
const writeFileTxt = (content) => {
writeFileSync(fileTxtUrl, content);
};
// take snapshot of "./file.txt"
const fileSnapshot = takeFileSnapshot(fileTxtUrl);
writeFileTxt("Hello world");
// compare the state of "./file.txt" with previous version
fileSnapshot.compare();takeDirectorySnapshot(directoryUrl)
Captures and compares the state of an entire directory.
import { writeFileSync } from "node:fs";
import { takeDirectorySnapshot } from "@jsenv/snapshot";
const directoryUrl = new URL("./dir/", import.meta.url);
const writeManyFiles = () => {
writeFileSync(new URL("./a.txt", directoryUrl), "a");
writeFileSync(new URL("./b.txt", directoryUrl), "b");
};
// take snapshot of "./dir/"
const directorySnapshot = takeDirectorySnapshot(directoryUrl);
writeManyFiles();
// compare the state of "./dir/" with previous version
directorySnapshot.compare();Stable Snapshots Across Environments
To ensure snapshots remain consistent across different machines and CI environments, @jsenv/snapshot automatically normalizes fluctuating values:
| Fluctuating Value | Stabilized As |
|---|---|
| Time durations | "Xs" instead of "2.34s" |
| Filesystem paths | Platform-independent paths |
| Network ports | Removed from URLs |
| Random IDs | Consistent placeholder values |
| Stack traces | Simplified and normalized |
This ensures your snapshot tests remain stable regardless of when or where they run.
Advanced Examples
- Testing complex assertion behavior: @jsenv/assert/tests/array.test.js.md
- Testing server-side builds with browser execution: @jsenv/core/tests/script_type_module_basic.test.mjs
Compatibility
- Node.js: 16.x and above
- Works with most JavaScript test runners
- Compatible with ESM and CommonJS modules
Contributing
If you encounter unstable snapshots due to fluctuating values not being properly normalized, please open an issue or submit a pull request.
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
10 months ago
10 months ago
10 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
9 months ago
1 year ago
8 months ago
1 year ago
1 year ago
9 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
12 months ago
12 months ago
11 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago