Skip to content

Fix: Jest Snapshot Outdated — 1 snapshot obsolete

FixDevs ·

Quick Answer

How to fix Jest snapshot failures — updating outdated snapshots, removing obsolete ones, fixing inline snapshots, preventing brittle snapshot tests, and managing snapshots in CI.

The Error

Jest fails with a snapshot mismatch:

● MyComponent › renders correctly

  1 snapshot failed.

  Snapshot name: `MyComponent renders correctly 1`

  - Snapshot  - 3
  + Received  + 3

    <div
      className="container"
  -   style="color: red;"
  +   style="color: blue;"
    >
  -   <h1>Old Title</h1>
  +   <h1>New Title</h1>
    </div>

Or obsolete snapshots after deleting tests:

 › 1 snapshot obsolete.
   • MyComponent renders the old variant 1

Snapshot Summary
 › 1 snapshot obsolete from 1 test suite. Re-run Jest with `--updateSnapshot` to remove it.

Or in watch mode:

Snapshot Summary
 › 3 snapshots failed from 2 test suites. Inspect your code changes or re-run jest with `-u` to update them.

Why This Happens

Jest snapshot tests compare the current output of a component or function against a previously saved .snap file. A mismatch occurs when:

  • Intentional code change — you updated a component’s markup, styles, or output, and the snapshot reflects the old version. The snapshot needs to be updated to match the new correct output.
  • Unintentional regression — a code change accidentally broke something. The snapshot is correctly catching the regression.
  • Obsolete snapshot — a test was renamed, moved, or deleted, but the old snapshot entry remains in the .snap file.
  • Dynamic content in snapshot — timestamps, random IDs, or other dynamic values differ on each run, causing snapshots to always fail.
  • Environment differences — snapshot generated on one OS or Node version differs slightly from the current environment (rare, usually affects date formatting or whitespace).

Before blindly running --updateSnapshot, determine whether the change is intentional or a bug.

Fix 1: Update Outdated Snapshots (Intentional Changes)

When you’ve intentionally changed a component and the snapshot is just stale:

# Update all failing snapshots
jest --updateSnapshot

# Or the short form
jest -u

# Update snapshots for a specific test file
jest MyComponent.test.tsx --updateSnapshot

# Update in watch mode — press 'u' when prompted
jest --watch
# Then press 'u' to update all failing snapshots
# Or press 'i' to update them one by one interactively

After updating, review the changes in the .snap file with git diff before committing:

git diff src/__snapshots__/

This confirms the snapshot changes are exactly what you intended — not an accidental regression.

Common Mistake: Running jest -u to “fix” CI failures without reviewing what changed. Snapshot tests only catch regressions if you read the diff before accepting it. An unreviewed jest -u commit is an untested change.

Fix 2: Remove Obsolete Snapshots

Obsolete snapshots are entries in .snap files that no longer correspond to any test. They accumulate when tests are renamed or deleted:

# Remove obsolete snapshots only (doesn't update failing ones)
jest --updateSnapshot

# Or explicitly
jest --ci && jest -u  # Will only remove obsolete, update changed

Manually clean up a .snap file if --updateSnapshot doesn’t help:

// src/__snapshots__/MyComponent.test.tsx.snap
// Delete entries that no longer have corresponding tests

In watch mode, press u to update all snapshots including removing obsolete ones.

Fix 3: Fix Dynamic Values in Snapshots

Snapshots with dynamic content (timestamps, random IDs, generated hashes) fail on every run:

// BAD — snapshot contains the current date, fails tomorrow
test('renders invoice', () => {
  const invoice = <Invoice date={new Date()} id={Math.random()} />;
  expect(invoice).toMatchSnapshot();
  // Snapshot: date="2026-03-19T10:23:45.123Z" id="0.8472651..."
  // Tomorrow: date="2026-03-20T..." ← FAILS
});

Fix — mock or freeze dynamic values:

// Mock Date to return a fixed value
jest.useFakeTimers();
jest.setSystemTime(new Date('2026-01-01'));

test('renders invoice', () => {
  const invoice = <Invoice date={new Date()} id="fixed-test-id" />;
  expect(invoice).toMatchSnapshot();
});

afterEach(() => {
  jest.useRealTimers();
});

Use expect.any() matchers in snapshots for fields that legitimately vary:

test('creates user', () => {
  const user = createUser({ name: 'Alice' });
  expect(user).toMatchSnapshot({
    id: expect.any(String),          // Matches any string — ID is dynamic
    createdAt: expect.any(Date),     // Matches any date
    name: 'Alice',                   // Exact match for stable fields
  });
});

Use toMatchInlineSnapshot for small outputs — inline snapshots live in the test file and are easier to review:

test('formats price', () => {
  expect(formatPrice(9.99)).toMatchInlineSnapshot(`"$9.99"`);
  // Jest writes the snapshot directly into the test file on first run
});

Fix 4: Use More Specific Assertions Instead of Full Snapshots

Snapshot tests that capture entire component trees are brittle — any trivial change (adding a CSS class, changing a div to a section) breaks them. Use targeted assertions for stable properties:

// BAD — entire component snapshot breaks on any markup change
test('shows username', () => {
  render(<UserCard user={{ name: 'Alice', role: 'admin' }} />);
  expect(screen.getByRole('article')).toMatchSnapshot();
});

// BETTER — assert on specific behavior, not the full DOM
test('shows username', () => {
  render(<UserCard user={{ name: 'Alice', role: 'admin' }} />);
  expect(screen.getByText('Alice')).toBeInTheDocument();
  expect(screen.getByText('admin')).toBeInTheDocument();
});

// GOOD USE OF SNAPSHOTS — for complex computed output
test('serializes config object', () => {
  const config = buildConfig({ env: 'production', debug: false });
  expect(config).toMatchSnapshot();
  // Snapshot captures the exact config structure — intentional
});

Snapshots are most valuable for:

  • Complex data transformation output (serializers, formatters)
  • CLI output text
  • API response shapes (with dynamic fields masked)
  • Error message formats

Snapshots are least valuable for:

  • Simple component rendering (use @testing-library/react queries instead)
  • Anything with dynamic content you don’t control

Fix 5: Fix Snapshot Location and Naming

Snapshots are stored in __snapshots__/ directories next to the test files. If tests are moved without moving the snapshots, obsolete entries accumulate:

src/
  components/
    Button.test.tsx           ← test file
    __snapshots__/
      Button.test.tsx.snap    ← auto-generated snapshot file

If you rename a test file, Jest creates a new snapshot file and the old one becomes orphaned:

# Find orphaned snapshot files
find . -name "*.snap" -not -path "*/node_modules/*"

# Then check if corresponding test files exist

Name snapshots descriptively to make diffs readable:

// Jest uses the test description as the snapshot name
test('renders button in primary variant', () => {
  // Snapshot name: "renders button in primary variant 1"
  expect(render(<Button variant="primary">Click</Button>).asFragment())
    .toMatchSnapshot('primary button');  // Custom name
});

Fix 6: Handle Snapshots in CI

In CI, never auto-update snapshots — fail explicitly so the developer must review the change:

# CI script — fail if any snapshot is outdated or obsolete
jest --ci

# --ci flag:
# - Fails if snapshots need updating (doesn't auto-update)
# - Fails if there are obsolete snapshots
# - Disables interactive mode
# GitHub Actions example
- name: Run tests
  run: jest --ci --coverage

If CI fails on snapshots, the fix is to update them locally and commit the updated .snap files:

# Locally
jest -u                   # Update all
git add src/__snapshots__/
git commit -m "Update snapshots for Button refactor"

Pro Tip: Add .snap files to your PR review checklist. Snapshot diffs often reveal unintended changes — a snapshot growing by 20 lines might mean a component is now rendering unexpected content.

Fix 7: Regenerate All Snapshots from Scratch

If snapshots are severely out of date across many files, regenerate them all:

# Delete all snapshot files
find . -name "*.snap" -not -path "*/node_modules/*" -delete

# Run tests — all snapshots fail because no .snap files exist
# Jest creates fresh snapshots automatically
jest -u

Review the newly created snapshots carefully with git diff before committing.

Still Not Working?

Check for non-deterministic rendering. If a snapshot fails inconsistently, the component output varies between renders. Common causes:

  • Async data loading without proper mocking
  • CSS-in-JS libraries that generate class names with counters
  • Third-party components with internal state

Serialize custom objects. If your snapshot shows [Object] instead of the actual content, Jest doesn’t know how to serialize it. Add a custom serializer:

// jest.config.js
module.exports = {
  snapshotSerializers: ['enzyme-to-json/serializer'],
  // Or for custom types:
  // snapshotSerializers: ['./src/test/myCustomSerializer'],
};

Reset snapshot counters. Each toMatchSnapshot() call in a test gets a numbered name (snapshot 1, snapshot 2). If you add a snapshot call before existing ones, all subsequent numbers shift and every snapshot fails. Use explicit names:

// Without name — fragile, renumbers on insertion
expect(a).toMatchSnapshot();  // "renders correctly 1"
expect(b).toMatchSnapshot();  // "renders correctly 2"

// With name — stable
expect(a).toMatchSnapshot('initial state');
expect(b).toMatchSnapshot('after click');

For related testing issues, see Fix: Jest Test Timeout and Fix: Jest Mock Not Working.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles