Cypress JS SDK

The Evinced Cypress JS SDK integrates with new or existing Cypress tests to automatically detect accessibility issues. By adding a few lines of code to your Cypress project, you can begin analyzing all the web pages and DOM changes to provide a dynamic view of how your site can become more accessible. As a result of the test, a rich and comprehensive report is generated to easily track issues to resolution.

Interested in seeing this in action? Contact us to get started!


  • Cypress version 10.0.0 or higher

Get Started


The Cypress SDK package is not publicly available. Contact us to get started!

In your project directory install the Cypress JS SDK using npm.

1npm install @evinced/cypress-sdk

Your First Test

SDK Initialization

To work with Cypress JS SDK you need to have authentication token. Please refer to licensing section for details. In the cypress/support/e2e.js file add the following lines to initialize SDK and provide either offline or online token. Note: for Cypress version <10 the file cypress/support/index.js should be used.

1import Evinced from "@evinced/cypress-sdk";
3// Initialize SDK
6// Set offline credentials method
8 serviceId: '<serviceId>',
9 token: '<token>'
11// OR
12// Set online creaentials method (through Evinced lience server)
14 serviceId: '<serviceId>',
15 secret: '<secret>'

Add Evinced accessibility checks (Single Run Mode)

This is a simple example of how to add an Evinced accessibility scan to a test. Please note the inline comments that give detail on each test step.

