VOOZH about

URL: https://blog.logrocket.com/storybook-visual-regression-testing-lost-pixel-react/

โ‡ฑ Storybook visual regression testing with Lost Pixel and React - LogRocket Blog


2023-01-17
1625
#react
Kapeel Kokane
155176
109
๐Ÿ‘ Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

Testing is a vital part of modern-day software development; in fact, the TDD paradigm, short for test-driven development, stresses the importance of writing tests before writing even a single line of code.

๐Ÿ‘ Storybook Lost Pixel Getting Started

For backend applications, this might be straightforward; however, testing UI-centric applications can be quite tricky. Here, Lost Pixel comes in handy; Lost Pixel is an open source tool that helps identify regressions in the user interface with every push that we make to the application.

In this article, weโ€™ll learn how to test a few Storybook components using Lost Pixel. Letโ€™s get started!

๐Ÿš€ Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

What is Lost Pixel?

According to the Lost Pixel GitHub page, Lost Pixel is an open source visual regression testing tool. Lost Pixel renders actual images of components; when we make any changes to the component, Lost Pixel compares the original images to the changed ones, thereby detecting regression.

Lost Pixelโ€™s approach is quite different from snapshot testing using Jest, in which the entire component is represented in its verbose, textual format, and then compared with the changed version.

At the time of writing, Lost Pixel supports Storybook, Ladle, Next.js, Gatsby, and Remix. In this article, weโ€™ll explore using Lost Pixel alongside Storybook components.

What is Storybook?

Storybook is a tool that can help us optimize our React development workflow. According to the official Storybook documentation, Storybook is a tool for UI development that isolates components, making development faster and easier.

We can think of Storybook as a platform that lets us code the building blocks for our applications independently of each other. When we finally put all of them together into meaningful applications, weโ€™ll encounter fewer bugs and surprises in behavior. In addition, Storybook provides free documentation of all our components. To get more clarity on how all of that works, letโ€™s build a hands-on project with Storybook, React, and Vite.

Setting up Storybook with React

Storybook with React and Vite

In this article, weโ€™ll set up Storybook in a React project. For that, weโ€™ll first need a base React project. First, letโ€™s create our React project using Vite:

npm create vite@latest

Weโ€™ll follow the prompts on the screen to create a React project with JavaScript. Once that finishes running, we can run the project that we just created by going into that directory and starting the dev server:

cd storybook-testing
npm run dev

You should see the Vite + React homescreen running on http://127.0.0.1:5173/ by visiting the same URL in the browser:

๐Ÿ‘ Vite React Homescreen Browser

Storybook setup

Now, weโ€™ll set up Storybook in this repo by running the following code:

npx storybook init

The command above will add the necessary files and make the required changes to the package.json for Storybook to work. If you get an error like the one below, select yes to create a new .npmrc file in the repo:

๐Ÿ‘ Error Install Npm Rc Package

Next, we can run Storybook using the command below:

npm run storybook

The command above will bring up the Storybook homepage on http://localhost:6006/, which looks like the following image:

๐Ÿ‘ Storybook Homepage View

Notice that Storybook has already created a few button components that we can explore using the UI:

๐Ÿ‘ Storybook Button Component Example Gif

Weโ€™ll use Lost Pixel to perform regression testing on these pre-defined buttons.

Repo setup

With those changes, we can push the code to a new GitHub repo as follows:

git init
git add --all
git commit -m 'first commit'
git remote add origin <repo_origin_url>
git push -u origin main

Now that the repo is ready, weโ€™ll add the Lost Pixel code.

Lost Pixel setup

With our UI set up, weโ€™ll introduce Lost Pixel into the same repository. First, we install Lost Pixel using the command below:

npm install lost-pixel

Next, we create a lost-pixel.config.js file at the root of our Vite project:

import { CustomProjectConfig } from 'lost-pixel';
export const config: CustomProjectConfig = {
 storybookShots: {
 storybookUrl: './storybook-static',
 },
 generateOnly: true,
 failOnDifference: true,
};

In the code above, weโ€™re telling Lost Pixel where to find the Storybook components. In our case, once the Storybook build command runs, the Storybook components will be found at the ./storybook-static URL.

Next, we need to create two GitHub workflows. In the root of the repo, create a folder named .github and another folder named workflows inside of it. Weโ€™ll place the following two files inside the workflows folder.

lost-pixel-update.yml

The lost-pixel-update.yml workflow will help Lost Pixel create the baselines against which it will perform regression testing. While performing the tests, Lost Pixel needs to know the right way to render the component in order to determine whether the component has diverged from that behavior.

The lost-pixel-update.yml file looks like the following:

on: [workflow_dispatch]
jobs:
 build:
 runs-on: ubuntu-latest
 steps:
 - name: Checkout
 uses: actions/checkout@v2
 - name: Setup Node.js
 uses: actions/setup-node@v2
 with:
 node-version: 16.x
 cache: 'npm'
 - name: Install dependencies
 run: npm ci
 - name: Build Storybook components
 run: npm run build-storybook
 - name: Run Lost Pixel container
 id: lp
 uses: lost-pixel/[email protected]
 env:
 LOST_PIXEL_MODE: update
 - name: Create Pull request
 uses: peter-evans/create-pull-request@v4
 if: ${{ failure() && steps.lp.conclusion == 'failure' }}
 with:
 token: ${{ secrets.GH_TOKEN }}
 commit-message: update lost-pixel baselines
 delete-branch: true
 branch: "lost-pixel-baselines/${{ github.ref_name }}"
 title: "Lost Pixel updating baselines - ${{ github.ref_name }}"
 body: Automated baseline update PR - lost pixel

