Sign inSign up

Visual testing with Cypress

Integrate Chromatic with Cypress to get visual test coverage at every point of your end-to-end test run

loading
Joe Vaughan
@joevaugh4n
Last updated:
Summary: Learn how to augment your Cypress end-to-end tests with Chromatic's visual testing so that you can catch UI bugs and functional bugs in the same workflow. Find out more about Chromatic's Cypress integration.

Cypress’s end-to-end (E2E) tests are designed to validate the user journey throughout an application from start to finish. However, by default, Cypress's tests don’t include visual tests that catch bugs or unexpected changes in your application’s appearance.

In this guide, we’ll explore how to take your Cypress tests further by integrating automatic visual tests, so you can confirm your application’s appearance and functionality in the same E2E test run.

What is visual testing?

Visual testing aims to catch unexpected changes in your application’s user interface. Typically, you perform visual tests through a process of image or screenshot comparison. First, set a baseline of how your UI should look. Then, test your UI after any code changes and compare the visual result against the baseline to spot any differences.

With purpose-built visual testing tools, you can perform visual tests manually or automatically. In this tutorial, we’ll integrate Cypress with Chromatic, one such automated visual testing tool.

Cypress’ visual testing support

Cypress doesn’t automatically provide a convenient way to check an application’s appearance. Technically, you can test UI in Cypress by using the same tests that you perform for validating your application’s functionality. However, functional testing for styling is intensive on time and maintenance: it's possible that you would need to assert classnames and styling across thousands of UI elements.

Fortunately, Cypress's plugin ecosystem enables you to integrate third-party visual testing tools within your E2E tests. This allows you to gain coverage of your application’s visuals within your current test suite. In fact, Cypress’s docs recommend integrating a third-party visual testing integration.

Integrate Chromatic with Cypress

Chromatic is a specialized visual testing tool built by the creators of Storybook, and integrating with Cypress takes five quick steps:

  1. Create a Chromatic project and install Chromatic’s Cypress visual test dependencies in your codebase via the command line:
npm install --save-dev chromatic @chromatic-com/cypress
  1. Import Chromatic in cypress/support/e2e.js:
import "@chromatic-com/cypress/support";
  1. Install Chromatic in cypress.config.js:
const { defineConfig } = require("cypress");
const { installPlugin } = require("@chromatic-com/cypress");

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      installPlugin(on, config);
    },
  },
});
  1. Run Cypress with npx cypress run while prepending ELECTRON_EXTRA_LAUNCH_ARGS=--remote-debugging-port=9222. This environment variable tells Cypress that we want to use the Chrome Devtools Protocol (CDP), which lets Chromatic listen to network requests and archive resources during your test run. We specifyport=9222, but any unused port number is okay!
ELECTRON_EXTRA_LAUNCH_ARGS=--remote-debugging-port=9222 npx cypress run
  1. Finally, run a Chromatic build to generate baseline images!
CHROMATIC_ARCHIVE_LOCATION=./cypress/downloads npx chromatic --cypress -t=<TOKEN>

You’re all set! Next, let’s explore the advantages of visual testing with Cypress and Chromatic in a real-world project.

Validating the user interface

Imagine you’re developing an e-commerce web app and have been tasked with verifying data flow between the backend and the front end for a key product page.

Tungsten cube page on Amazon

First, let’s write a Cypress test script to take a page element that depends on data flow (such as the page title) and validate how it renders:

describe("My First Test", () => {
  it("Visits product page", () => {
    // Go to the Amazon product page
    cy.visit(
      "https://www.amazon.com/Tungsten-Cube-Biggest-Size/dp/B07WK9WLZ8/",
    );
    // Verify the page title
    cy.title().should(
      "eq",
      'Amazon.com: The 4" Tungsten Cube - Biggest Size : Toys & Games',
    );
  });
});

The test passes! However, without writing any extra code, notice that you also gained a fully interactive snapshot of the test case, viewable in Chromatic.

Test in Chromatic

We can use this snapshot to validate data throughout the entire product page without needing to write any new assertions. You can see and verify all of the page’s data properties right there in the interactive snapshot.

Screenshot at any stage of a Cypress test

Next, let’s run a Cypress visual test that captures the different dynamic states of the search bar. We’ll return to our first test, use cy.get to navigate to the search bar, and enter a search (‘rubik’s cube’):

describe("My First Test", () => {
  it("Searches from product page 1", () => {
    // 👇 go to the product page
    cy.visit(
      "https://www.amazon.com/Tungsten-Cube-Biggest-Size/dp/B07WK9WLZ8/",
    );
    // 👇 verify the page title
    cy.title().should(
      "eq",
      'Amazon.com: The 4" Tungsten Cube - Biggest Size : Toys & Games',
    );
    // 👇 find the main search field and type in it
    cy.get(".nav-search-field > input").type("rubik’s cube");
  });
});

This generates passing Cypress tests and gives you a snapshot of the final state of the UI, showing ‘rubik’s cube’ typed into the search field:

Three different data states in a test run, captured in Chromatic as snapshots

You can configure your tests to run Cypress visual tests and capture snapshots at specific points using the cy.takeSnapshot() task.

We can use this method to capture a snapshot when we first focus the search field:

describe("My First Test", () => {
  it("Searches from product page 2", () => {
    // 👇 go to the product page
    cy.visit(
      "https://www.amazon.com/Tungsten-Cube-Biggest-Size/dp/B07WK9WLZ8/",
    );
    // 👇 verify the page title
    cy.title().should(
      "eq",
      'Amazon.com: The 4" Tungsten Cube - Biggest Size : Toys & Games',
    );
    // 👇 find & focus the search field
    cy.get(".nav-search-field > input").focus();
    // 👇 tell Chromatic to take a snapshot here
    cy.takeSnapshot();
    // 👇 finish the test as before
    cy.get(".nav-search-field > input").type("rubik’s cube");
  });
});

When this test runs, Cypress will capture two snapshots: one of the focused search field, and another of the end of the test. The two snapshots will appear in Chromatic like so:

Visual test for tungsten cube page

Bringing it all together

First, we explored the limitations of functional testing for catching visual regressions. Then, we learned how to resolve them by following Cypress’s recommendation and integrating a visual testing tool to get E2E tests that simultaneously check your app's look and feel. Now, you can perform visual tests without any extra assertions!

Try Chromatic for free

Chromatic’s Cypress integration has a free tier, and you can get started without entering any credit card information.

Try Chromatic with Cypress now, or head to the docs to learn more about our Cypress integration.

Did this article help you?

Get free UI development guides and tutorials like this emailed to you.

4,477 developers and counting

We’re hiring!

Join the team behind Storybook and Chromatic. Build tools that are used in production by 100s of thousands of developers. Remote-first.

View jobs

Popular posts

Functional testing in 2024

Verify that your application behaves as expected on every code change
loading
Joe Vaughan
Product
PricingAboutJobsTerms of ServicePrivacyStatusSecurity • SOC 2Contact Sales
Chromatic
© Chroma Software Inc. Made by the maintainers of Storybook.