1it("Evinced basic example", () => {
2 // Navigate to site
3 cy.visit("");
4 //Scan for a11y issues, get the result and assert on the number of issues found
5 cy.evAnalyze().should((issues) => {
6 expect(issues);
7 });

Add Evinced accessibility checks (Continuous Mode)

This is an example of how to add a continuous Evinced accessibility scan to a test. Using the evStart() and evStop() methods, the Evinced engine will continually scan in the background capturing all DOM changes and page navigations as the test is executed. This will capture all accessibility issues as clicking on drop-downs or similar interactions reveals more of the page. The advantage of continuous mode is that no interaction with the actual test code is needed.

1context('Evinced Demo Site tests', () => {
3 it('Search Test', () => {
4 cy.visit('');
6 // Start the Evinced engine
7 cy.evStart();
9 const BASE_FORM_SELECTOR = '#gatsby-focus-wrapper > main > div.wrapper-banner > div.filter-container';
10 const SELECT_HOME_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > div.dropdown.line`;
11 const SELECT_WHERE_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > div.dropdown.line`;
12 const TINY_HOME_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > ul > li:nth-child(2)`;
13 const EAST_COST_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > ul > li:nth-child(3)`;
14 cy.get(SELECT_HOME_DROPDOWN).click();
15 cy.get(TINY_HOME_OPTION).click();
16 cy.get(SELECT_WHERE_DROPDOWN).click();
17 cy.get(EAST_COST_OPTION).click();
19 // Conclude the scan, print issues to cy.log with logIssues and print the report JSON object to browser's console
20 cy.evStop({logIssues: true}).should((issues) => {
21 console.log(JSON.stringify(issues, null, 2));
22 });
23 });



Initializes the Evinced object within the project.


1import Evinced from "@evinced/cypress-sdk";

Note: this call is intended to be done only once in support file. Second call of this method will lead to the error.

Please refer to configuration to see examples of using init with options.

Return value


Implementation details

  • Listens to Cypress events
    • window:before:load - Injects Evinced to the page, continues recording if needed
    • window:before:unload - Stores the state of the current page
    • test:before:run - Initializes test scope state
  • Registers ev commands
    • evAnalyze()
    • evStart()
    • evStop()
    • evSaveFile()
  • Registers Chai assertions
    • evValid()


Scans the current page and returns a list of accessibility issues.

Note: This method is not supported if evStart() is already running.

Please refer to configuration to see examples of using init with options.


1cy.evAnalyze({ rootSelector: "#some .selector" }).should((issues) => {
2 expect(issues).to.have.length(6);

Return value


A Report object is returned containing accessibility issues. This is the recommended method for static page analysis. For more information regarding reports as well as the Report object itself, please refer to our detailed Web Reports page.


Continually watches for DOM mutations and page navigation and records all accessibility issues until the evStop() method is called. This method is recommended for dynamic page flows.


2cy.evStart({ rootSelector: "#some .selector" });
4cy.evStop().should((issues) => {
5 expect(issues).to.have.length(6);

Return value



Stops the process of issue gathering started by evStart() command.


3cy.get('#some .selector').click();
5cy.get('#another .selector').click();
6cy.evStop({logIssues: true}).should((issues) => {
7 expect(issues).to.have.length(10);

Return value


Returns an object containing recorded accessibility issues from the point in time at which the evStart() method was instantiated. For more information regarding reports as well as the returned object itself, please refer to detailed Web Reports page.

Default options

2 logIssues: false // Will log every accessibility issue to Cypress console when true

evSaveFile(issues, format, destination)

Saves list of the issues in a file, with the specified format and location. For example, format could be ‘json’ or 'html. Please find detailed information on Web Reports page.


1const filePath = "./reports/results.json";
3cy.evAnalyze().then((issues) => {
4 cy.evSaveFile(issues, "json", filePath);
5 cy.readFile(filePath).should("exist");

Return value



Throws a chai exception if any issues exist that don't match the provided filters.


1cy.evAnalyze().should("be.evValid", {
2 ignoreSeverities: ["CRITICAL"],
3 ignoreTypes: ["NOT_FOCUSABLE"],

Default options

2 ignoreSeverities: [],
3 ignoreTypes: []

Aggregated Report

The aggregated report feature allows you to have a general aggregated report for the whole run (not only for one test or suite). This report will contain all the issues found by the tests where evStart() and evStop() commands were called. It is still possible to use the evSaveFile() command in any place of your code along with this Aggregated Report feature.


Important! The feature is not supported by the Cypress frameworks versions <10.

For using the aggregated report feature you should add the special entry evReporterOptions to your cypress.config.js file:

1const os = require('os');
3module.exports = {
4 env: {
5 // To disable the feature just comment out the whole evReporterOptions entry.
6 evincedConfig: {
7 reporterOptions: {
8 reportFormat: 'html', // Sets a desired format for the report. Available options are: html, sarif, and json.
9 filePath: './evincedReports/aggregatedReport.html', // Specifies a path to the final aggregated report file.
10 tmpDir: os.tmpdir(), // Specifies the temporary directory to store temporary report files.
11 reportTimeStamp: new Date().toISOString() // Provides a unique timestamp for the report to distinguish to which test run the temporary files belong to. Please do not change this value unless you are sure what you would like to achieve.
12 }
13 }
14 }


To work with Cypress JS SDK you need to have Authentication token. There are to methods to provide the token: offline mode and online mode. The difference is if you use online mode the request to obtain the token will be sent to Evinced Licencing Server. You need to provide Service ID and Secret API key in such a case. They are available via the Evinced Product Hub.

Offline mode assumes that you already have token and can provide it directly. If an offline token is required please reach out to your account team or

We encourage to use environment variables to store credentials and read them in code

1# Offline mode
2export CYPRESS_AUTH_SERVICE_ID=<serviceId>
3export CYPRESS_AUTH_TOKEN=<token>
5# Online mode
6export CYPRESS_AUTH_SERVICE_ID=<serviceId>
7export CYPRESS_AUTH_SECRET=<secret>


1// Set offline credentials method
3 serviceId: Cypress.env('CYPRESS_AUTH_SERVICE_ID'),
4 token: Cypress.env('CYPRESS_AUTH_TOKEN'),
7// OR
9// Set online credentials method (through Evinced lience server)
11 serviceId: Cypress.env('CYPRESS_AUTH_SERVICE_ID'),
12 secret: Cypress.env('CYPRESS_AUTH_SECRET'),


The same configuration object can be used in Evinced.init, evStart() and evAnalyze() methods but with a bit different consequences. By providing some options in Evinced.init method you define a global configuration for all calls of evStart() or evAnalyze() methods. Please note that global configuration is not intended to be altered from tests due to it will affect all the rest tests as well as tests running in parallel threads. To alter configuration in specific tests you can provide config on the method's level, for instance with evStart() it defines local configuration for this particular session until evStop() is called. If provided in both levels, the command's level config will override the global one.

Engines configuration

Evinced uses two separate engines when scanning for accessibility issues, one is the aXe engine and the other is the Evinced engine. By default, Evinced disables the aXe Needs Review and Best Practices issues based on customer request and due to the fact they are mostly false positives. Please note this setting when comparing issue counts directly. See an example of how to enable Needs Review and Best practices issues in our toggles section.

Configuration object type

The type of options object is:

1type SkipValidation = {
2 selector: string,
3 urlRegex: string,
4 validationTypes: string[]
7type IssueContentPerType = {
8 [key: string]: {
9 knowledgeBaseLink: string
10 }
13type EvOptions = {
14 logIssues?: boolean;
15 rootSelector?: string;
16 axeConfig?: any;
17 debug?: boolean;
18 strict?: boolean;
19 logging?: any;
20 toggles?: {
21 [key: string]: boolean;
22 },
23 skipValidations?: SkipValidation[],
24 issuesContentPerType?: IssueContentPerType[]
2### Log Issues
3Controls whether to print detected issues with `cy.log` command or not.
5`false` by default.
7Applicable in `Evinced.init`, `evStart()`, `evStop()` and `evAnalyze()`
9#### Example
11Evinced.init({ logIssues: true });

Root Selector

Instructs engine to return issues which belong to or which are nested to element with the specified selector. By default the issues for all elements from document root will be returned.

null by default.


1cy.evAnalyze({ rootSelector: "#some .selector" }).should((issues) => {
2 expect(issues).to.have.length(6);

AXE Configuration

Evinced leverages Axe open-source accessibility toolkit as part of its own accessibility detection engine. The Evinced engine is able to pinpoint far more issues than Axe alone.

For the full Axe config options, see Axe Core API.


1const axeConfig = {
2 rules: {
3 "link-name": { enabled: false },
4 },
7// Global config
8Evinced.init({ axeConfig });
10// Command config
11cy.evAnalyze({ axeConfig });
12cy.evStart({ axeConfig });

Errors Strict Mode

When set to true it switches SDK in mode when Evinced SDK errors are thrown as runtime errors and stops current test execution. Otherwise errors are printed into console except critical ones.

false by default


1Evinced.init({ strict: true });

Engine Logging

Switches logging on for engine. Log messages from the engine will be printed to console.

Levels are: debug, info, warn, error

null by default.

error is a default level on engine side.

1 cy.evStart({
2 logging: {
3 LOGGING_LEVEL: 'debug',
5 }
6 });

Reports Screenshots

The Screenshots feature allows to include screenshots to the Evinced reports. When the feature is enabled, Evinced will take screenshots of the page, highlight an element with a specific accessibility issue, and include them to the report.


false by default.

Note: The Screenshots feature may affect the test run performance.

Enabling the Screenshots feature

For enabling the Screenshots feature you should set the enableScreenshots parameter to true. It can be done in two ways:

1// Can be passed via a global config during initialization.
3 enableScreenshots: true
6// OR
8// Can be passed via a command config during the command execution.
10 enableScreenshots: true
13 enableScreenshots: true


Toggles are feature flags which controls SDK and Engine behavior. With toggles we introduce experimental features or manage the way how accessibility issues are gathered. The list of toggles is not specified so we suggest not to rely on specific toggle name or value and use them in invetigation puprposes only.

Example enabling aXe Best Practices and Needs Review Issues

2 toggles: { USE_AXE_NEEDS_REVIEW: true, USE_AXE_BEST_PRACTICES: true },

Skip Validations

Skips specific validations for the given URL pattern and the selector.

SkipValidation[] by default.


1 const skipValidationsParametersForEvStart = [
2 {
3 selector: 'span.slds-checkbox--faux',
4 urlRegex: 'www\.example\.org',
5 validationTypes: [
9 ]
10 },
11 {
12 selector: ' > figure',
13 urlRegex: 'www\.example\.org',
14 validationTypes: [
17 ]
18 }
19 ];
20 cy.evStart({
21 skipValidations: skipValidationsParametersForEvStart,
22 });

How to identify ID for the specific issue type is described in tutorial section.

Knowledge Base Link overrides

This custom parameter helps to customize knowledge base links in the reports. Those links are displayed in the reports as follows:


The knowledge base link can be overridden for every issue type ID.


2 issuesContentPerType: {
4 knowledgeBaseLink: "",
5 },
6 },

Where WRONG_SEMANTIC_ROLE is ID of the type of the specific issue. In this example, the corresponding issue type for this ID is Interactable Role. How to identify ID for the specific issue type is described in tutorial section. After passing the type ID and a custom knowledge base link we are set to see it in the reports.

Shadow DOM support


The feature is not yet implemented in this SDK. If you'd like to increase the priority of it, please contact our support

When set to true, the accessibility tests run analysis on iframes that exist inside the page. Default is false.

The feature is not yet implemented in this SDK. If you'd like to increase the priority of it, please contact our support

Global Switch

Global Switch allows to disable or enable Evinced functionality. It could be needed, for example, while working on functional tests in your local environment or for running some CI jobs that are not intended to gather information regarding accessibility issues.

When switched off

  • evStart() and evSaveFile() will be bypassed.
  • evStop() and evAnalyze() will return an empty report.
  • evValid() will never fail.

true by default.

Important! Global Switch environment variable overrides the global configuration option.

Switch on/off Evinced functionality in config

1// Add the following code to cypress.config.js (version >=v10) or cypress.json (version <v10)
2env: {
3 evincedConfig: {
4 switchOn: false
5 }

Switching off Evinced functionality with environment variable

1export CYPRESS_EV_SWITCH_ON="false"


You can find fully functional example projects on our GitHub

Tutorial 1

Generating a comprehensive accessibility report for your application

In this tutorial, we will enhance our existing Cypress UI test with the Evinced Cypress SDK in order to check our application for accessibility issues. In order to get started you will need the following:

  1. All of the prerequisites for the Evinced Cypress SDK should be met
  2. Evinced Cypress SDK should be added to your project

Preface - existing UI test overview

Let’s consider the following basic UI test as our starting point.

1context("Evinced Demo Site tests", () => {
2 it("Search Test", () => {
3 cy.visit("");
5 "#gatsby-focus-wrapper > main > div.wrapper-banner > div.filter-container";
6 const SELECT_HOME_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > div.dropdown.line`;
7 const SELECT_WHERE_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > div.dropdown.line`;
8 const TINY_HOME_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > ul > li:nth-child(2)`;
9 const EAST_COST_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > ul > li:nth-child(3)`;
10 cy.get(SELECT_HOME_DROPDOWN).click();
11 cy.get(TINY_HOME_OPTION).click();
12 cy.get(SELECT_WHERE_DROPDOWN).click();
13 cy.get(EAST_COST_OPTION).click();
14 });

We wrote this test for a demo travel site called TRVL that has a few known accessibility issues.

The purpose of this test is to check the functionality of the main application screen and ensure a user can successfully select their desired trip. For now, this test is only concerned with the functional testing of the app. However, with the help of the Evinced Cypress SDK, we can also check it for accessibility issues along the way. Let’s go through this process with the following step-by-step instructions.

Step #1 - Initialize the Evinced Cypress SDK

In your cypress/support/e2e.js file add the following lines to add the Evinced engine to your project. See details about Evinced.init in API section.

1import Evinced from "@evinced/cypress-sdk";

Step #2 - Start the Evinced engine

Now that we have everything we need to scan for accessibility issues, let’s start the Evinced engine. Since we are going to use it scan throughout our test, the best place for its initialization will be our before method.

1context("Evinced Demo Site tests", () => {
2 before(() => {
3 // Start the Evinced engine
4 cy.evStart();
5 });
7 it("Search Test", () => {
8 cy.visit("");
10 "#gatsby-focus-wrapper > main > div.wrapper-banner > div.filter-container";
11 const SELECT_HOME_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > div.dropdown.line`;
12 const SELECT_WHERE_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > div.dropdown.line`;
13 const TINY_HOME_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > ul > li:nth-child(2)`;
14 const EAST_COST_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > ul > li:nth-child(3)`;
15 cy.get(SELECT_HOME_DROPDOWN).click();
16 cy.get(TINY_HOME_OPTION).click();
17 cy.get(SELECT_WHERE_DROPDOWN).click();
18 cy.get(EAST_COST_OPTION).click();
19 });

Step #3 - Stop the Evinced engine and create reports

As our test was executed we collected a lot of accessibility information. We can now perform accessibility assertions at the end of our test suite. Referring back again to our UI test the best place for this assertion will be the method that gets invoked last - after. To stop the Evinced engine and generate the actual object representation of your accessibility report simply call the evStop() method. We can then output the report files in JSON format.

1context("Evinced Demo Site tests", () => {
2 before(() => {
3 // Start the Evinced engine
4 cy.evStart();
5 });
7 after(() => {
8 // Conclude the scan, print issues to cy.log with logIssues and print the report JSON object to browser's console
9 cy.evStop({ logIssues: true }).should((report) => {
10 console.log(JSON.stringify(report, null, 2));
11 });
12 });
14 it("Search Test", () => {
15 cy.visit("");
17 "#gatsby-focus-wrapper > main > div.wrapper-banner > div.filter-container";
18 const SELECT_HOME_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > div.dropdown.line`;
19 const SELECT_WHERE_DROPDOWN = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > div.dropdown.line`;
20 const TINY_HOME_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(1) > div > ul > li:nth-child(2)`;
21 const EAST_COST_OPTION = `${BASE_FORM_SELECTOR} > div:nth-child(2) > div > ul > li:nth-child(3)`;
22 cy.get(SELECT_HOME_DROPDOWN).click();
23 cy.get(TINY_HOME_OPTION).click();
24 cy.get(SELECT_WHERE_DROPDOWN).click();
25 cy.get(EAST_COST_OPTION).click();
26 });

For the sake of simplicity of this tutorial let’s simply assume that our application is accessible as long as it has no accessibility issues found. Thus, if we have at least one accessibility issue detected - we want our tests to be failed. Let’s add the corresponding assertion to our after method. For more information regarding reports as well as the Report object itself, please see our detailed Web Reports page.

1after(() => {
2 // Scan for a11y issues, create the JSON report, and assert on the number of critical issues found
3 cy.evStop().should((issues) => {
4 expect(issues);
5 });

You are now set to run the test and ensure the accessibility of your application! So, go ahead and run it via your IDE or any other tooling you use for JavaScript development.

Tutorial 2

Obtaining issues' type IDs for customizing knowledge base links in the reports

The Cypress SDK allows to customize issues' knowledge base links in the reports. To do that, we have to pass a type ID of an issue and a link for substitution to the init() method. More information about the feature you can find in the Knowledge Base Links overrides. Below you will find the instruction of how to obtain a type ID of an issue.

Step #1 - Generate a JSON-report

For generating a JSON-report we use the evSaveFile() command.

In case of using evStart() command in your tests modify your evStop() command in the following way:

1cy.evStop().then((issues) => {
2 cy.evSaveFile(issues, "json", "./path/to/save/file");

In case of using evAnalyze() command in your tests add to the command call the following:

1cy.evAnalyze().then((issues) => {
2 cy.evSaveFile(issues, "json", "./path/to/save/file");

This step is required to be done just once. After obtaining the JSON-report the code mentioned above may be removed if it is not used in the test flow.

Step #2 - Find a required issue in the report

Now that we have everything we need to get an issue type ID. Let's assume we have generated the report as follows:

Click to see code
2 {
3 "id": "88b997b6-769d-4703-b5e2-62cff68f507f",
4 "index": "I1",
5 "hidden": false,
6 "validation": {
7 "id": "80119244-1ea7-4aaa-bb4b-554ad59678c6"
8 },
9 "skipIssue": false,
10 "elements": [
11 {
12 "id": "42e76fb7-b38b-4979-a18e-0ff0c0d7bbd7",
13 "index": "S1",
14 "selector": ".block-dropdown:nth-child(1) > .dropholder > .dropdown.line",
15 "pageUrl": "",
16 "boundingBox": {
17 "x": 221.21875,
18 "y": 576.1875,
19 "height": 23.9375,
20 "width": 250,
21 "top": 576.1875,
22 "bottom": 600.125,
23 "left": 221.21875,
24 "right": 471.21875
25 },
26 "domSnippet": "<div class=\"dropdown line\"><p>Select</p></div>",
27 "componentId": "ce13d0bb"
28 }
29 ],
30 "type": {
32 "newId": "86649b9b-96e1-4abb-903a-5ec30f0af526",
33 "name": "Interactable Role"
34 },
35 "firstSeenTime": 1676232893048,
36 "lastSeenTime": 1676232893048,
37 "additionalInformation": {},
38 "summary": "Screen readers do not interpret the element as interactable.",
39 "description": "**Cause:** Missing or incorrect semantics prevent screen readers from interpreting an element as interactable. \n**Effect:** Screen reader either does not navigate to the element or navigates to it but does not correctly convey its function to the user. \n**Suggested Solutions:**\n* Change the element's tag to correctly reflect its type, ie: <*button*>, <*a*> or <*input*><*/input*> \n* Add attributes (ARIA) to indicate the element's type and/or potential functionalities. \n",
40 "severity": {
41 "id": "CRITICAL",
42 "name": "Critical",
43 "newId": "3c68eb41-9227-481d-8eec-9dc8956b19c4"
44 },
45 "originalSeverity": {
46 "id": "CRITICAL",
47 "name": "Critical",
48 "newId": "3c68eb41-9227-481d-8eec-9dc8956b19c4"
49 },
50 "tags": [
51 {
52 "id": "WCAG-1.3.1",
53 "description": "1.3.1 Info and Relationships (Level A)",
54 "link": ""
55 },
56 {
57 "id": "WCAG-A"
58 },
59 {
60 "id": "WCAG2.0"
61 }
62 ],
63 "knowledgeBaseLink": "",
64 "signature": "2ffa5563",
65 "canonicalSignature": "2ffa5563"
66 }

There are entry for each particular issue. For each issue we should see a section called type where we see a field id. In the case above it is WRONG_SEMANTIC_ROLE. Also in the section we can see a name of the type - Interactable Role. This is it!

Step #3 - Pass the type ID to init()

In the Knowledge Base Links overrides section you can find a working example of how to pass the parameter to Evinced.init.


Please feel free to reach out to with any questions.


  1. Can I configure which validations to run?

Yes, see the configuration section for details on how to configure Axe validations to your needs.

  1. Can I run tests with Evinced using cloud-based services like Sauce Labs, Perfecto, or BrowserStack?

Yes, we have tested the Evinced SDK on many of these types of cloud-based services and expect no issues.