Notice that the steps in this GitHub action are straightforward. We create a Node.js container, build our Storybook components, and then run Lost Pixel using the pre-built action released on the GitHub action store, lost-pixel/[email protected].

This action runs the Lost Pixel action in update mode. However, notice that the last step is special, creating a pull request with the changed components so that those can be merged with the repo and act as the new baseline components. Weโ€™re using the secrets.GH_TOKEN to authenticate while we create the pull request, which weโ€™ll review later.

lost-pixel-test.yml

The lost-pixel-test.yml workflow will be triggered on every push to the repo, thereby generating the new images for the components and comparing them against those generated while running the baseline tests. If there is any difference between the two, the test will fail. The lost-pixel-test.yml file looks like the following code:

on: [push]
jobs:
 build:
 runs-on: ubuntu-latest
 steps:
 - name: Checkout
 uses: actions/checkout@v2
 - name: Setup Node
 uses: actions/setup-node@v2
 with:
 node-version: 16.x
 cache: 'npm'
 - name: Install dependencies
 run: npm ci
 - name: Build Storybook
 run: npm run build-storybook
 - name: Lost Pixel
 id: lp
 uses: lost-pixel/[email protected]

This action is almost the same as the previous action with some slight differences. The last step that creates a PR is missing, and weโ€™re also not running Lost Pixel in update mode. As we noticed in the lost-pixel-update.yml file, the PR creation step requires that we supply secrets.GH_TOKEN.


Over 200k developers use LogRocket to create better digital experiences

๐Ÿ‘ Image
Learn more โ†’

Generate GitHub auth token

Check out this GitHub repo for the detailed steps to generate a personal access token. In short, the steps are as follows:

  • Visit your GitHub profile settings
  • Click on Developer settings and then Personal access token
  • Click on Tokens (classic) and then Generate new token
  • Select the scope for the token as workflow

๐Ÿ‘ Generate New Personal Access Token Github Classic

Once the token is generated, copy it to the clipboard. We need to add it as a secret in the repo:



  • On the repository page, click on Settings
  • Click on Secrets and then Actions
  • Click on New repository secret

๐Ÿ‘ Add Github Token Secret

Name the secret GH_TOKEN, paste the secret, and then click on Add secret. This will add the secret to the repo so that the PR creation step goes through smoothly.

Generating baselines

With this setup done, we can now run the action to generate the baselines for all our of Storybook components. Add the two newly created .yml files, create a commit, and push it to the remote repo. We can see that the test gets triggered immediately on a code push, but it fails because there are no baselines:

๐Ÿ‘ Create Baselines Storybook Components

Letโ€™s run the workflow to generate baselines. Visit the Actions tab of the GitHub repo, then select the lost-pixel-update.yml workflow. Click on Run workflow:

๐Ÿ‘ Run Lost Pixel Storybook Github Action

With all the previous steps completed, the workflow runs smoothly and creates a pull request as a result:

๐Ÿ‘ Storybook Lost Pixel Workflow Run Success

Merge the pull request so that the .png files corresponding to the baselines get merged in the repo.

Testing visual regressions

With the baselines configured, letโ€™s introduce some visual regressions in our Storybook component. Visit the stories Button.stories.jsx file and change the label of the primary button to say Test Button:

export const Primary = Template.bind({});
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Primary.args = {
 primary: true,
 label: 'Test Button',
};

Save the file, commit, and push to the remote:

git commit -m 'testing regression'
git pull --rebase
git push

You should see that the lost-pixel-test.yml workflow is triggered immediately. It runs, successfully pointing out that there is a regression in the primary button version of the component:

๐Ÿ‘ Lost Pixel Test YML Workflow Triggered

If this is an expected regression, we can trigger the lost-pixel-update.yml workflow as before, and the baselines would be updated.

Conclusion

Lost Pixel provides us with an alternate method to perform UI regression testing, which is significantly different from the standard practice of snapshot testing. If your project uses lots of Storybook components, and youโ€™re not concerned about additional .png images being pushed to the repository, you can explore Lost Pixel in your projects for detecting UI regressions.

Get set up with LogRocket's modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');
     
    // Add to your HTML:
    
    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
     
  3. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
๐Ÿ‘ Image
๐Ÿ‘ Image
๐Ÿ‘ Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension โ€” no new framework required.

๐Ÿ‘ Image
Ikeh Akinyemi
Jun 12, 2026 โ‹… 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo โ€” with email/password login, Google OAuth, session persistence, and protected routes.

๐Ÿ‘ Image
Chinwike Maduabuchi
Jun 9, 2026 โ‹… 13 min read

AI dev tool power rankings & comparison [June 2026]

Compare the top AI development tools and models of June 2026. View updated rankings, feature breakdowns, and find the best fit for you.

๐Ÿ‘ Image
Chizaram Ken
Jun 8, 2026 โ‹… 11 min read

How to check username availability at scale with Bloom filters

Learn how Bloom filters reduce database lookups for username availability checks while preserving correctness at scale.

๐Ÿ‘ Image
Rosario De Chiara
Jun 8, 2026 โ‹… 6 min read
View all posts

Would you be interested in joining LogRocket's developer community?

Join LogRocketโ€™s Content Advisory Board. Youโ€™ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now