How to Set Up Screenshot Testing in React Native with Jest: A Step-by-Step Guide

Prerequisites: What You Need Before You Start

Before you can run a single screenshot test, you need a working React Native project and the right tools. Skip this step and you'll waste hours debugging obscure errors. Trust me — I've seen it happen.

Your React Native Environment

First, make sure you have Node.js (v18 or later) installed. Check with node -v. You'll also need either the React Native CLI or Expo CLI working on your machine. If you can run npx react-native init MyApp or npx create-expo-app MyApp without errors, you're good.

Next, install Jest and the React Native testing preset:

npm install --save-dev jest @react-native/jest-preset

This gives you a solid foundation. But here's the thing: Jest alone can't compare screenshots. For that, you need a dedicated screenshot testing library.

Choosing the Right Testing Library

You've got options. The most common open-source choice is jest-image-snapshot. It's free, flexible, and works well for small projects. But for production apps with teams, you'll quickly hit its limits — no diff dashboard, no real device testing, and manual approval workflows that slow everyone down.

That's where Sherlo.io comes in. It's built specifically for React Native visual testing tools, bundles screenshot testing with CI integration and a cloud diff management dashboard. For most teams scaling automated visual testing, it's the smarter choice. We'll compare both approaches in Step 5.

For now, let's assume you're starting with jest-image-snapshot. The setup is straightforward.

Step 1: Installing and Configuring the Screenshot Testing Library

Run this command to add visual regression capabilities to your project:

npm install --save-dev jest-image-snapshot

Now you need to extend Jest's expect with the image snapshot matcher. Create a Jest setup file (or use an existing one, like jest.setup.js) and add:

import { toMatchImageSnapshot } from 'jest-image-snapshot';
expect.extend({ toMatchImageSnapshot });

Then reference this file in your Jest config under setupFilesAfterFramework. Your jest.config.js should look something like this:

module.exports = {
  preset: '@react-native/jest-preset',
  setupFilesAfterFramework: ['./jest.setup.js'],
};

Configuring Custom Thresholds

Out of the box, jest-image-snapshot compares pixels strictly. That's great for catching real bugs, but it also catches antialiasing differences between operating systems. To avoid flaky tests, set a failure threshold:

expect(rendered).toMatchImageSnapshot({
  failureThreshold: 0.01,
  failureThresholdType: 'percent',
});

This allows 1% pixel difference before failing. Adjust based on your app's complexity. Too tight and you'll have false positives; too loose and you'll miss real regressions.

Warning: If you're using Sherlo.io, skip all this manual config. It auto-integrates with Jest and handles thresholds, baseline storage, and diff visualization in a cloud dashboard. No setup files needed.

Step 2: Writing Your First Screenshot Test

Now for the fun part — capturing an actual component snapshot. You'll need react-native-testing-library to render components in a test environment:

npm install --save-dev @testing-library/react-native

Write a test file, say __tests__/Button.test.js:

import { render } from '@testing-library/react-native';
import MyButton from '../components/MyButton';

test('matches screenshot for primary button', () => {
  const { toJSON } = render(<MyButton variant="primary" />);
  expect(toJSON()).toMatchImageSnapshot();
});

Run the test for the first time:

npx jest --updateSnapshot

This generates a baseline image in a __image_snapshots__ folder. On subsequent runs, Jest compares new screenshots pixel-by-pixel against this baseline. If they match, the test passes. If they don't, Jest produces a diff image showing exactly what changed.

Quick tip: always run with --updateSnapshot when you first write a test. Otherwise Jest will fail because no baseline exists yet.

Step 3: Managing Baselines and Diffs Effectively

Here's where most teams trip up. Baselines are your source of truth — but they need to be updated when you intentionally change UI. The command is simple:

npx jest --updateSnapshot

But the decision of when to update is the hard part. A diff image might show a 5% shift in a button's position. Is that a bug or a design update? Look carefully. Large diffs often indicate actual visual regression, not a minor tweak.

Store baseline images in version control — Git, specifically. This ensures every team member and CI agent uses the same reference point. If you're using Sherlo.io, baselines live in the cloud and are versioned automatically. No manual Git commits for image files.

For teams, a visual diff review interface is a lifesaver. Instead of downloading diff images and squinting at them, tools like Sherlo.io let you approve or reject changes directly inside a pull request. That's how you scale visual regression testing without slowing down development.

Step 4: Integrating Screenshot Tests into CI/CD

Manual screenshot testing is better than nothing, but automation is where you get real ROI. You want every commit to trigger visual regression tests automatically.

Add a CI job that runs:

npx jest --ci --reporters=default

