How to Review Snapshot Changes in Code Review
Snapshot changes are common in pull requests, but most reviewers don't know what to look for. They see a .snap file diff, assume the developer updated it intentionally, and approve without actually verifying anything.
This is how snapshot testing loses its value. Regressions get committed with an approved snapshot update, and the snapshot baseline now includes the bug.
This guide explains how to review snapshot changes properly: what to look for, how to read diffs, and when to push back.
The Core Review Question
For every snapshot change, ask: Is this change intentional or accidental?
If the developer changed the component and the snapshot reflects the new design — intentional. If the developer fixed a bug and the snapshot shows different markup for reasons that aren't obvious — investigate.
A snapshot update is never automatically fine. It requires the same scrutiny as any other code change.
What Good Snapshot Diffs Look Like
Intentional addition
<div class="user-card">
<img src="/avatar.jpg" alt="Alice" />
<h2>Alice</h2>
+ <span class="badge">Admin</span>
</div>A new badge element was added. If the PR description says "added admin badge to user cards," this is expected.
Questions to ask:
- Does the PR description explain this change?
- Is the new element accessible (role, aria-label if needed)?
- Is it the right element for the content type?
Intentional structural change
- <div class="card card--horizontal">
- <img src="/hero.jpg" />
- <div class="card__content">
- <h2>Title</h2>
- </div>
- </div>
+ <article class="card">
+ <header>
+ <h2>Title</h2>
+ </header>
+ <img src="/hero.jpg" />
+ </article>Significant restructuring. If the PR is "refactor Card for accessibility," this makes sense — article is semantically correct, header wraps the heading.
Questions to ask:
- Does this change break any CSS that targeted the old class names?
- Is the new structure more or less accessible?
- Did the visual output actually improve (is there a screenshot/Storybook link)?
Class change
- <button class="btn btn--primary">
+ <button class="btn btn--secondary">A class name changed from primary to secondary. This changes the button's visual appearance.
Questions to ask:
- Is this intentional? Was the design spec for this button secondary?
- Are there other places that use this component that now have the wrong button variant?
Red Flags in Snapshot Diffs
Removed accessibility attributes
- <button aria-label="Close dialog" class="close-btn">
+ <button class="close-btn">An aria-label was removed. Screen readers can no longer describe this button. This is a bug — reject it.
- <img src="/product.jpg" alt="Product name" />
+ <img src="/product.jpg" />Missing alt attribute. Accessibility regression. Reject.
Changed text content
- <p>Your account has been created successfully.</p>
+ <p>Account created.</p>The message changed. If this is a user-facing success message, does the product team know? Is this intentional copy change or did someone shorten it to fix a test?
Disappeared elements
<form>
<input name="email" type="email" />
- <input name="csrf_token" type="hidden" value="abc123" />
<button type="submit">Submit</button>
</form>A CSRF token input disappeared. This could be a security issue — an anti-CSRF protection was removed. Escalate immediately.
Layout-breaking class removals
- <div class="flex items-center justify-between">
+ <div>Layout classes removed. The content will likely reflow in an unintended way. Ask for a screenshot before approving.
Event handler changes
- <button onClick={handleSubmit} onKeyDown={handleKeyDown}>
+ <button onClick={handleSubmit}>Keyboard handler removed. Tab-navigation users may no longer be able to trigger this action.
How to Read Snapshot File Diffs
Snapshot file structure
A .snap file contains serialized snapshots:
exports[`ComponentName renders correctly 1`] = `
"<div class=\"component\">...</div>"
`;
exports[`ComponentName disabled state 1`] = `
"<div class=\"component component--disabled\">...</div>"
`;Each export corresponds to one toMatchSnapshot() call in one test. The key is {test name} {call number}.
Reading the diff context
GitHub and GitLab show .snap files as text diffs. The snapshot content is escaped — \" is " in the actual output.
If a diff is hard to read, paste the before and after into a diff tool or run the test locally:
# See what the current test produces
npx jest ComponentName.test.js --verbose
# Update snapshot and review with git diff
npx jest ComponentName.test.js --updateSnapshot
git diff __snapshots__/ComponentName.test.js.snapLocal review of snapshot changes is often clearer than trying to parse GitHub's diff view.
Reviewer Checklist
For every snapshot change in a PR:
Snapshot Review Checklist
=========================
[ ] Does the PR description explain what changed and why?
[ ] Are all aria-* attributes that existed before still present (or removed intentionally)?
[ ] Are alt attributes on images present?
[ ] Is the semantic HTML still appropriate (heading levels, button vs div, etc.)?
[ ] Did any text content change unexpectedly?
[ ] Did any security-relevant elements disappear (CSRF tokens, nonce attributes)?
[ ] Is there a screenshot or Storybook link for visual changes?
[ ] Were the snapshots updated with --updateSnapshot (intentional) or regenerated (accidental)?Not every item applies to every change. Use judgment.
When to Reject Snapshot Changes
Always reject:
- Removed accessibility attributes (
aria-*,alt,role) - Missing CSRF or security tokens
- Changes the developer can't explain
Investigate before approving:
- Large structural rewrites
- Changed text content (user-facing copy)
- Removed CSS classes that affect layout
- Changed element types (
divtobuttonor vice versa)
Approve without detailed review:
- Adding new elements that match the PR description
- Minor wording changes documented in the PR
- Formatting-only changes (whitespace, attribute order)
Setting Team Expectations
Add a snapshot review guide to your PR template:
## Snapshot Changes
If this PR includes snapshot changes, verify:
- [ ] Changes are intentional (not side effects of an unrelated change)
- [ ] Accessibility attributes are preserved or intentionally modified
- [ ] Visual changes are documented with a screenshot or Storybook link
- [ ] Snapshots were updated with `--updateSnapshot`, not regenerated from scratchTrain new team members on snapshot review. It's a skill that's rarely taught explicitly, and it's easy to assume "snapshot updated = everything is fine."
Automating Snapshot Review
Some teams use tooling to flag snapshot changes for mandatory review:
CODEOWNERS file:
# Require QA review for all snapshot changes
**/*.snap @qa-team
# Require senior dev review for inline snapshots
**/*.test.js @senior-devsGitHub Actions to comment on snapshot changes:
on:
pull_request:
paths:
- '**/*.snap'
jobs:
flag-snapshot-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
body: '⚠️ This PR includes snapshot changes. Please review the diff carefully for unintended regressions, accessibility changes, or missing elements.'
})This ensures every PR with snapshot changes gets an explicit reminder to review them.
Summary
Snapshot review is a code review skill. Treating snapshot updates as routine maintenance misses the entire point — snapshots exist to flag unintended changes, and approving them without review removes that protection.
For every snapshot change: understand why it changed, verify the change is intentional, check for accessibility and semantic regressions, and ask for a screenshot when visual output changed. The few minutes spent reviewing a snapshot diff can catch bugs that would otherwise reach production.