Visual testing with Cypress
Integrate Chromatic with Cypress to get visual test coverage at every point of your end-to-end test run
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:
- 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
- Import Chromatic in
cypress/support/e2e.js
:
import "@chromatic-com/cypress/support";
- 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);
},
},
});
- Run Cypress with
npx cypress run
while prependingELECTRON_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
- 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.
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.
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:
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:
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.