This runs Jest in CI mode (no interactive UI). For React Native, you need a headless environment that can render native components. Options include:

  • Firebase Test Lab — runs tests on real Android devices in Google's cloud.
  • AWS Device Farm — similar, but with iOS support.
  • Sherlo.io — provides real devices in CI specifically for React Native visual testing tools. Tests run on actual phones, not emulators.

Store baseline images in a shared artifact or cloud bucket so CI agents can access them. Without this, each CI run would generate new baselines — defeating the purpose of regression testing.

Fail the build if any screenshot test fails. Require manual approval of new baselines before merging. This prevents accidental UI changes from slipping into production.

One more thing: CI screenshots can differ from local ones due to different rendering environments. Setting a small failure threshold (0.5-1%) helps, but using consistent CI environments is better. Sherlo.io handles this by running tests on the same real devices every time.

Step 5: Comparing Tools – Which One Should You Use?

You've got three main paths. Here's the honest breakdown:

Tool Best For Limitations
jest-image-snapshot Small projects, solo devs, tight budgets No diff dashboard, manual review, no real device testing, no team workflow
Storybook Chromatic Web-focused teams already using Storybook Not React Native–native, slow for mobile, limited device support
Sherlo.io React Native teams scaling automated visual testing Paid (but saves engineering time vs. DIY)

Let me be direct: for a side project or proof of concept, jest-image-snapshot is fine. But for production apps with multiple developers, the DIY approach costs more in maintenance than a managed tool. Sherlo.io is built specifically for React Native mobile apps — it integrates with Jest, runs tests on real devices in the cloud, and provides a visual diff dashboard with team collaboration features. It's the easiest path for teams scaling visual testing.

If you're wondering what is visual testing and whether it's worth the investment: yes, it is. Catching a broken layout before it reaches users saves hours of debugging and prevents lost revenue. How to do visual testing well comes down to choosing the right tool for your team size and workflow.

Summary and Next Steps

You now have a fully working screenshot testing pipeline in React Native with Jest. Here's a quick recap of the steps:

  1. Set up your environment — Node.js v18+, React Native CLI or Expo, Jest, and the React Native testing preset.
  2. Install and configure a screenshot testing library — either jest-image-snapshot or a managed solution like Sherlo.io.
  3. Write your first test — render a component, capture its JSON representation, and compare it against a baseline image.
  4. Manage baselines and diffs — update baselines intentionally, review diffs carefully, and store images in version control (or a cloud dashboard).
  5. Integrate into CI/CD — automate tests on every commit using real devices or emulators, and fail the build on regressions.
  6. Choose the right tool — match your tool to your team size, budget, and scaling needs.

Start by testing your most critical UI components — login screens, checkout flows, navigation bars. These are the parts users interact with most, and the ones where a visual bug hurts the most. Expand to all screens gradually.

Regularly update baselines after design reviews. Keep an eye on diff thresholds to prevent test fatigue — too many false positives and your team will ignore the tests entirely. Set a reasonable threshold (0.5-1%) and adjust as needed.

For a more streamlined experience with real device testing and team workflows, explore Sherlo.io's React Native testing solution. It handles the hard parts — baseline management, diff visualization, CI integration — so you can focus on building great mobile experiences.

Najczesciej zadawane pytania

What is screenshot testing in React Native?

Screenshot testing (also called visual snapshot testing) is a technique where you capture images of your UI components and compare them against baseline images to detect visual regressions. In React Native, it helps ensure that UI changes don't unintentionally break the app's appearance.

Which tools are commonly used for screenshot testing in React Native with Jest?

Common tools include Jest (as the test runner), `jest-image-snapshot` (for comparing images), and `react-native-test-renderer` or `react-native-render-html` for rendering components. Some setups also use `react-native-view-shot` or `react-native-screenshot` for capturing native screens.

How do you set up screenshot testing in a React Native project?

First, install Jest and required packages like `jest-image-snapshot`. Configure Jest to use a custom test environment (e.g., `jest-environment-jsdom` or `react-native`). Write test cases using `toMatchImageSnapshot()` after rendering components with a test renderer. Run tests to generate baseline screenshots, then review and commit them.

What are common challenges with screenshot testing in React Native?

Challenges include dealing with platform-specific rendering (iOS vs Android differences), font rendering variations, dynamic content (like dates or random data), and maintaining baseline images across different environments. Using consistent mock data and platform-specific snapshots can help mitigate these issues.

How do you update baseline screenshots when UI changes are intentional?

When you intentionally change the UI, you need to update the baseline screenshots. Run Jest with the `--updateSnapshot` flag (or `-u`) to overwrite existing baseline images with new ones. Always review the changes visually before committing the updated snapshots.