Visual Regression Testing with Cypress and Angular
Visual regression testing is a robust technic that improves our suite of tests, by literarily taking a screenshot of an element, component, or page in a determined state and then use it to compare the latest state of that element.

Let me start with two questions:
- Have you done modifications to a global CSS sheet, and have no idea if a component got affected?
- Have you migrated a library to the latest version and you're wondering if the component is rendering differently than before?
Visual regression testing is a robust technic that improves our suite of tests, by literarily taking a screenshot of an element, component, or page in a determined state and then use it to compare the latest state of that element.
How it works?
Once an element is ready to be tested, we are going to take our golden screenshot and this one will be used in the future to compare the previous and new state and find if something has changed.
Who uses this kind of tests?
It's a common practice in large projects but to give a reference to a giant in the industry, Google uses it in its products. When the Angular team announced their new render engine, Ivy, they mentioned that to test the new engine, they upgraded all their apps to the latest version and ran hundreds of thousands of tests to make sure that the engine was not causing side effects or unexpected renders. They had different flavours of tests, including visual regression tests.

What should I consider?
- In the end, these image comparison tests, so it's expected that they aren't as fast as a unit test.
- Every time you update an element (and there is a screenshot test already in place) and you are sure of the change, you will need to update the golden screenshot
When should I use it?
- If you're creating several tests to make sure that CSS properties are being applied.
- If you're about to do a pretty aggressive update in the app the could affect, for example updating a CSS framework library.
- You want to implement and improve your suite of tests.
Are they the same as snapshots in Jest?
The principle is the same, Jest can take a copy of the code of a component and compare it with the latest every-time the test run. In our case, we're taking screenshots.
How can I implement this in my project?
We are going to use Cypress, which is really modern and cutting edge to that let us run End-to-End test in the front-end.
Note: This is not the only way to do it, most of the testing frameworks have an option or plugin to do it. There are also tools like Applitools that help us to automate this process in a simpler way.
In this example we'll use only open source tools.
Code
- Create an Angular project, and then install Cypress along with a plugin by running:
npm i -D cypress cypress-image-snapshot
- Create to NPM script in the package json:
"cypress": "cypress"
and"cypress:open": "npm run cypress -- open"
- Run
npm run cypress:open
. The first time Cypress runs, it will create a folder structure to place your E2E by default. - Now lets update the following files:
plugins/index.js
const {
addMatchImageSnapshotPlugin,
} = require('cypress-image-snapshot/plugin');
module.exports = (on, config) => {
addMatchImageSnapshotPlugin(on, config);
}
This implements the cypress-image-snapshot
plugging.
support/commands.js
import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command';
if (Cypress.config('isInteractive')) {
Cypress.Commands.add('matchImageSnapshot', () => {
cy.log('Skipping snapshot ?')
})
} else {
addMatchImageSnapshotCommand()
}
The validates that screenshots be created only in headless mode, this way we avoid issues with the size of the screen.
5. My app is showing a fake Charmander in the app component, so I'm going to create a new file in integration
call home.spec.ts
and write a test which will take a screenshot of the main route.

describe('Home screenshot', () => {
it('should take a screenshot of the home page', () => {
cy.visit('/');
cy.matchImageSnapshot('home');
});
});
Now, let's run this command to generate the screenshots:
npm run cypress run

6. To make sure that the test is working, let's update the Charmarder for a real one and run the same command again:

7. ¡BOOM! Failed.

If you want to update the golden screenshot, just add this flag--env updateSnapshots=true
to the previous command and that's it.

Conclusion
The visual regression tests are an extra shield that We can implement in our project and make sure every-time there is a side effect that could affect the visual layer, we can capture it and find out the problem before the app gets into production. Also decreases human error and the manual QA processes.