skills/vitest-snap-getting-started/SKILL.md
End-to-end guide for adding vitest-snap to an existing Vitest project: install package, register matchers in setupFiles via side-effect import, write first toJsonSnapshot call, understand auto-naming and built-in defaults (UndefinedFilter, Date redaction), then add a filter or redaction. Use when bootstrapping vitest-snap from scratch.
npx skillsauth add Odonno/vitest-snap vitest-snap-getting-startedInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill builds on setup and write-snapshot. Read them for full option references.
npm i vitest-snap -D
# or: bun add -D vitest-snap
import "vitest-snap";
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
setupFiles: ["./vitest.setup.ts"],
},
});
import { expect, test } from "vitest";
test("user object", async () => {
const user = { id: 1, name: "Alice", createdAt: new Date() };
await expect(user).toJsonSnapshot();
// first run: writes ./snapshots/user-object
// subsequent runs: diffs against that file
});
undefined props are removed by UndefinedFilterDate instances are replaced with [Date_1], [Date_2], … by ValueRedaction./snapshots relative to the test file"user object" → user-object)import { expect, test } from "vitest";
import { UndefinedFilter, NullFilter, ReplacedRedaction } from "vitest-snap";
test("user object", async () => {
const user = {
id: 1,
name: "Alice",
password: "s3cr3t",
createdAt: new Date(),
};
await expect(user).toJsonSnapshot({
filters: [new UndefinedFilter(), new NullFilter()],
redactions: [
new ValueRedaction((_, v) => v instanceof Date, "[Date]"),
new ReplacedRedaction(".password", "[REDACTED]"),
],
});
});
Note: providing a custom filters or redactions array replaces the defaults — always re-add UndefinedFilter and the Date ValueRedaction when extending.
<test-file-dir>/
└── snapshots/
└── <slugified-test-name>[_<arg1>][_<arg2>][.<ext>]
Examples:
"user object" → snapshots/user-object"pagination page-size %i" with args: [50] → snapshots/pagination-page-size-50args: [50], fileExtension: "json" → snapshots/pagination-page-size-50.jsonRun with --update-snapshots flag (Vitest native):
bunx vitest run --update-snapshots
Wrong:
test("user", () => {
expect(user).toJsonSnapshot(); // no await
});
Correct:
test("user", async () => {
await expect(user).toJsonSnapshot();
});
All four matchers return Promise<void>; omitting await makes the test pass without writing or diffing the snapshot file — silent false positive.
Source: src/index.ts
Wrong:
// vitest.config.ts — no setupFiles configured
export default defineConfig({ test: {} });
Correct:
// vitest.setup.ts
import "vitest-snap";
// vitest.config.ts
export default defineConfig({
test: { setupFiles: ["./vitest.setup.ts"] },
});
vitest-snap registers matchers via side-effect import calling expect.extend(). Missing the import causes all matcher calls to throw at runtime.
Source: docs/content/docs/index.mdx
Wrong:
await expect(data).toJsonSnapshot({
filters: [new NullFilter()], // UndefinedFilter no longer applied
});
Correct:
await expect(data).toJsonSnapshot({
filters: [new UndefinedFilter(), new NullFilter()],
});
filters: [...] completely replaces the default [new UndefinedFilter()]. Undefined props reappear in the snapshot.
Source: src/options/index.ts
Wrong:
await expect(data).toJsonSnapshot({
redactions: [new ReplacedRedaction(".password", "[REDACTED]")],
// Dates no longer redacted → flaky tests
});
Correct:
await expect(data).toJsonSnapshot({
redactions: [
new ValueRedaction((_, v) => v instanceof Date, "[Date]"),
new ReplacedRedaction(".password", "[REDACTED]"),
],
});
redactions: [...] completely replaces the default Date redaction. Dates appear as serialized strings → flaky tests.
Source: src/options/index.ts
tools
Write snapshot tests with toJsonSnapshot, toYamlSnapshot, toMarkdownSnapshot, toTextSnapshot. Covers SnapOptions (dir, name, fileExtension, args, indent), auto-naming from test name, parametric snapshots with test.each and args, Markdown table rendering rules, and yaml peer dependency for toYamlSnapshot. Use when writing any vitest-snap matcher call.
testing
Install vitest-snap, register matchers via side-effect import in Vitest setupFiles, configure global defaults with configureGlobalSnapOptions. Covers option merge order (defaults → global → per-call), yaml peer dependency for toYamlSnapshot, UndefinedFilter/Date redaction defaults, and snapshot file migration when changing global dir.
testing
Apply redactions to replace or stabilize values before snapshotting: ValueRedaction(predicate, replaced, counting), ReplacedRedaction(selector, replaced, counting), SortedRedaction(selector). Covers counting behaviour ([Tag] → [Tag_1], [Tag_2]), deepest-first traversal order, default Date redaction override (custom array replaces it), .** selector root replacement risk, and Selector<T> typed paths. Use when configuring the redactions option on any matcher.
testing
Apply filters to remove nodes before snapshotting: UndefinedFilter (default), NullFilter, ExcludeFilter(selector), IncludeFilter(selector[]). Covers Selector<T> typed path DSL, bare selector string shorthand for IncludeFilter, adjacent IncludeFilter auto-merge via regroupFilters, default filters override behaviour (custom array replaces UndefinedFilter), and array slot preservation semantics. Use when configuring the filters option on any matcher.