Selenium JS SDK
The Evinced Selenium JS SDK integrates with new or existing Selenium WebDriver tests to automatically detect accessibility issues. By adding a few lines of code to your Selenium WebDriver 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!
Prerequisites
- Selenium version 4 or higher
- Mocha tests only supported
Get started
Installation
To install Selenium JS SDK you will need either a file provided by Evinced Support or access to a remote repository that provides it. If you have neither, contact us to get started.
Installation with a locally provided file
With a local copy of the Selenium JS SDK gzipped tar package (.tgz extension), install it in your project using NPM or Node package manager of your choice:
1# Using NPM2npm install -D "path to js-selenium-sdk-<version>.tgz file"
Installation from a remote repository
Evinced Customers have the option of accessing Selenium JS SDK from a remote repository — the Evinced Jfrog Artifactory — to keep their SDK version up-to-date and to share the SDK internally at their organization.
When access is enabled, Selenium JS SDK is available at
https://evinced.jfrog.io/artifactory/restricted-npm/%40evinced/js-selenium-sdk.
Installation using NPM:
1npm install @evinced/js-selenium-sdk
AI Skills
The @evinced/js-selenium-sdk package ships with built-in AI agent skills that guide your AI assistant through integrating the Evinced SDK — from initial setup and writing tests to configuring rules and generating reports.
To activate AI Skills, add the following to your project's AGENTS.md file (create it at the root of your project if it does not exist):
1## Context23Before working on any accessibility testing task, always read:45`node_modules/@evinced/js-selenium-sdk/evinced-ai/entry.mdc`67The entry.mdc file contains:8- Integration rules for the Evinced Selenium JS SDK9- Skills for setup, test writing, configuration, reporting, and logging10- Links to detailed documentation for each task type1112## When to use1314When the user asks about accessibility testing, WCAG compliance, ARIA attributes, Evinced SDK usage, or accessibility reports or scans, read the entry point file listed under Context.1516## Capabilities1718- Set up the Evinced SDK in Selenium WebDriver projects19- Write accessibility tests using `evAnalyze`, `evStart`, `evStop`20- Configure accessibility rules and scopes21- Generate HTML, JSON, SARIF, or CSV reports22- Configure the SDK — proxy, screenshots, iframes, and `evConfig.json`23- Enable and tune SDK logging and log levels24- Control SDK toggles — kill switch, analytics opt-out, and mock engine25- Integrate accessibility checks into CI/CD pipelines
Note for monorepos: with pnpm, or yarn/npm workspaces, the package may be hoisted to the workspace root. If the path above does not exist, look for evinced-ai/entry.mdc under the workspace root's node_modules instead.
This works with any AI assistant that reads project context files (Cursor, Claude, Copilot, Windsurf, Gemini, and others).
Try asking your AI assistant:
- "Set up the Evinced SDK in my project"
- "Add accessibility checks to my existing Selenium WebDriver test"
- "Scope the scan to only the navigation bar"
Authentication
To launch Selenium JS SDK, you need to have a Service ID and an API Key.
Where to find your Evinced SDK credentials
These credentials are available via the Evinced Product Hub in the “Automation for Web” or “Automation for Mobile” product areas. Click the “Get SDK” button to see the Service Account ID and API Key at the bottom of the page.
Authenticate for Offline Testing
There are two methods to provide the token: online mode and offline mode. Online mode contacts the Evinced Licensing Server. Offline mode assumes that an Evinced employee has supplied a JSON Web Token (JWT). If an offline token is required, please reach out to your account team or support@evinced.com.
Please set credentials in environment variables and reference the environment variables in code.
1# Online mode2export EVINCED_SERVICE_ID=<serviceId>3export EVINCED_API_KEY=<apiKey>45# Offline mode, when a JWT has been provided by Evinced6export EVINCED_SERVICE_ID=<serviceId>7export EVINCED_AUTH_TOKEN=<token>
Setting credentials, an example:
1// Online credentials2const { setCredentials } = require('@evinced/js-selenium-sdk');34await setCredentials({5 serviceId: process.env.EVINCED_SERVICE_ID,6 secret: process.env.EVINCED_API_KEY7});89// OR1011// If provided a JWT by Evinced12// Offline credentials13const { setOfflineCredentials } = require('@evinced/js-selenium-sdk');1415setOfflineCredentials({16 serviceId: process.env.EVINCED_SERVICE_ID,17 token: process.env.EVINCED_AUTH_TOKEN,18});
Your First Test
SDK Initialization
To use Selenium JS SDK, you first need to authenticate. Please refer to Authentication for details.
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.
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34describe('Demo page', async () => {5 let driver;67 it('Demo page. evAnalyze', async () => {8 const driver = await new Builder()9 .forBrowser('chrome')10 .build();11 const evincedService = new EvincedSDK(driver);12 await driver.get('https://demo.evinced.com/');13 const issues = await evincedService.evAnalyze();14 assert.equal(issues.length, 6);15 await driver.quit();16 });17});
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 navigation 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.
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34describe('Demo page', async () => {5 let driver;67 it('Demo page. evStart/evStop', async () => {8 const driver = await new Builder()9 .forBrowser('chrome')10 .build();11 const evincedService = new EvincedSDK(driver);12 await evincedService.evStart();13 await driver.get('https://demo.evinced.com/');14 const issues = await evincedService.evStop();15 assert.equal(issues.length, 6);16 await driver.quit();17 });18});
Using Evinced with Selenium BiDi. Learn more
For faster execution and analysis, you can configure the Evinced SDK to use Selenium BiDi (Bidirectional Protocol). BiDi enables more efficient communication between the test automation and the browser, resulting in improved performance during accessibility scanning.
To configure the WebDriver with BiDi enabled, use the following code snippet:
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34const driver = await new Builder()5 .forBrowser('chrome')6 .setCapability('webSocketUrl', true)7 .build();89const evincedService = new EvincedSDK(driver);
Advantage of using Selenium BiDi:
- Faster execution and analysis: Reduced communication overhead between the driver and browser enables more efficient accessibility data collection
API
EvincedSDK
Prepares the Evinced object for use in the project.
The specific SDK initialization is not needed. You need just import EvincedSDK in your test files.
1const { EvincedSDK } = require('@evinced/js-selenium-sdk');
Refer to Configuration to see examples of initializing with options.
evAnalyze(options)
Scans the current page and returns a list of accessibility issues. This is the recommended method for static page analysis.
Note: This method is not supported if evStart() is already running.
1const evincedService = new EvincedSDK(driver);2await driver.get('https://demo.evinced.com/');3const issues = await evincedService.evAnalyze();
Returns Promise<Issue[]>.
The returned report object contains a list of accessibility issues.
For more information regarding reports as well as the report object itself, please refer to our detailed Web Reports page.
evStart(options)
Continually watches for DOM mutations and page navigation, recording accessibility issues
until the evStop() method is called. This method is recommended for dynamic page flows.
1const evincedService = new EvincedSDK(driver);2await evincedService.evStart();3await driver.get('https://demo.evinced.com/');4const issues = await evincedService.evStop();
Returns Promise<void>.
evStop(options)
Stops the issue-gathering process started by evStart().
1const evincedService = new EvincedSDK(driver);2await evincedService.evStart();3await driver.get('https://demo.evinced.com/');4const issues = await evincedService.evStop();
Returns Promise<Issue[]>.
The returned report object includes all accessibility issues detected between
the evStart() and evStop() method calls.
For more information regarding reports as well as the report object itself, please refer to our detailed Web Reports page.
evSaveFile(destination, issues, format)
Saves issues in a file with the specified format and location.
Supported formats are json, html, sarif, and csv.
Find detailed information in the Web Reports page.
1const evincedService = new EvincedSDK(driver);2await driver.get('https://demo.evinced.com/');3const issues = await evincedService.evAnalyze();4evincedService.evSaveFile(issues, 'html', 'test-results/evinced-report.html');5evincedService.evSaveFile(issues, 'csv', 'test-results/evinced-report.csv');6evincedService.evSaveFile(issues, 'json', 'test-results/evinced-report.json');7evincedService.evSaveFile(issues, 'sarif', 'test-results/evinced-report.sarif.json');
Returns Promise<void>.
Configuration
The same configuration object can be used when initializing the Evinced object
using evConfig.json and when calling the evStart()
and evAnalyze() methods but with a bit different consequences.
Providing options when initializing defines a global configuration for all calls
of evAnalyze() and evStart(), while providing options to
either of those methods affect only the test in which they are called.
Options provided in either evAnalyze() or evStart() override
those set in Evinced engine initialization.
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 the Toggles section.
Configuration Object
To define global configuration for Selenium JS SDK, place evConfig.yaml, evConfig.yml, or structured evConfig.json at the project root. JSON and YAML formats remain fully supported; only legacy top-level key names are deprecated. Per-command options on EvincedSDK methods use the same nested structure.
1type EvConfig = {2 switchOn?: boolean;3 scan?: {4 rootSelector?: string;5 iframes?: boolean;6 iframeDomains?: string[];7 screenshots?: { enabled?: boolean };8 withPasses?: boolean;9 };10 analysis?: {11 AXE_CONFIG?: Record<string, unknown>;12 TOGGLES?: Record<string, boolean>;13 SKIP_VALIDATIONS?: SkipValidation[];14 ISSUE_CONTENT_PER_TYPE?: Record<string, { knowledgeBaseLink: string }>;15 RECORDING_SERVICE?: Record<string, unknown>;16 [key: string]: unknown;17 };18 platform?: {19 upload?: { enabled?: boolean; autoUpload?: boolean };20 };21 logging?: {22 enabled?: boolean;23 preset?: 'errors' | 'standard' | 'diagnostic';24 level?: 'error' | 'warn' | 'info' | 'debug' | 'trace';25 outputDir?: string;26 channels?: {27 sdk?: boolean;28 engine?: boolean;29 browserConsole?: boolean;30 performance?: boolean;31 scanInsights?: boolean;32 };33 maxEntryLength?: number;34 systemInfo?: boolean;35 };36 network?: {37 idle?: { enabled?: boolean; timeout?: number; maxWait?: number };38 };39 performance?: {40 bundleCache?: boolean;41 };42};
Recommended (evConfig.yaml):
1switchOn: true2scan:3 iframes: true4 screenshots:5 enabled: false6performance:7 bundleCache: false
Recommended (structured evConfig.json):
1{2 "switchOn": true,3 "scan": {4 "iframes": true,5 "screenshots": {6 "enabled": false7 }8 }9}
Deprecated (legacy flat keys in evConfig.json):
1{2 "switchOn": true,3 "includeIframes": true,4 "enableScreenshots": false5}
Root Selector
Sets a CSS selector to limit the Evinced Engine to scan only the selected element and its children. Must be a valid CSS selector. If not set, the Evinced Engine will scan the entire document.
Default: no value
Recommended (evConfig.yaml):
1scan:2 rootSelector: '#main'
Recommended (structured evConfig.json):
1{2 "scan": {3 "rootSelector": "#main"4 }5}
Recommended (per command):
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34const driver = await new Builder().forBrowser('chrome').build();5const evincedService = new EvincedSDK(driver);67await evincedService.evStart({8 scan: { rootSelector: '.some-selector' }9});10await driver.get('https://demo.evinced.com/');11const issues = await evincedService.evStop();
Deprecated (legacy flat rootSelector key in evConfig — JSON, YAML, and YML remain supported):
1{2 "rootSelector": "#main"3}
Deprecated (per command — legacy initOptions):
1await evincedService.evStart({2 initOptions: { rootSelector: '.some-selector' }3});
Axe Configuration
Configures Axe open-source accessibility toolkit, which the Evinced engine includes with its own, more extensive accessibility detection. For full Axe config options, see Axe Core API.
Recommended (per command):
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34const driver = await new Builder().forBrowser('chrome').build();5const evincedService = new EvincedSDK(driver);6await driver.get('https://demo.evinced.com/');7const issues = await evincedService.evAnalyze({8 analysis: {9 AXE_CONFIG: {10 rules: {11 'link-name': { enabled: false }12 }13 }14 }15});
Deprecated (per command — legacy initOptions.axeConfig):
1const issues = await evincedService.evAnalyze({2 initOptions: {3 axeConfig: {4 rules: {5 'link-name': { enabled: false }6 }7 }8 }9});
Engine Logging
Set level of messages the Evinced engine will print to the console.
Valid levels are "debug", "info", "warn" and "error".
Default: "error"
Configure SDK log output with the logging.* section in evConfig.yaml, evConfig.yml, or structured evConfig.json. To include analysis-engine messages, set logging.channels.engine: true or use the diagnostic preset (which includes the engine channel).
Recommended (evConfig.yaml):
1logging:2 enabled: true3 preset: diagnostic
Recommended (enable engine channel only):
1logging:2 enabled: true3 channels:4 engine: true
Reports Screenshots
When true, the Evinced SDK will include screenshots in its reports that
highlight elements with accessibility issues.
Default: false.
Note: Enabling screenshots may affect test run performance.

