963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
3.5 KiB
3.5 KiB
name, description
| name | description |
|---|---|
| snapshot-testing | Snapshot testing with file, inline, and file snapshots |
Snapshot Testing
Snapshot tests capture output and compare against stored references.
Basic Snapshot
import { expect, test } from 'vitest';
test('snapshot', () => {
const result = generateOutput();
expect(result).toMatchSnapshot();
});
First run creates .snap file:
// __snapshots__/test.spec.ts.snap
exports['snapshot 1'] = `
{
"id": 1,
"name": "test"
}
`;
Inline Snapshots
Stored directly in test file:
test('inline snapshot', () => {
const data = { foo: 'bar' };
expect(data).toMatchInlineSnapshot();
});
Vitest updates the test file:
test('inline snapshot', () => {
const data = { foo: 'bar' };
expect(data).toMatchInlineSnapshot(`
{
"foo": "bar",
}
`);
});
File Snapshots
Compare against explicit file:
test('render html', async () => {
const html = renderComponent();
await expect(html).toMatchFileSnapshot('./expected/component.html');
});
Snapshot Hints
Add descriptive hints:
test('multiple snapshots', () => {
expect(header).toMatchSnapshot('header');
expect(body).toMatchSnapshot('body content');
expect(footer).toMatchSnapshot('footer');
});
Object Shape Matching
Match partial structure:
test('shape snapshot', () => {
const data = {
id: Math.random(),
created: new Date(),
name: 'test',
};
expect(data).toMatchSnapshot({
id: expect.any(Number),
created: expect.any(Date),
});
});
Error Snapshots
test('error message', () => {
expect(() => {
throw new Error('Something went wrong');
}).toThrowErrorMatchingSnapshot();
});
test('inline error', () => {
expect(() => {
throw new Error('Bad input');
}).toThrowErrorMatchingInlineSnapshot(`[Error: Bad input]`);
});
Updating Snapshots
# Update all snapshots
vitest -u
vitest --update
# In watch mode, press 'u' to update failed snapshots
Custom Serializers
Add custom snapshot formatting:
expect.addSnapshotSerializer({
test(val) {
return val && typeof val.toJSON === 'function';
},
serialize(val, config, indentation, depth, refs, printer) {
return printer(val.toJSON(), config, indentation, depth, refs);
},
});
Or via config:
// vitest.config.ts
defineConfig({
test: {
snapshotSerializers: ['./my-serializer.ts'],
},
});
Snapshot Format Options
defineConfig({
test: {
snapshotFormat: {
printBasicPrototype: false, // Don't print Array/Object prototypes
escapeString: false,
},
},
});
Concurrent Test Snapshots
Use context's expect:
test.concurrent('concurrent 1', async ({ expect }) => {
expect(await getData()).toMatchSnapshot();
});
test.concurrent('concurrent 2', async ({ expect }) => {
expect(await getOther()).toMatchSnapshot();
});
Snapshot File Location
Default: __snapshots__/<test-file>.snap
Customize:
defineConfig({
test: {
resolveSnapshotPath: (testPath, snapExtension) => {
return testPath.replace('__tests__', '__snapshots__') + snapExtension;
},
},
});
Key Points
- Commit snapshot files to version control
- Review snapshot changes in code review
- Use hints for multiple snapshots in one test
- Use
toMatchFileSnapshotfor large outputs (HTML, JSON) - Inline snapshots auto-update in test file
- Use context's
expectfor concurrent tests