Writing Tests
Custom Matchers
File snapshot assertions use one of the custom matchers:
toMatchJsonFile- for JSON file snapshotstoMatchTextFile- for text file snapshots
JSON File Snapshots
test("value is expected value", () => {
expect({ value: "expected value" }).toMatchJsonFile();
});
// value_is_expected_value.json
// {
// "value": "expected value"
// }Text File Snapshots
test("value is expected value", () => {
expect("expected value").toMatchTextFile();
});
// value_is_expected_value.txt
// expected valueMultiple Expectations
You can test multiple related values in a single test:
function mapToString(value: boolean | number): string {
return value.toString();
}
test("maps values to string", () => {
expect({
boolean: mapToString(true),
positiveNumber: mapToString(1),
negativeNumber: mapToString(-1),
}).toMatchJsonFile();
});
// maps_values_to_string.json
// {
// "boolean": "true",
// "positiveNumber": "1",
// "negativeNumber": "-1",
// }Normalization
Normalizers can be used to apply custom normalization, e.g., mask values which are not stable. Custom normalizers are applied before internal normalizers and the snapshot serialization.
function maskDate(value: unknown): unknown {
if (value instanceof Date) {
return "[DATE]";
}
return value;
}
test("date is masked", () => {
expect({ date: new Date() }).toMatchJsonFile({ normalizers: [maskDate] });
});
// date_is_masked.json
// {
// "date": "[DATE]"
// }Named Snapshots
By default, the name of a file snapshot is automatically derived from the hierarchy of test titles, including describe and test. When using multiple file snapshot matchers in the same test context, it's necessary to define a unique name for the snapshot.
test("named snapshots", () => {
// named_snapshots/snapshot_1.txt
expect("value 1").toMatchTextFile({ name: "snapshot 1" });
// named_snapshots/snapshot_2.txt
expect("value 2").toMatchTextFile({ name: "snapshot 2" });
});By default, all named snapshots are stored as separate files in the same directory, which is determined by the test context.
Custom File Path Resolver
To change the default behavior, you can use a different file path resolver:
import { resolveNameAsFileSuffix } from "@cronn/vitest-file-snapshots";
test("named snapshots", async () => {
// named_snapshots_snapshot_name.txt
await expect("value 1").toMatchTextFile({
name: "snapshot name",
resolveFilePath: resolveNameAsFileSuffix,
});
});Soft Assertions
function mapValue(value: string): string {
return `mapped ${value}`;
}
test("value is mapped", () => {
const data = { value: "value" };
expect.soft(initialValue).toMatchJsonFile({ name: "before" });
expect.soft(mapValue(initialValue)).toMatchJsonFile({ name: "after" });
});
// value_is_mapped_before.json
// {
// "value": "value"
// }
// value_is_mapped_after.json
// {
// "value": "mapped value"
// }Updating Snapshots
Snapshots can be updated using Vitest's built-in support for snapshot updates:
- Using the CLI parameter
--update - Configuring the option
updatein yourvitest.config.ts
By default, only missing validation files are written. When updates are enabled, existing validation files will also be overridden.
TIP
If you accidentally updated more snapshots than intended, you can revert the changes using your VCS and selectively apply updates by diffing the validation and output directories.