@sa11y/wdio
Version:
Accessibility testing API for WebdriverIO
125 lines • 5.23 kB
JavaScript
;
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertAccessibleSync = exports.assertAccessible = exports.runAxe = exports.loadAxe = exports.getAxeVersion = void 0;
const axe = __importStar(require("axe-core"));
const preset_rules_1 = require("@sa11y/preset-rules");
const format_1 = require("@sa11y/format");
const common_1 = require("@sa11y/common");
/**
* Merge given options with default options
*/
function setDefaultOptions(opts = {}) {
const defaultOptions = {
driver: browser,
scope: undefined,
rules: preset_rules_1.defaultRuleset,
exceptionList: {},
};
return Object.assign(Object.assign({}, defaultOptions), opts);
}
/**
* Return version of axe injected into browser
*/
function getAxeVersion(driver) {
return driver.execute(() => {
return typeof axe === 'object' ? axe.version : undefined;
});
}
exports.getAxeVersion = getAxeVersion;
/**
* Load axe source into browser if it is not already loaded and return version of axe.
* Since axe min js is large (400+kb), keep polling until given timeout in milliseconds.
*/
async function loadAxe(driver, timeout = 10000, pollTime = 100) {
// TODO (perf): Conditionally injecting axe based on axe version doesn't
// work reliably resulting in axe undefined error sometimes
await driver.execute(axe.source);
await driver.waitUntil(async () => (await getAxeVersion(driver)) === common_1.axeVersion, {
timeout: timeout,
interval: pollTime,
timeoutMsg: `Unable to load axe after ${timeout} ms`,
});
}
exports.loadAxe = loadAxe;
/**
* Load and run axe in given WDIO instance and return the accessibility violations found.
*/
async function runAxe(options = {}) {
const { driver, scope, rules } = setDefaultOptions(options);
const elemSelector = scope ? (await scope).selector : undefined;
await loadAxe(driver);
// run axe inside browser and return violations
return driver.executeAsync(
// TODO (chore): Fix lint error
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// TS2345: Argument of type is not assignable to parameter of type
(elemSelector, rules, done) => {
axe.run((elemSelector || document), rules, (err, results) => {
if (err)
throw err;
done(results.violations);
});
}, elemSelector, rules);
}
exports.runAxe = runAxe;
/**
* Verify that the currently loaded page in the browser is accessible.
* Throw an error with the accessibility issues found if it is not accessible.
* Asynchronous version of {@link assertAccessibleSync}
*/
async function assertAccessible(opts = {}) {
const options = setDefaultOptions(opts);
// TODO (feat): Add as custom commands to both browser for page level and elem
// https://webdriver.io/docs/customcommands.html
const violations = await (0, common_1.getViolations)(() => runAxe(options));
// TODO (refactor): move exception list filtering to getViolations()
// and expose it as an arg to assert and jest api as well ?
const filteredResults = (0, format_1.exceptionListFilter)(violations, options.exceptionList);
format_1.A11yError.checkAndThrow(filteredResults);
}
exports.assertAccessible = assertAccessible;
/**
* Verify that the currently loaded page in the browser is accessible.
* Throw an error with the accessibility issues found if it is not accessible.
* Synchronous version of {@link assertAccessible}
* @deprecated Please update to using async method.
*/
function assertAccessibleSync(opts = {}) {
const options = setDefaultOptions(opts);
// Note: https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-sync#switching-between-sync-and-async
void options.driver.call(async () => {
await assertAccessible(options);
});
}
exports.assertAccessibleSync = assertAccessibleSync;
//# sourceMappingURL=wdio.js.map