Module for adding visual regression testing to Cypress.
npm install cypress-visual-regression
Configure the visual regression plugin and environment variables in your cypress.config.js file like:
const { defineConfig } = require("cypress")
const { configureVisualRegression } = require('cypress-visual-regression')
module.exports = defineConfig({
e2e: {
env: {
visualRegression: {
type: 'regression'
}
},
screenshotsFolder: './cypress/snapshots/actual',
setupNodeEvents(on, config) {
configureVisualRegression(on)
}
}
})
Pay attention to the type
option. Use 'base' to generate baseline images, and 'regression' to compare current
screenshot to the base screenshot
In your support file cypress/support/e2e.js add the following:
const { addCompareSnapshotCommand } = require('cypress-visual-regression/dist/command')
addCompareSnapshotCommand()
If you're using TypeScript, use files with a .ts
extension, as follows:
cypress.config.ts
import { defineConfig } from 'cypress'
import { configureVisualRegression } from 'cypress-visual-regression'
export default defineConfig({
e2e: {
env: {
visualRegression: {
type: 'regression'
}
},
screenshotsFolder: './cypress/snapshots/actual',
setupNodeEvents(on, config) {
configureVisualRegression(on)
},
},
})
cypress/support/e2e.ts
import { addCompareSnapshotCommand } from 'cypress-visual-regression/dist/command'
addCompareSnapshotCommand()
cypress/tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
"types": [
"cypress",
"cypress-visual-regression"
]
}
}
For more info on how to use TypeScript with Cypress, please refer to this document.
All options can be configured within visualRegression
under env
variable inside cypress.config.js
file, like this:
e2e: {
screenshotsFolder: './cypress/snapshots/actual',
env: {
visualRegression: {
type: 'regression',
baseDirectory: 'cypress/snapshot/base',
diffDirectory: 'cypress/snapshot/diff',
generateDiff: 'always',
failSilently: true
}
}
}
Variable | Default | Description |
---|---|---|
type | / | Either 'regression' or 'base'. Base will override any existing base images with new screenshots. Regression will compare the base to the current screenshot. |
baseDirectory | 'cypress/snapshot/base' | Path to the directory where the base snapshots will be stored. |
diffDirectory | 'cypress/snapshot/diff' | Path to the directory where the generated image differences will be stored. |
generateDiff | 'fail' | Either 'fail', 'never' or 'always'. Determines if and when image differences are generated. |
failSilently | false | Used to decide if any error found in regression should be thrown or returned as part of the result. |
You can also pass default cypress screenshot arguments to addCompareSnapshotCommand()
, like this:
const addCompareSnapshotCommand = require('cypress-visual-regression/dist/command')
addCompareSnapshotCommand({
capture: 'fullPage'
})
cy.compareSnapshot(name)
cy.compareSnapshot(name, errorThreshold)
cy.compareSnapshot(name, options)
Arguments | Default | Description |
---|---|---|
name | / | Represents the name of the base snapshot file that the actual screenshot will be compared with. |
errorThreshold | 0 | Threshold under which any image difference will be considered as failed test. Represented in percentages. |
options | {} | Used to provide additional cypress screenshot options as well as failSilently and errorThreshold values. |
cy.compareSnapshot('homePage') // will compare actual screenshot to current and fail if there's any difference in the images
cy.get('h1').compareSnapshot('homePage', 0.2) // will compare only the image of h1 element and fail only if the percentage of pixels that are different is bigger than 0.2%
cy.compareSnapshot('homePage', {errorThreshold: 1, failSilently: true}).then(comparisonResults => {
console.log(comparisonResults.mismatchedPixels) // will print the number of mismatched pixels
console.log(comparisonResults.percentage) // will print the percentage of mismatched pixels
console.log(comparisonResults.error) // will print the visual regression error message (if any)
})
Looking for more examples? See cypress/e2e/main.cy.ts.
Following function creates a command that allows you to hide elements of the page based on their className:
/**
* To be called after you setup the command, in order to add a
* hook that does stuff before the command is triggered
*/
export function beforeCompareSnapshots(
/** Element you want to ignore */
ignoredElementsQuerySelector: string,
/** Main app element (if you want for the page to be loaded before triggering the command) */
appContentQuerySelector: string = "body"
) {
Cypress.Commands.overwrite("compareSnapshots", (originalFn, ...args) => {
return cy
// wait for content to be ready
.get(appContentQuerySelector)
// hide ignored elements
.then($app => {
return new Cypress.Promise((resolve, reject) => {
setTimeout(() => {
$app.find(ignoredElementsQuerySelector).css("visibility", "hidden");
resolve();
// add a very small delay to wait for the elements to be there, but you should
// make sure your test already handles this
}, 300);
});
})
.then(() => {
return originalFn(...args);
});
});
}
You may then use this function like:
const addCompareSnapshotCommand = require("cypress-visual-regression/dist/command");
const beforeCompareSnapshots = require("./commands/beforeCompareSnapshots");
addCompareSnapshotCommand({
errorThreshold: 0.1
});
// add a before hook to compareSnapshot (this must be called AFTER compareSnapshotCommand() so the command can be overriden)
beforeCompareSnapshots(
".chromatic-ignore,[data-chromatic='ignore']",
"._app-content"
);
In this example, we ignore the elements that are also ignored by 3rd party tool Chromatic.
set visualRegressionLogger
to true
to enable logging.