Recommended (per command):
1const issues = await evincedService.evAnalyze({2 scan: { screenshots: { enabled: true } }3});
Deprecated (per command — legacy initOptions.enableScreenshots):
1const issues = await evincedService.evAnalyze({2 initOptions: { enableScreenshots: true }3});
Toggles
Enables experimental features. Feature names and values may vary from release to release.
Example: Recommended (per command):
1const issues = await evincedService.evAnalyze({2 analysis: {3 TOGGLES: {4 USE_AXE_NEEDS_REVIEW: true,5 USE_AXE_BEST_PRACTICES: true6 }7 }8});
Deprecated (per command — legacy initOptions.toggles):
1const issues = await evincedService.evAnalyze({2 initOptions: {3 toggles: {4 USE_AXE_NEEDS_REVIEW: true,5 USE_AXE_BEST_PRACTICES: true6 }7 }8});
Skip Validations
Sets validation types to be skipped for specified URL pattern and CSS selector. Issue type IDs can be found by inspecting a JSON report as described in Web Reports.
Default: no validations skipped.
Recommended (per command):
1const skipSelector = {2 selector: 'testValue.slds-checkbox',3 urlRegex: '.*',4 validationTypes: ['WRONG_SEMANTIC_ROLE', 'NOT_FOCUSABLE', 'NO_DESCRIPTIVE_TEXT']5};67await evincedService.evStart({8 analysis: { SKIP_VALIDATIONS: [skipSelector] }9});
Deprecated (per command — legacy initOptions.skipValidations):
1await evincedService.evStart({2 initOptions: { skipValidations: [skipSelector] }3});
Recording Service
This setting controls how frequently event-triggered functions are executed, helping to optimize performance and responsiveness. The option does not enable or disable the event-handling service itself but determines how frequently events are processed based on the selected mode.
Available modes:
debounce– Delays execution until a set time has passed since the last event. Useful for actions triggered by continuous input, such as typing in a search box, to avoid excessive function calls.throttle– Ensures execution at fixed intervals, regardless of event frequency. Ideal for scenarios like handling window resize events or scroll tracking, where limiting execution prevents performance degradation.
Default: Functions execute as triggering events occur.
An example of how to modify settings: Recommended (per command):
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34const driver = await new Builder().forBrowser('chrome').build();5const evincedService = new EvincedSDK(driver);67await evincedService.evStart({8 analysis: {9 RECORDING_SERVICE: {10 ENABLE_DEBOUNCE_NEW_SELECTORS: true,11 DEBOUNCE_NEW_SELECTORS_MS: 500,12 DELAY_MODE: 'throttle'13 }14 }15});1617await driver.get('https://demo.evinced.com/');1819await evincedService.evStop();
Deprecated (per command — legacy initOptions.recordingService):
1await evincedService.evStart({2 initOptions: {3 recordingService: {4 ENABLE_DEBOUNCE_NEW_SELECTORS: true,5 DEBOUNCE_NEW_SELECTORS_MS: 500,6 DELAY_MODE: 'throttle'7 }8 }9});
Shadow DOM Support
Shadow DOM is now supported by default. No additional configuration is needed.
If using an earlier release, configure shadow DOM support as follows: Recommended (per command):
1const issues = await evincedService.evAnalyze({2 analysis: { TOGGLES: { SUPPORT_SHADOW_DOM: true } }3});45await evincedService.evStart({6 analysis: { TOGGLES: { SUPPORT_SHADOW_DOM: true } }7});
Deprecated (per command — legacy initOptions.toggles):
1const issues = await evincedService.evAnalyze({2 initOptions: {3 toggles: { SUPPORT_SHADOW_DOM: true }4 }5});67await evincedService.evStart({8 initOptions: {9 toggles: { SUPPORT_SHADOW_DOM: true }10 }11});
Deprecated (global config — legacy flat key in evConfig.json):
1{2 "toggles": {3 "SUPPORT_SHADOW_DOM": true4 }5}
IFrames Support
When true, accessibility analysis includes iframe that exist inside the page.
Default: true.
Recommended (evConfig.yaml):
1scan:2 iframes: false
Recommended (structured evConfig.json):
1{2 "scan": {3 "iframes": false4 }5}
Recommended (per session or analysis):
1await evincedService.evStart({ scan: { iframes: false } });2const issues = await evincedService.evAnalyze({ scan: { iframes: false } });
Deprecated (legacy flat keys in evConfig — JSON, YAML, and YML remain supported):
1{2 "includeIframes": false3}
Deprecated (per session or analysis — legacy initOptions):
1await evincedService.evStart({ initOptions: { includeIframes: false } });2const issues = await evincedService.evAnalyze({ initOptions: { includeIframes: false } });
Important! The current implementation does not support an analysis of Cross Origin iFrames. Only issues from the iFrames with the origin of the parent iFrame will be gathered.
Note: Since iframe analysis is enabled by default, your tests may take longer to run when analyzing pages with multiple or complex iFrames.
Include Hidden IFrames Domain
Configures which hidden iframe domains are included in accessibility analysis. By default, hidden iframes are excluded for performance and security reasons.
This setting allows you to specify a list of domains to analyze even when the iframe is hidden.
Recommended (per analysis):
1const issues = await evincedService.evAnalyze({2 scan: {3 iframes: true,4 iframeDomains: ['example.com', 'test.com']5 }6});
Deprecated (per analysis — legacy initOptions):
1const issues = await evincedService.evAnalyze({2 initOptions: {3 includeIframes: true,4 includeHiddenIframeDomains: ['example.com', 'test.com']5 }6});
Passed Validations
By default, the Evinced SDK only reports accessibility issues that have failed validation. However, you can also configure the SDK to include passed validations in your reports. Passed validations represent accessibility checks that were successfully completed without any issues found.
Why include passed validations?
Including passed validations in your reports provides several benefits:
- Comprehensive Coverage: Get a complete picture of all accessibility checks performed, not just the failures
- Compliance Documentation: Demonstrate which accessibility standards your application successfully meets
- Trend Analysis: Track improvements over time by monitoring both failed and passed validation counts
- Quality Assurance: Verify that accessibility checks are running as expected across your entire application
- Regulatory Reporting: Provide evidence of accessibility testing coverage for compliance audits
Report Structure
When passed validations are enabled, your reports will include both:
failedValidations: Array of accessibility issues that need to be fixedpassedValidations: Array of accessibility checks that passed successfully
Default: false (passed validations are not included)
Enable Passed Validations
To include passed validations in your reports, set the withPasses option to true.
Warning: Enabling passed validations has a performance impact on your testing as the reporting overhead is significantly greater than when reporting just found issues.
Single Page Analysis with Passed Validations
1const { Builder } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34const driver = await new Builder().forBrowser('chrome').build();5const evincedService = new EvincedSDK(driver);67await driver.get('https://demo.evinced.com');89const report = await evincedService.evAnalyze({10 scan: { withPasses: true }11});1213await driver.quit();
Continuous Analysis with Passed Validations
1const { Builder, By } = require('selenium-webdriver');2const { EvincedSDK } = require('@evinced/js-selenium-sdk');34const driver = await new Builder().forBrowser('chrome').build();5const evincedService = new EvincedSDK(driver);67// Start continuous analysis with passed validations8await evincedService.evStart({9 scan: { withPasses: true }10});1112// Navigate and interact with your application13await driver.get('https://demo.evinced.com');14await driver.findElement(By.css('.some-button')).click();1516const report = await evincedService.evStop();1718await driver.quit();
Saving Reports with Passed Validations
1const evincedService = new EvincedSDK(driver);23await evincedService.evStart({ scan: { withPasses: true } });4await driver.get('https://demo.evinced.com');5const report = await evincedService.evStop();67await evincedService.evSaveFile(report, 'json', './reports/complete-report.json');89await evincedService.evSaveFile(report, 'html', './reports/report.html');
Configuration file
Recommended (evConfig.yaml):
1scan:2 withPasses: true
Recommended (structured evConfig.json):
1{2 "scan": {3 "withPasses": true4 }5}
Deprecated (legacy flat keys in evConfig — JSON, YAML, and YML remain supported):
1{2 "includePassedValidations": true3}
Recommended (per command):
1await evincedService.evAnalyze({ scan: { withPasses: true } });2await evincedService.evStart({ scan: { withPasses: true } });
Deprecated (per command — legacy initOptions):
1await evincedService.evAnalyze({ initOptions: { includePassedValidations: true } });2await evincedService.evStart({ initOptions: { includePassedValidations: true } });
Report Structure
Without passed validations (withPasses: false):
1{2 "issues": [3 // Array of failed validation issues only4 ],5 "screenshotsMap": { /* screenshot data */ }6}
With passed validations (withPasses: true):
1{2 "failedValidations": [3 // Array of issues that failed validation4 ],5 "passedValidations": [6 // Array of checks that passed validation7 ],8 "screenshotsMap": { /* screenshot data */ }9}
Network Idle Detection
The networkIdle configuration enables the SDK to wait for all network requests to complete before
running accessibility analysis. This is particularly useful for modern web applications that load
content dynamically after the initial page load.
Why use Network Idle Detection?
When testing modern web applications, accessibility analysis may run before all content has loaded, resulting in:
- Incomplete results: Dynamic content not yet rendered won't be analyzed
- False negatives: Accessibility issues in delayed content won't be detected
- Inconsistent results: Analysis timing may vary between test runs
Network idle detection solves this by ensuring all network activity has settled before analysis begins.
Configuration Options:
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enables or disables network idle detection |
idleTimeout | number | 300 | Time in milliseconds to wait after the last network request completes before considering the network idle |
maxWaitTime | number | 7500 | Maximum time in milliseconds to wait for network idle. If exceeded, analysis proceeds with a warning |
Network idle detection can be configured globally during SDK initialization or per-command for granular control.
Global Configuration
Recommended (evConfig.yaml):
1network:2 idle:3 enabled: true4 timeout: 3005 maxWait: 7500
Recommended (structured evConfig.json):
1{2 "network": {3 "idle": {4 "enabled": true,5 "timeout": 300,6 "maxWait": 75007 }8 }9}
Deprecated (legacy flat networkIdle key in evConfig — JSON, YAML, and YML remain supported):
1{2 "networkIdle": {3 "enabled": true,4 "idleTimeout": 300,5 "maxWaitTime": 75006 }7}
Per-Command Configuration
Recommended:
1await evinced.evStart({2 network: { idle: { enabled: true, maxWait: 10000 } }3});45await evinced.evAnalyze({6 network: { idle: { enabled: true, timeout: 500, maxWait: 5000 } }7});
Deprecated (per command — legacy initOptions.networkIdle):
1await evinced.evStart({2 initOptions: {3 networkIdle: { enabled: true, maxWaitTime: 10000 }4 }5});67await evinced.evAnalyze({8 initOptions: {9 networkIdle: { enabled: true, idleTimeout: 500, maxWaitTime: 5000 }10 }11});
Usage Example
1const { Builder } = require('selenium-webdriver');2const { By } = require('selenium-webdriver');3const { EvincedSDK } = require('@evinced/js-selenium-sdk');45const driver = await new Builder().forBrowser('chrome').build();6const evinced = new EvincedSDK(driver);78await evinced.evStart({9 network: { idle: { enabled: true } }10});11await driver.get('https://example.com/app');12await driver.findElement(By.id('products-nav')).click();13const issues = await evinced.evStop();1415await driver.get('https://example.com/products');16const singlePageIssues = await evinced.evAnalyze({17 network: { idle: { enabled: true } }18});
Configuration Options
network.idle.enabled(boolean, default:false) - Enable/disable network idle detectionnetwork.idle.timeout(number, default:300) - Milliseconds to wait with no active requests before considering network idlenetwork.idle.maxWait(number, default:7500) - Maximum time to wait before proceeding anyway
How It Works
Network idle detection waits for network activity to settle before running accessibility analysis. This ensures analysis runs on a stable page with all dynamic content loaded.
- Static Analysis (
evAnalyze): Waits for network idle before running analysis - Continuous Mode (
evStart/evStop): Waits for network idle only atevStart()(session start), not after navigation or atevStop()
How It Works:
The SDK monitors all network requests and waits for the network to become idle before proceeding with analysis:
- Network is considered "idle" when no requests are active for at least
idleTimeoutmilliseconds - Analysis waits for idle state or
maxWaitTime, whichever comes first - Configuration from
evStart()automatically applies to subsequent page navigations andevStop()
Best Practices:
- Start with defaults: Enable with default settings and adjust only if needed
- Increase timeout for slow APIs: If your backend is slow, increase
maxWaitTime - Use per-command for specific pages: Enable only for pages with dynamic content
Important Notes:
- Disabled by default: The feature is opt-in to maintain backward compatibility
- No overhead when disabled: When not enabled, there is zero performance impact
- Automatic timeout extension: Command timeouts are automatically adjusted based on
maxWaitTime - Warning on timeout: If
maxWaitTimeis exceeded, the SDK logs a warning and proceeds with analysis
Global Switch
When false, disables Evinced functionality. Enabled by default, use this setting to disable
Evinced accessibility analysis when not needed during test development or when running CI jobs
where accessibility testing is not intended.
Default: true.
When switched off:
evStart()andevSaveFile()will be bypassed.evStop()andevAnalyze()will return an empty report.
Switching Evinced Functionality Off in Configuration
Add the following to your evConfig file (evConfig.yaml, evConfig.yml, or structured evConfig.json at the project root). JSON and YAML formats remain fully supported; only legacy top-level key names are deprecated.
Recommended (evConfig.yaml):
1switchOn: false
Recommended (structured evConfig.json):
1{2 "switchOn": false3}
Alternative (per command with the same modern key):
1const issues = await sdk.evAnalyze({ switchOn: false });
Important! Global Switch environment variable overrides the global configuration option.
Switching Evinced Functionality Off in Environment
1export EV_SWITCH_ON=false
Uploading Reports to Evinced Platform
Introduction
Evinced Platform allows you to seamlessly collect, organize, visualize and monitor Evinced accessibility reports in one place. In this section, we will guide you through the key functionalities of the upload methods of the accessibility reports from the Evinced SDK to the Evinced Platform, which was introduced in version to be determined. This upload method is fully compatible with the previous versions of the Evinced SDK API, and is disabled by default.
Enable Upload Report to Platform
To enable the uploading functionality of accessibility reports to the Evinced Platform
you will need to set the enableUploadToPlatform feature flag to true via
the global setUploadToPlatformConfig method:
1import { setUploadToPlatformConfig } from '@evinced/js-selenium-sdk';23setUploadToPlatformConfig({enableUploadToPlatform: true})
You can also use the external config evConfig.json and add the values to be loaded.
Important! The external config has more precedence if both initialization options are used.
1{2 "uploadToPlatformOptions": {3 "enableUploadToPlatform": true,4 "setUploadToPlatformDefault": false5 }6}
Note: Using uploadToPlatform: true in method parameters (e.g., evincedService.evAnalyze({ uploadToPlatform: true })) is not sufficient on its own. You must first enable the feature by setting enableUploadToPlatform: true via setUploadToPlatformConfig() or evConfig.json. The method parameter only controls whether a specific report uploads when the feature is already enabled.
Automatic Report Upload
Once the enableUploadToPlatform method is set to true and setUploadToPlatformDefault is true (which is the default),
all generated reports will be automatically uploaded to the Platform immediately upon calling the evStop() or evAnalyze() command.
How it works:
- When
enableUploadToPlatform: trueandsetUploadToPlatformDefault: true (default), upload happens automatically - No additional code is needed - just call
evAnalyze()orevStop()and the report uploads - Upload occurs synchronously as part of the command execution
If you want to change this behavior and control uploads manually, set the setUploadToPlatformDefault feature flag to false.
1import { setUploadToPlatformConfig } from '@evinced/js-selenium-sdk';23setUploadToPlatformConfig({enableUploadToPlatform: true, setUploadToPlatformDefault: true});
If the setUploadToPlatformDefault is disabled, you can still upload
selected reports to the platform.
For that, use the following parameter in the evStop() command:
1await evincedService.evStop({uploadToPlatform: true});
Or, in the evAnalyze() command:
1await evincedService.evAnalyze({uploadToPlatform: true});
Test Names
To facilitate report management and be able to distinguish between different reports on the Platform, use the setTestInfo method to inform the test name and test class.
It’s recommended to do that in the “beforeEach” hook.
1describe('Upload to platform', () => {2 let driver;3 let evincedService;45 beforeEach(async () => {6 driver = await getDriverOfflineCredentials(); // or your driver setup7 evincedService = new EvincedSDK(driver);89 evincedService.testRunInfo.addLabel({ testName: 'your test name' });10 });11});
Labels and Custom Fields
You can attach labels and custom fields to your report to enhance readability and organization in the platform. Labels help you filter, search, and organize reports on the Evinced Platform.
There are two types of labels:
Built-in Labels: Pre-defined labels that can be set using the addLabel method. Available built-in labels include:
testName- The name of the testtestFile- The file path of the testenvironment- The environment where the test runs (e.g., "Development", "Staging", "Production")flow- The test flow identifiergitBranch- The Git branch namegitUserName- The Git user namegitVersion- The Git commit version
Custom Labels: Flexible key-value pairs that can be set using the customLabel method. You can use any custom key-value pairs, including:
- Single values:
{ productVersion: '1.0.0' } - Multiple values (arrays):
{ browsers: ['Chrome', 'Firefox'] } - Special label
unitId: Use this to tag tests for relevant units within your organization
See the following code examples of how to set up labels:
1describe('Upload to platform', () => {2 let driver;3 let evincedService;45 beforeEach(async () => {6 driver = await getDriverOfflineCredentials(); // or your driver setup7 evincedService = new EvincedSDK(driver);89 // Set built-in labels10 evincedService.testRunInfo.addLabel({11 testName: 'My Test',12 environment: 'Development',13 gitBranch: 'main'14 });1516 // Set custom labels (including unitId for organizational tagging)17 evincedService.testRunInfo.customLabel({18 customParameter: "demo value",19 productVersion: "1.00",20 browsers: ["Chrome 1.00", "Firefox 2.00"],21 SDK: "JS Selenium SDK",22 unitId: 'unit-123' // Tag for organizational unit23 });24 });25});
Use of beforeEach and afterEach Hooks
We recommend using the beforeEach and afterEach hooks to control analysis sessions and upload reports to the platform. This way, each test will be uploaded separately with its own report.
In beforeEach hook use evStart() to start Evinced analysis and set any labels
you want for the report to contain when uploading to the platform.
In the afterEach hook call evStop() to stop analysis and upload reports to the platform.
See this code example:
1describe('Upload hooks example', () => {2 let driver;3 let evincedService;45 beforeEach(async () => {6 driver = await getDriverOfflineCredentials(); // or your driver setup7 evincedService = new EvincedSDK(driver);89 await driver.get('https://demo.evinced.com/');10 evincedService.testRunInfo.addLabel({11 testName: 'testHooks',12 testFile: 'upload-hooks.js',13 environment: 'Development'14 });15 await evincedService.evStart();16 });1718 afterEach(async () => {19 await evincedService.evStop({ uploadToPlatform: true });20 await driver.quit();21 });22});
Putting All of This Together
Here is a complete code snippet of how to perform uploads to the platform on a per-test basis.
1describe('Upload hooks example', () => {2 let driver;3 let evincedService;45 beforeEach(async () => {6 driver = await getDriverOfflineCredentials(); // or your driver setup7 evincedService = new EvincedSDK(driver);89 evincedService.testRunInfo.addLabel({ testName: 'customTestName' });10 evincedService.testRunInfo.customLabel({11 customParameter: "demo value",12 productVersion: "1.00",13 SDK: "JS Selenium SDK",14 });15 await evincedService.evStart();16 });1718 afterEach(async () => {19 await evincedService.evStop({ uploadToPlatform: true });20 await driver.quit();21 });2223 it("Check upload to platform using evStop", async () => {24 await driver.get('https://demo.evinced.com/');25 });26});
Accessing Upload Information
After uploading issues to the platform, you can retrieve the upload test ID and platform URL using these convenience methods.
Methods:
getUploadTestId()
Returns the unique test ID generated for the upload.
1const testId = evincedService.testRunInfo.getUploadTestId();2// Output: Upload Test ID: a58e1808-3b31-4b6b-8a14-3d8e95fe7643
getUploadTestUrl()
Returns the platform URL where the uploaded report can be viewed.
1const platformUrl = evincedService.testRunInfo.getUploadTestUrl();2// Output: Platform URL: https://platform.evinced.com/web-sdk/test/a58e1808-3b31-4b6b-8a14-3d8e95fe7643
Complete Example:
1const issues = await evincedService.evAnalyze({ uploadToPlatform: true });23// Get upload information4const testId = evincedService.testRunInfo.getUploadTestId();5const platformUrl = evincedService.testRunInfo.getUploadTestUrl();
Tutorials
You can find fully functional example projects on our GitHub.
Generating a comprehensive accessibility report for your application
In this tutorial, we will enhance our existing Selenium JS UI test with the Evinced JS Selenium SDK in order to check our application for accessibility issues. In order to get started you will need the following:
- All of the prerequisites for the Evinced JS Selenium SDK should be met
- Evinced JS Selenium SDK should be added to your project
Preface - existing UI test overview
Let’s consider the following basic UI test as our starting point.
1const { Builder } = require("selenium-webdriver");23describe("Evinced Demo site tests", async () => {4 let driver;5 before(async () => {6 let options;7 driver = await new Builder()8 .forBrowser("chrome")9 .setChromeOptions(options)10 .build();1112 await driver.manage().setTimeouts({ implicit: 1000 });13 });1415 after(async () => {16 await driver.quit();17 });1819 it("Demo page. Single page analyze", async () => {20 await driver.get("https://demo.evinced.com/");21 });22});
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 JS Selenium 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 - Importing the Evinced JS Selenium SDK
In your test file add the following lines to add the Evinced engine to your project.
1const { EvincedSDK } = require("@evinced/js-selenium-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 and set credentials. Let's use the offline setting for this example. Since we are going to use it scan throughout our test, the best place for its initialization will be our before method.
1const { Builder } = require("selenium-webdriver");2const { EvincedSDK } = require("@evinced/js-selenium-sdk");34describe("Evinced Demo site tests", async () => {5 let driver;6 let evincedService;7 before(async () => {8 setOfflineCredentials({9 serviceId: process.env.EVINCED_SERVICE_ID,10 token: process.env.EVINCED_AUTH_TOKEN,11 });12 let options;13 driver = await new Builder()14 .forBrowser("chrome")15 .setChromeOptions(options)16 .build();1718 await driver.manage().setTimeouts({ implicit: 1000 });19 evincedService = new EvincedSDK(driver);20 await evincedService.evStart();21 });2223 after(async () => {24 await driver.quit();25 });2627 it("Demo page. Single page analyze", async () => {28 await driver.get("https://demo.evinced.com/");29 });30});
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.
1const { Builder } = require("selenium-webdriver");2const { EvincedSDK } = require("@evinced/js-selenium-sdk");34describe("Evinced Demo site tests", async () => {5 let driver;6 let evincedService;7 before(async () => {8 setOfflineCredentials({9 serviceId: process.env.EVINCED_SERVICE_ID,10 token: process.env.EVINCED_AUTH_TOKEN,11 });12 let options;13 driver = await new Builder()14 .forBrowser("chrome")15 .setChromeOptions(options)16 .build();1718 await driver.manage().setTimeouts({ implicit: 1000 });19 evincedService = new EvincedSDK(driver);20 await evincedService.evStart();21 });2223 after(async () => {24 const issues = await evincedService.evStop();25 await driver.quit();26 });2728 it("Demo page. Single page analyze", async () => {29 await driver.get("https://demo.evinced.com/");30 });31});
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(async () => {2 const issues = await evincedService.evStop();3 assert.equal(issues.length, 0);4 await driver.quit();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.
Fail the test if critical issues are found
Here you can see a way of failing your test if critical accessibility issues are found using the Selenium JS SDK.
Using evAnalyze:
1const issues = await evincedService.evAnalyze();23const criticalIssues = issues.filter((issue) => issue.severity.name === 'Critical');4await assert(criticalIssues.length === 0, 'found critical issues');
Using evStart/evStop:
1await evincedService.evStart();2const issues = await evincedService.evStop();34const criticalIssues = issues.filter((issue) => issue.severity.name === 'Critical');5await assert(criticalIssues.length === 0, 'found critical issues');
The criticalIssues array will contain all the critical issues found during the scan. If the array is not empty, the test will fail on the assertion.
Support
Please feel free to reach out to support@evinced.com with any questions.
FAQ
- Can I configure which validations to run?
Yes, see the Configuration section for details on how to configure Axe validations to your needs.
- 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.