Integrating Testing Library Snapshots Using Percy
Integrating Testing Library Snapshots Using Percy
What if your UI tests could tell you what changed, why it changed, and whether it actually matters to users?
For many teams, traditional UI tests answer only part of that question, often missing visual regressions or producing fragile assertions that break too easily.
Testing Library shifted how teams write UI tests by focusing on user behavior instead of implementation details. At the same time, snapshot testing emerged as a way to track UI changes automatically and surface unexpected differences early.
This article explains what a Testing Library is, how it connects to snapshot testing, and how to use React Testing Library with Percy for visual snapshots. You’ll also learn why Percy is often preferred for snapshot testing and best practices to make the most of this setup in real-world projects.
What is a Testing Library?
A Testing Library is a set of tools designed to help developers test user interfaces the way real users interact with them. Instead of focusing on component internals or implementation details, it encourages testing visible behavior like text, roles, and interactions.
The core idea is simple: tests should resemble how users find and use elements on the screen. This makes tests more resilient to refactors and UI changes that don’t affect user behavior.
Popular libraries such as React Testing Library, Vue Testing Library, and Angular Testing Library follow this philosophy. They are commonly used for component and integration testing in modern frontend applications.
How is Testing Library Related to Snapshot Testing?
Snapshot testing and Testing Library can work together but serve different purposes in verifying UI behavior.
React Testing Library (RTL) focuses on testing what users see and interact with, queries like getByRole, getByText, and assertions like toHaveTextContent mirror how real users use your app. In contrast, snapshot testing captures a serialized representation of rendered output (e.g., DOM structure) and compares it on subsequent runs to detect changes.
When used thoughtfully, snapshot tests can support RTL by providing a baseline snapshot of the DOM that helps with debugging or catching unintended changes, especially for complex markup. However, snapshots should not replace explicit behavior tests, and you should keep snapshots small and focused to avoid brittleness.
How They Connect (with Practical Notes)
- Snapshot as a Debug Aid with RTL: When an RTL query fails, snapshots can help visualize the rendered DOM at that moment. Capturing container and using toMatchSnapshot() gives a formatted snapshot of the DOM tree, making it easier to spot why a query didn’t find an element.
import { render } from '@testing-library/react'; test('renders correctly', () => { const { container } = render(<MyComponent />); expect(container).toMatchSnapshot(); });
- Snapshots vs Behavior Tests: RTL encourages tests based on behavior, not implementation. Snapshots record the full output but don’t tell you why output matters or what intention your test asserts. Include explicit RTL assertions along with snapshots to verify user-observable results rather than just structure.
- Handling Portals and Complex DOM: Some components, like those using React portals, place parts of the UI outside the default container. If you snapshot only the default container, you may miss those parts. Instead, use baseElement or query specific elements and snapshot them.
const { baseElement } = render(<ModalComponent />); expect(baseElement).toMatchSnapshot();
- Small, Focused Snapshots Are More Maintainable: Big snapshots containing entire pages or large trees become hard to review and maintain. Capture only what’s necessary, split tests or use helpers like custom serializers to keep snapshots concise.
- Use Snapshots as Safety Nets, Not Sole Validators: Snapshots are good at telling you something changed, but they don’t always indicate whether the change breaks behavior. Combine snapshots with detailed RTL assertions to ensure both structural consistency and actual UI behavior.
30,000 Snapshot Tests For One Perfect UI
How to Use React Testing Library
React Testing Library (RTL) is designed to help you test React components from the user’s perspective. Instead of checking component internals or state, RTL encourages testing what users can actually see and interact with in the UI.
The core workflow is simple: render a component, query elements the way a user would, and make assertions based on visible behavior. This approach results in tests that are easier to read, less brittle, and more resilient to refactors that don’t affect user experience.
Core Concepts and Usage
- Render Components in a Realistic Environment: RTL’s render function mounts components into a virtual DOM that closely mirrors how they appear in the browser. This allows tests to interact with components as users would, rather than inspecting internal implementation details.
import { render } from '@testing-library/react'; import Button from './Button'; test('renders button', () => { render(<Button label="Submit" />); });
- Query Elements the Way Users Do: RTL provides queries like getByRole, getByText, and getByLabelText. These prioritize accessibility and visible content, which helps ensure your UI works for real users, including those using assistive technologies.
import { screen } from '@testing-library/react'; expect(screen.getByRole('button', { name: /submit/i })).toBeInTheDocument();
- Avoid Testing Implementation Details: RTL discourages querying by class names, IDs, or component structure. This keeps tests stable even when internal markup changes, as long as the user-facing behavior remains the same.
- Test User Interactions, Not Just Static Output: Use userEvent to simulate clicks, typing, and other interactions. This ensures your tests reflect how users actually engage with the interface rather than triggering events artificially.
import userEvent from ‘@testing-library/user-event’;
test('submits form', async () => { render(<LoginForm />); await userEvent.type(screen.getByLabelText(/email/i), 'user@test.com'); await userEvent.click(screen.getByRole('button', { name: /login/i })); });
- Assert on Outcomes, Not Steps: After interactions, assert on what changed in the UI, such as new text appearing or buttons becoming disabled. This keeps tests focused on results rather than internal processes.
- Use Snapshots Sparingly with RTL: RTL allows snapshot testing via the container or baseElement, but snapshots should support debugging or catch unexpected changes, not replace explicit assertions. Small, targeted snapshots are easier to review and maintain.
const { container } = render(<Alert type="error" />); expect(container).toMatchSnapshot();
Why This Matters Before Adding Visual Snapshots
React Testing Library establishes behavioral confidence by ensuring components behave correctly from a user’s perspective. Once this foundation is in place, tools like Percy can layer on visual confidence, validating that the UI also looks correct across changes.
This separation of concerns keeps tests purposeful, readable, and scalable as your application grows.
How to Use Percy For Snapshot Testing
BrowserStack Percy is a visual testing tool specialising in visual automation through snapshots and baseline comparison. In essence, Percy runs visual validation tests through running hundreds and thousands of snapshots in contrast with an approved baseline snapshot.
Percy adds a visual layer to your existing test suite by capturing UI snapshots during test runs and comparing them against approved baselines. Instead of relying on DOM snapshots alone, Percy renders your application in real browsers and flags meaningful visual changes, exactly where they happen in the UI.
When paired with React Testing Library, Percy fits naturally into your workflow. You keep writing behavior-focused tests, and Percy quietly handles visual validation in the background, turning your functional tests into visual regression checks with minimal extra effort.
Percy is the Ultimate Next-Gen Snapshot Testing Tool You Cannot Miss!
Setting Up Percy with React Testing Library
- Install Percy and Its Test Runner Integration
Percy integrates with popular test runners like Jest, Cypress, Playwright, and Selenium. For React Testing Library with Jest, you typically install Percy’s CLI and browser integration.
npm install --save-dev @percy/cli @percy/playwright- Wrap Test Execution with Percy
Percy runs alongside your existing test command. This ensures snapshots are captured automatically during test execution without changing how your tests are structured.
npx percy exec -- npm test- Add Snapshot Calls at Key UI States
Use Percy’s snapshot command to capture visuals at meaningful points, such as initial render, after user interaction, or once async data has loaded.
import { percySnapshot } from '@percy/playwright'; test('renders error state', async ({ page }) => { await page.goto('/login'); await percySnapshot(page, 'Login – Error State'); });
Capturing Reliable Visual Snapshots
- Snapshot Stabilization by Default: Percy automatically stabilizes snapshots by freezing animations, disabling blinking cursors, and normalizing dynamic rendering. This prevents flaky diffs caused by timing-based UI changes rather than real regressions.
- Control When Snapshots Are Taken: Snapshots should be captured only after the UI reaches a stable, user-visible state. Waiting for network requests, animations, or lazy-loaded components ensures accurate visual comparisons.
- Name Snapshots Clearly and Consistently: Descriptive snapshot names make reviews faster and more actionable, especially when multiple states of the same component are captured across tests.
Reviewing and Approving Changes
- Visual Diffs Highlight What Changed: Percy compares each new snapshot against its baseline and highlights only the pixels that changed. This makes it easy to distinguish intentional UI updates from accidental regressions.
- Approve or Reject in Pull Requests: Percy integrates directly with GitHub and other CI providers. Reviewers can approve visual changes alongside code reviews, keeping UI decisions visible and documented.
- Baseline Updates Stay Intentional: Approved changes automatically become the new baseline. This ensures future comparisons reflect the latest, accepted UI rather than outdated visuals.
Why Perform Snapshot Testing Through Percy?
Percy takes snapshot testing beyond static DOM comparisons by validating how your UI actually looks in real browsers. It focuses on reducing noise, improving review confidence, and scaling visual testing across teams and platforms, without changing how developers write tests.
Below is a feature-focused view of how Percy strengthens snapshot testing, especially when used with React Testing Library and modern CI workflows.
| Feature | Description | Impact |
|---|---|---|
| Snapshot Stabilization | Automatically freezes animations, blinking cursors, and transient UI states before snapshot capture. | Eliminates flaky diffs caused by timing issues instead of real UI regressions. |
| Seamless RTL Compatibility | Works alongside React Testing Library without changing test structure or user-centric assertions. | Keeps tests focused on behavior while adding visual coverage effortlessly. |
| Scalable Snapshot Limits | Handles large snapshot volumes efficiently, even for component-heavy applications. | Supports growing design systems without overwhelming test maintenance. |
| Intelligent Visual Diffing | Uses perceptual diffing to highlight only meaningful visual changes while ignoring insignificant pixel noise. | Reduces false positives and speeds up visual review cycles. |
| Debug-Friendly Snapshot UI | Side-by-side diffs, highlighted changes, and zoom tools simplify visual analysis. | Shortens investigation time when UI regressions are detected. |
| Real Browser Rendering | Snapshots are captured in real Chromium, Firefox, and WebKit environments rather than simulated DOM outputs. | Ensures visual accuracy that closely matches production user experiences. |
| Cross-Browser Snapshot Support | Captures snapshots across multiple browsers from a single test run. | Catches browser-specific rendering issues early in development. |
| GitHub and GitLab Integrations | Deep integrations with popular version control platforms for inline snapshot review. | Improves collaboration between developers, designers, and QA teams. |
| CI-Native Workflow | Snapshots are captured during CI runs and surfaced directly in pull requests. | Makes visual changes reviewable at the same time as code changes. |
| Baseline Management | Approved snapshots automatically become the new visual baseline for future comparisons. | Prevents outdated snapshots and keeps visual history aligned with product evolution. |
Best Practices to Utilize Percy for React Testing Library
Percy works best when visual snapshots are intentional, stable, and closely tied to real user behavior. When combined with React Testing Library, the goal is not to snapshot everything, but to capture the UI states that truly matter as your application evolves.
Below are practical best practices to help you get consistent, high-signal snapshots without slowing down your test suite or review process.
- Snapshot user-visible states, not internal component structure: Trigger snapshots after interactions a real user would perform, such as form submissions, error states, or completed async actions, rather than immediately after rendering.
- Avoid snapshotting every test case: Use Percy snapshots selectively for key UI states. Over-snapshotting increases review noise and makes it harder to spot meaningful visual regressions.
- Wait for the UI to fully stabilize before capturing: Ensure data fetching, animations, lazy-loaded components, and transitions have completed so snapshots reflect a finished, user-ready interface.
- Use clear, descriptive snapshot names: Snapshot names should communicate intent, such as Checkout – Payment Error State, making diffs easier to review during pull requests.
- Pair functional assertions with visual snapshots: Continue asserting behavior using RTL queries, then add Percy snapshots to validate visual correctness once the expected behavior is confirmed.
- Group related snapshots logically: Capture multiple states of the same component in a single test where possible, rather than spreading them across disconnected test files.
- Minimize dynamic content where possible: Mock timestamps, random IDs, or personalized content to reduce unnecessary visual changes between test runs.
- Review visual diffs as part of code review: Treat Percy diffs as first-class review artifacts, just like unit test results or lint checks, to prevent unintentional UI changes from slipping through.
- Update baselines intentionally, not reflexively: Approve snapshot changes only when the visual update is expected and agreed upon, avoiding baseline drift over time.
- Document snapshot strategy for the team: Establish shared guidelines for when and how to add Percy snapshots so visual testing remains consistent across contributors.
Switch to Percy to unlock precision-driven snapshot testing. Unlock up to 5000 screenshots per month for free!
Conclusion
Snapshot testing has evolved from a quick debugging aid into a meaningful layer of UI quality assurance. When combined with React Testing Library, it helps teams validate not just how components behave, but how they actually appear to users during real interactions.
Percy strengthens this approach by bringing real-browser rendering, stabilized snapshots, and actionable visual diffs into the development workflow. Instead of brittle DOM snapshots or noisy test failures, teams get high-confidence visual feedback directly in pull requests.
Used thoughtfully, Percy-based snapshot testing scales with modern front-end applications, supporting fast iteration while keeping visual regressions under control as codebases, teams, and design systems grow.
Related Articles
What is Visual Testing [A 2026 Guide]
Many visual bugs slip past automation. Visual testing adds a safety net by comparing how your websit...
A Complete Guide to Visual UI Testing in 2026
Visual UI testing detects visual changes across screens and devices. This guide covers how it works ...
What is Visual Regression Testing [2026]
Visual regression testing detects unintended UI changes by comparing visual baselines. This article ...
