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

# Snapshots

> Use snapshot testing in Bun to capture and compare output across test runs, with support for inline snapshots, error snapshots, and property matchers.

Snapshot testing saves the serialized output of a value and compares it on future runs. This is useful for complex objects, component output, or any value that should remain stable over time.

## Basic snapshots

Use `.toMatchSnapshot()` to capture a value:

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

test("formats user object", () => {
  const user = { id: 1, name: "Alice", role: "admin" };
  expect(user).toMatchSnapshot();
});
```

On the **first run**, the value is serialized and written to a snapshot file. On subsequent runs, the value is compared against the stored snapshot — the test fails if they differ.

### Snapshot file location

Snapshots are stored in a `__snapshots__` directory alongside the test file:

```
your-project/
├── user.test.ts
└── __snapshots__/
    └── user.test.ts.snap
```

The snapshot file contents look like:

```typescript __snapshots__/user.test.ts.snap theme={null}
// Bun Snapshot v1, https://bun.com/docs/test/snapshots

exports[`formats user object 1`] = `
{
  "id": 1,
  "name": "Alice",
  "role": "admin",
}
`;
```

## Updating snapshots

When output intentionally changes, regenerate snapshots with:

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

After updating, commit the snapshot files alongside your code changes so they are reviewed as part of the diff.

```bash theme={null}
git diff __snapshots__/
git add __snapshots__/
git commit -m "update snapshots after API response shape change"
```

## Inline snapshots

For small values, use `.toMatchInlineSnapshot()` to store the snapshot directly in the test file. On the first run, Bun writes the value into your test file automatically.

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

test("formats currency", () => {
  expect(formatCurrency(99.99)).toMatchInlineSnapshot(`"$99.99"`);
});
```

After the first run, your test file is updated with the snapshot value filled in. Subsequent runs compare against the inline string.

## Error snapshots

Capture and compare error messages with `.toThrowErrorMatchingSnapshot()` and `.toThrowErrorMatchingInlineSnapshot()`:

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

test("throws on invalid input", () => {
  expect(() => {
    parseConfig("not valid json");
  }).toThrowErrorMatchingInlineSnapshot(`"Invalid configuration: not valid json"`);
});
```

## Advanced usage

### Complex objects

Snapshots are particularly effective for deeply nested structures:

```typescript theme={null}
test("generates report", () => {
  const report = generateReport([
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
  ]);

  expect(report).toMatchSnapshot();
});
```

### Property matchers

For values that change between runs (timestamps, random IDs), use property matchers to assert the shape while ignoring volatile values:

```typescript theme={null}
test("creates user with dynamic fields", () => {
  const user = {
    id: crypto.randomUUID(),
    name: "Alice",
    createdAt: new Date().toISOString(),
  };

  expect(user).toMatchSnapshot({
    id: expect.any(String),
    createdAt: expect.any(String),
  });
});
```

The snapshot stores `Any<String>` for the matched fields while capturing the exact value of `name`.

### React component snapshots

Snapshots work well for testing rendered HTML output:

```typescript theme={null}
import { test, expect } from "bun:test";
import { render } from "@testing-library/react";

function Badge({ label, variant = "default" }: { label: string; variant?: string }) {
  return <span className={`badge badge-${variant}`}>{label}</span>;
}

test("Badge renders correctly", () => {
  const { container } = render(<Badge label="New" variant="success" />);
  expect(container.innerHTML).toMatchInlineSnapshot(
    `"<span class=\"badge badge-success\">New</span>"`
  );
});
```

### Custom serializers

Register a custom serializer to control how a type is printed in snapshots:

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

expect.addSnapshotSerializer({
  test: (val) => val instanceof Date,
  serialize: (val) => `"${val.toISOString()}"`,
});

test("event with date", () => {
  expect({
    name: "Meeting",
    date: new Date("2024-06-01T10:00:00Z"),
  }).toMatchSnapshot();
});
```

## Troubleshooting snapshot failures

When a snapshot test fails, Bun shows a diff:

```diff theme={null}
- Expected
+ Received

  Object {
-   "name": "Alice",
+   "name": "Bob",
  }
```

**Common causes:**

| Cause                        | Solution                                                     |
| ---------------------------- | ------------------------------------------------------------ |
| Intentional change           | Run `bun test --update-snapshots`                            |
| Unintentional regression     | Fix the code that produces the output                        |
| Dynamic data in snapshot     | Use property matchers for volatile fields                    |
| Platform-specific formatting | Normalize values (e.g., path separators) before snapshotting |

## Best practices

<AccordionGroup>
  <Accordion title="Keep snapshots small and focused">
    Snapshot only the part of the output that matters to the test. Large snapshots are hard to review when they change.

    ```typescript theme={null}
    // Good: snapshot a specific field
    expect(response.body).toMatchInlineSnapshot(`"success"`);

    // Avoid: snapshotting an entire page render
    expect(renderFullPage()).toMatchSnapshot();
    ```
  </Accordion>

  <Accordion title="Handle dynamic data with property matchers">
    ```typescript theme={null}
    // Good: normalize volatile fields
    expect(apiResponse).toMatchSnapshot({
      timestamp: expect.any(Number),
      requestId: expect.any(String),
    });

    // Avoid: snapshots that break on every run
    expect(apiResponse).toMatchSnapshot(); // contains Date.now()
    ```
  </Accordion>

  <Accordion title="Review snapshot changes carefully">
    Snapshot diffs in pull requests deserve the same scrutiny as code changes. An unexpected snapshot change is often a sign of a bug.
  </Accordion>

  <Accordion title="Group snapshots with describe">
    Organizing snapshots inside `describe` blocks makes the snapshot file easier to navigate:

    ```typescript theme={null}
    describe("Button", () => {
      test("primary variant", () => {
        expect(renderButton("primary")).toMatchSnapshot();
      });

      test("secondary variant", () => {
        expect(renderButton("secondary")).toMatchSnapshot();
      });
    });
    ```
  </Accordion>
</AccordionGroup>
