> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
> Use this file to discover all available pages before exploring further.

# Snapshot Testing

> Test output against saved snapshots

Snapshot testing captures the output of your code and saves it to a file. Future test runs compare against the saved snapshot, making it easy to catch unexpected changes.

## Basic usage

Use `toMatchSnapshot()` to create a snapshot:

```ts theme={null}
import { test, expect } from "bun:test";

test("component renders correctly", () => {
  const html = renderComponent({ name: "Alice", age: 30 });
  expect(html).toMatchSnapshot();
});
```

The first time this test runs, Bun creates a snapshot file:

```
__snapshots__/
  my-test.test.ts.snap
```

The snapshot file contains:

```js theme={null}
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots

exports[`component renders correctly 1`] = `
<div>
  <h1>Alice</h1>
  <p>Age: 30</p>
</div>
`;
```

## Inline snapshots

Inline snapshots write the expected value directly into your test file:

```ts theme={null}
import { test, expect } from "bun:test";

test("inline snapshot", () => {
  const data = { name: "Alice", age: 30 };
  expect(data).toMatchInlineSnapshot();
});
```

After the first run, Bun updates your test file:

```ts theme={null}
test("inline snapshot", () => {
  const data = { name: "Alice", age: 30 };
  expect(data).toMatchInlineSnapshot(`
{
  "name": "Alice",
  "age": 30,
}
`);
});
```

## Named snapshots

Provide a name to identify the snapshot:

```ts theme={null}
import { test, expect } from "bun:test";

test("renders different states", () => {
  expect(render({ loading: true })).toMatchSnapshot("loading state");
  expect(render({ error: true })).toMatchSnapshot("error state");
  expect(render({ data: [] })).toMatchSnapshot("empty state");
});
```

## Updating snapshots

When your output changes intentionally, update snapshots:

```bash theme={null}
$ bun test --update-snapshots
```

Or use the shorthand:

```bash theme={null}
$ bun test -u
```

This updates all snapshots to match the current output.

## Property matchers

Use property matchers to ignore dynamic values:

```ts theme={null}
import { test, expect } from "bun:test";

test("user object", () => {
  const user = {
    id: Math.random(), // Changes every time
    name: "Alice",
    createdAt: new Date()
  };
  
  expect(user).toMatchSnapshot({
    id: expect.any(Number),
    createdAt: expect.any(Date)
  });
});
```

The snapshot will be:

```js theme={null}
exports[`user object 1`] = `
{
  "id": Any<Number>,
  "name": "Alice",
  "createdAt": Any<Date>,
}
`;
```

## Snapshot testing best practices

### Keep snapshots small

Snapshot large outputs can make it hard to review changes:

```ts theme={null}
// ❌ Bad: Snapshots entire page
test("renders page", () => {
  const html = renderPage();
  expect(html).toMatchSnapshot();
});

// ✅ Good: Snapshots specific component
test("renders header", () => {
  const html = renderHeader();
  expect(html).toMatchSnapshot();
});
```

### Use inline snapshots for small values

Inline snapshots make tests more readable:

```ts theme={null}
import { test, expect } from "bun:test";

test("formats date", () => {
  expect(formatDate(new Date("2024-01-01"))).toMatchInlineSnapshot(`"January 1, 2024"`);
});
```

### Review snapshot changes carefully

When updating snapshots, review the changes to ensure they're intentional:

```bash theme={null}
# View diff before updating
$ bun test

# If changes are correct
$ bun test --update-snapshots
```

### Don't snapshot implementation details

Snapshot user-facing output, not internal state:

```ts theme={null}
// ❌ Bad: Snapshots internal state
test("state machine", () => {
  const machine = createMachine();
  machine.transition("NEXT");
  expect(machine._internalState).toMatchSnapshot();
});

// ✅ Good: Snapshots public API
test("state machine", () => {
  const machine = createMachine();
  machine.transition("NEXT");
  expect(machine.currentState).toBe("active");
});
```

## Snapshot file location

Snapshots are stored in `__snapshots__` directories:

```
test/
├── __snapshots__/
│   ├── component.test.ts.snap
│   └── utils.test.ts.snap
├── component.test.ts
└── utils.test.ts
```

## CI environments

In CI, Bun prevents creating new snapshots:

```bash theme={null}
$ CI=true bun test
# Error: New snapshot created in CI environment
```

To update snapshots in CI:

```bash theme={null}
$ CI=true bun test --update-snapshots
```

## Snapshot serialization

Bun uses the same serialization as Jest:

* Objects are pretty-printed with sorted keys
* Strings preserve whitespace and escaping
* React elements are serialized to readable JSX
* Custom serializers can be added

### Custom serializers

Add custom serializers for specific types:

```ts theme={null}
import { expect } from "bun:test";

expect.addSnapshotSerializer({
  test: (val) => val instanceof URL,
  serialize: (val) => `URL<${val.href}>`
});

test("url snapshot", () => {
  const url = new URL("https://example.com/path");
  expect(url).toMatchInlineSnapshot(`URL<https://example.com/path>`);
});
```

## Interactive snapshot updates

When running tests interactively, Bun prompts you to update snapshots:

```
 FAIL  test/component.test.ts
  ✖ component renders correctly
    
    Received: "<div>New HTML</div>"
    
    › Press u to update snapshots
    › Press s to skip
```

Press `u` to update the snapshot or `s` to skip.

## Related

* [Writing Tests](/test/writing)
* [Configuration](/test/configuration)
* [expect API](/api-reference/test/expect)
