axe-playwright 1.1.11 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![NPM release](https://img.shields.io/npm/v/axe-playwright.svg 'NPM release')](https://www.npmjs.com/package/axe-playwright)
7
7
  [![NPM Downloads](https://img.shields.io/npm/dt/axe-playwright.svg?style=flat-square)](https://www.npmjs.com/package/axe-playwright)
8
8
 
9
- [Axe](https://www.deque.com/axe/) is an accessibility testing engine for websites and other HTML-based user interfaces. This package provides simple axe analyser commands which you can incorporate in your [Playwright](https://www.npmjs.com/package/playwright) tests.The idea is highly inspired by [Andy Van Slaars](https://github.com/avanslaars) cypress-axe project.
9
+ [Axe](https://www.deque.com/axe/) is an accessibility testing engine for websites and other HTML-based user interfaces. This package provides simple axe analyser commands which you can incorporate in your [Playwright](https://www.npmjs.com/package/playwright) tests.
10
10
 
11
11
  ## Install and configure
12
12
 
@@ -99,7 +99,7 @@ Defines the scope of the analysis - the part of the DOM that you would like to a
99
99
 
100
100
  Set of options passed into rules or checks, temporarily modifying them. This contrasts with axe.configure, which is more permanent.
101
101
 
102
- The keys consist of [those accepted by `axe.run`'s options argument](https://www.deque.com/axe/documentation/api-documentation/#parameters-axerun) as well as custom `includedImpacts`, `detailedReport`, and `detailedReportOptions` keys.
102
+ The keys consist of [those accepted by `axe.run`'s options argument](https://www.deque.com/axe/documentation/api-documentation/#parameters-axerun) as well as custom `includedImpacts`, `detailedReport`, `verbose`, and `detailedReportOptions` keys.
103
103
 
104
104
  The `includedImpacts` key is an array of strings that map to `impact` levels in violations. Specifying this array will only include violations where the impact matches one of the included values. Possible impact values are "minor", "moderate", "serious", or "critical".
105
105
 
@@ -116,9 +116,11 @@ The `detailedReport` key is a boolean whether to print the more detailed report
116
116
  }
117
117
  ```
118
118
 
119
+ The `verbose` key is a boolean to whether to print the message `No accessibility violations detected!` when there aren't accessibility violations present in the test. For the `DefaultTerminalReporter` this is true and for the `v2 Reporter` this is false.
120
+
119
121
  ##### reporter (optional)
120
122
 
121
- A class instance that implements the `Reporter` interface. Custom reporter instances can be supplied to override default reporting behaviour dictated by `DefaultTerminalReporter`.
123
+ A class instance that implements the `Reporter` interface or values `default` and `v2`. Custom reporter instances can be supplied to override default reporting behaviour dictated by `DefaultTerminalReporter` set by the value `default`. `v2` is the new TerminalReporter inspired by the reports from [jest-axe](https://github.com/nickcolley/jest-axe).
122
124
 
123
125
  ##### skipFailures (optional, defaults to false)
124
126
 
@@ -213,11 +215,9 @@ describe('Playwright web page accessibility test', () => {
213
215
 
214
216
  it('gets and reports a11y for the specific element', async () => {
215
217
  const violations = await getViolations(page, 'input[name="password"]', {
216
- axeOptions: {
217
- runOnly: {
218
- type: 'tag',
219
- values: ['wcag2a'],
220
- },
218
+ runOnly: {
219
+ type: 'tag',
220
+ values: ['wcag2a'],
221
221
  },
222
222
  })
223
223
 
@@ -0,0 +1,54 @@
1
+ import { Page } from 'playwright';
2
+ import { AxeResults, ElementContext, Result, RunOptions } from 'axe-core';
3
+ import DefaultTerminalReporter from './reporter/defaultTerminalReporter';
4
+ import Reporter, { ConfigOptions, Options } from './types';
5
+ declare global {
6
+ interface Window {
7
+ axe: any;
8
+ }
9
+ }
10
+ declare module 'axe-core' {
11
+ interface Node {
12
+ }
13
+ }
14
+ /**
15
+ * Injects axe executable commands in the active window
16
+ * @param page
17
+ */
18
+ export declare const injectAxe: (page: Page) => Promise<void>;
19
+ /**
20
+ * Configures axe runtime options
21
+ * @param page
22
+ * @param configurationOptions
23
+ */
24
+ export declare const configureAxe: (page: Page, configurationOptions?: ConfigOptions) => Promise<void>;
25
+ /**
26
+ * Runs axe-core tools on the relevant page and returns all results
27
+ * @param page
28
+ * @param context
29
+ * @param options
30
+ */
31
+ export declare const getAxeResults: (page: Page, context?: ElementContext, options?: RunOptions) => Promise<AxeResults>;
32
+ /**
33
+ * Runs axe-core tools on the relevant page and returns all accessibility violations detected on the page
34
+ * @param page
35
+ * @param context
36
+ * @param options
37
+ */
38
+ export declare const getViolations: (page: Page, context?: ElementContext, options?: RunOptions) => Promise<Result[]>;
39
+ /**
40
+ * Report violations given the reporter.
41
+ * @param violations
42
+ * @param reporter
43
+ */
44
+ export declare const reportViolations: (violations: Result[], reporter: Reporter) => Promise<void>;
45
+ /**
46
+ * Performs Axe validations
47
+ * @param page
48
+ * @param context
49
+ * @param options
50
+ * @param skipFailures
51
+ * @param reporter
52
+ */
53
+ export declare const checkA11y: (page: Page, context?: ElementContext | undefined, options?: Options | undefined, skipFailures?: boolean, reporter?: Reporter | 'default' | 'v2') => Promise<void>;
54
+ export { DefaultTerminalReporter };
package/dist/index.js CHANGED
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -31,10 +35,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
31
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
32
36
  };
33
37
  Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.checkA11y = exports.reportViolations = exports.getViolations = exports.getAxeResults = exports.configureAxe = exports.injectAxe = void 0;
38
+ exports.DefaultTerminalReporter = exports.checkA11y = exports.reportViolations = exports.getViolations = exports.getAxeResults = exports.configureAxe = exports.injectAxe = void 0;
35
39
  const fs = __importStar(require("fs"));
36
40
  const utils_1 = require("./utils");
37
41
  const defaultTerminalReporter_1 = __importDefault(require("./reporter/defaultTerminalReporter"));
42
+ exports.DefaultTerminalReporter = defaultTerminalReporter_1.default;
43
+ const terminalReporterV2_1 = __importDefault(require("./reporter/terminalReporterV2"));
38
44
  /**
39
45
  * Injects axe executable commands in the active window
40
46
  * @param page
@@ -73,7 +79,7 @@ exports.getAxeResults = getAxeResults;
73
79
  * @param options
74
80
  */
75
81
  const getViolations = (page, context, options) => __awaiter(void 0, void 0, void 0, function* () {
76
- const result = yield exports.getAxeResults(page, context, options);
82
+ const result = yield (0, exports.getAxeResults)(page, context, options);
77
83
  return result.violations;
78
84
  });
79
85
  exports.getViolations = getViolations;
@@ -94,15 +100,22 @@ exports.reportViolations = reportViolations;
94
100
  * @param skipFailures
95
101
  * @param reporter
96
102
  */
97
- const checkA11y = (page, context, options, skipFailures, reporter) => __awaiter(void 0, void 0, void 0, function* () {
98
- var _a;
99
- if (context === void 0) { context = undefined; }
100
- if (options === void 0) { options = undefined; }
101
- if (skipFailures === void 0) { skipFailures = false; }
102
- if (reporter === void 0) { reporter = new defaultTerminalReporter_1.default(options === null || options === void 0 ? void 0 : options.detailedReport, (_a = options === null || options === void 0 ? void 0 : options.detailedReportOptions) === null || _a === void 0 ? void 0 : _a.html); }
103
- const violations = yield exports.getViolations(page, context, options === null || options === void 0 ? void 0 : options.axeOptions);
104
- const impactedViolations = utils_1.getImpactedViolations(violations, options === null || options === void 0 ? void 0 : options.includedImpacts);
105
- yield exports.reportViolations(impactedViolations, reporter);
106
- utils_1.testResultDependsOnViolations(impactedViolations, skipFailures);
103
+ const checkA11y = (page, context = undefined, options = undefined, skipFailures = false, reporter = 'default') => __awaiter(void 0, void 0, void 0, function* () {
104
+ var _a, _b, _c;
105
+ const violations = yield (0, exports.getViolations)(page, context, options === null || options === void 0 ? void 0 : options.axeOptions);
106
+ const impactedViolations = (0, utils_1.getImpactedViolations)(violations, options === null || options === void 0 ? void 0 : options.includedImpacts);
107
+ let reporterWithOptions;
108
+ if (reporter === 'default') {
109
+ reporterWithOptions = new defaultTerminalReporter_1.default(options === null || options === void 0 ? void 0 : options.detailedReport, (_a = options === null || options === void 0 ? void 0 : options.detailedReportOptions) === null || _a === void 0 ? void 0 : _a.html, (_b = options === null || options === void 0 ? void 0 : options.verbose) !== null && _b !== void 0 ? _b : true);
110
+ }
111
+ else if (reporter === 'v2') {
112
+ reporterWithOptions = new terminalReporterV2_1.default((_c = options === null || options === void 0 ? void 0 : options.verbose) !== null && _c !== void 0 ? _c : false);
113
+ }
114
+ else {
115
+ reporterWithOptions = reporter;
116
+ }
117
+ yield (0, exports.reportViolations)(impactedViolations, reporterWithOptions);
118
+ if (reporter !== 'v2')
119
+ (0, utils_1.testResultDependsOnViolations)(impactedViolations, skipFailures);
107
120
  });
108
121
  exports.checkA11y = checkA11y;
@@ -0,0 +1,9 @@
1
+ import Reporter from '../types';
2
+ import { Result } from 'axe-core';
3
+ export default class DefaultTerminalReporter implements Reporter {
4
+ protected detailedReport: boolean | undefined;
5
+ protected includeHtml: boolean | undefined;
6
+ protected verbose: boolean | undefined;
7
+ constructor(detailedReport: boolean | undefined, includeHtml: boolean | undefined, verbose: boolean | undefined);
8
+ report(violations: Result[]): Promise<void>;
9
+ }
@@ -11,9 +11,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const utils_1 = require("../utils");
13
13
  class DefaultTerminalReporter {
14
- constructor(detailedReport, includeHtml) {
14
+ constructor(detailedReport, includeHtml, verbose) {
15
15
  this.detailedReport = detailedReport;
16
16
  this.includeHtml = includeHtml;
17
+ this.verbose = verbose;
17
18
  }
18
19
  report(violations) {
19
20
  return __awaiter(this, void 0, void 0, function* () {
@@ -29,7 +30,7 @@ class DefaultTerminalReporter {
29
30
  // summary
30
31
  console.table(violationData);
31
32
  if (this.detailedReport) {
32
- const nodeViolations = utils_1.describeViolations(violations).map(({ target, html, violations }) => {
33
+ const nodeViolations = (0, utils_1.describeViolations)(violations).map(({ target, html, violations }) => {
33
34
  if (!this.includeHtml) {
34
35
  return {
35
36
  target,
@@ -43,7 +44,7 @@ class DefaultTerminalReporter {
43
44
  }
44
45
  }
45
46
  else {
46
- console.log(`No accessibility violations detected!`);
47
+ this.verbose && console.log(`No accessibility violations detected!`);
47
48
  }
48
49
  });
49
50
  }
@@ -0,0 +1,7 @@
1
+ import Reporter from '../types';
2
+ import { Result } from 'axe-core';
3
+ export default class TerminalReporterV2 implements Reporter {
4
+ protected verbose: boolean | undefined;
5
+ constructor(verbose: boolean | undefined);
6
+ report(violations: Result[]): Promise<void>;
7
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const assert_1 = __importDefault(require("assert"));
16
+ const picocolors_1 = __importDefault(require("picocolors"));
17
+ class TerminalReporterV2 {
18
+ constructor(verbose) {
19
+ this.verbose = verbose;
20
+ }
21
+ report(violations) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const lineBreak = '\n\n';
24
+ const message = violations.length === 0
25
+ ? 'No accessibility violations detected!'
26
+ : `Found ${violations.length} accessibility violations: \n`;
27
+ const horizontalLine = picocolors_1.default.bold('-'.repeat(message.length));
28
+ const reporter = (violations) => {
29
+ if (violations.length === 0) {
30
+ return [];
31
+ }
32
+ return violations
33
+ .map((violation) => {
34
+ const errorBody = violation.nodes
35
+ .map((node) => {
36
+ const selector = node.target.join(', ');
37
+ const expectedText = `Expected the HTML found at $('${selector}') to have no violations:` +
38
+ '\n';
39
+ return (picocolors_1.default.bold(expectedText) +
40
+ picocolors_1.default.gray(node.html) +
41
+ lineBreak +
42
+ `Received:\n` +
43
+ picocolors_1.default.red(`${violation.help} (${violation.id})`) +
44
+ lineBreak +
45
+ picocolors_1.default.bold(picocolors_1.default.yellow(node.failureSummary)) +
46
+ lineBreak +
47
+ (violation.helpUrl
48
+ ? `You can find more information on this issue here: \n${picocolors_1.default.bold(picocolors_1.default.blue(violation.helpUrl))}`
49
+ : '') +
50
+ '\n' +
51
+ horizontalLine);
52
+ })
53
+ .join(lineBreak);
54
+ return errorBody;
55
+ })
56
+ .join(lineBreak);
57
+ };
58
+ const formatedViolations = reporter(violations);
59
+ const pass = formatedViolations.length === 0;
60
+ if (pass) {
61
+ this.verbose && console.log(message);
62
+ }
63
+ else {
64
+ assert_1.default.fail(message + horizontalLine + '\n' + formatedViolations);
65
+ }
66
+ });
67
+ }
68
+ }
69
+ exports.default = TerminalReporterV2;
@@ -0,0 +1,45 @@
1
+ import { Result, Check, ImpactValue, Locale, Rule, RunOptions } from 'axe-core';
2
+ export interface NodeViolation {
3
+ target: string;
4
+ html: string;
5
+ violations: string;
6
+ }
7
+ export interface Aggregate {
8
+ [key: string]: {
9
+ target: string;
10
+ html: string;
11
+ violations: number[];
12
+ };
13
+ }
14
+ export default interface Reporter {
15
+ report(violations: Result[]): Promise<void>;
16
+ }
17
+ export interface axeOptionsConfig {
18
+ axeOptions?: RunOptions;
19
+ }
20
+ export interface ConfigOptions {
21
+ branding?: {
22
+ brand?: string;
23
+ application?: string;
24
+ };
25
+ reporter?: 'v1' | 'v2' | 'no-passes';
26
+ checks?: Check[];
27
+ rules?: Rule[];
28
+ locale?: Locale;
29
+ axeVersion?: string;
30
+ }
31
+ /**
32
+ * Implement this interface to be able to specific custom reporting behaviour for checkA11y method.
33
+ * @see checkA11y
34
+ */
35
+ export default interface Reporter {
36
+ report(violations: Result[]): Promise<void>;
37
+ }
38
+ export type Options = {
39
+ includedImpacts?: ImpactValue[];
40
+ detailedReport?: boolean;
41
+ detailedReportOptions?: {
42
+ html?: boolean;
43
+ };
44
+ verbose?: boolean;
45
+ } & axeOptionsConfig;
@@ -0,0 +1,5 @@
1
+ import { NodeViolation } from './types';
2
+ import { ImpactValue, Result } from 'axe-core';
3
+ export declare const getImpactedViolations: (violations: Result[], includedImpacts?: ImpactValue[]) => Result[];
4
+ export declare const testResultDependsOnViolations: (violations: Result[], skipFailures: boolean) => void;
5
+ export declare const describeViolations: (violations: Result[]) => NodeViolation[];
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "axe-playwright",
3
- "version": "1.1.11",
3
+ "version": "1.1.12",
4
4
  "description": "Custom Playwright commands to inject axe-core and test for a11y",
5
5
  "main": "dist/index.js",
6
- "types": "index.d.ts",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist/**/*",
9
+ "README.md"
10
+ ],
7
11
  "keywords": [
8
12
  "a11y",
9
13
  "accessibility",
@@ -20,24 +24,24 @@
20
24
  "release": "npm cache clean --force && npm version patch && npm publish --force"
21
25
  },
22
26
  "peerDependencies": {
23
- "playwright-core": ">1.0.0"
27
+ "playwright": ">1.0.0"
24
28
  },
25
29
  "author": "Abhinaba Ghosh",
26
30
  "license": "MIT",
27
31
  "devDependencies": {
28
- "@types/is-ci": "^3.0.0",
29
- "@types/jest": "^27.0.3",
30
- "@types/node": "^17.0.4",
31
- "jest": "^26.6.3",
32
- "jest-each": "^27.0.2",
33
- "jest-playwright-preset": "^1.3.1",
34
- "playwright": "^1.1.1",
35
- "prettier": "^2.0.5",
36
- "ts-jest": "^26.5.0",
37
- "typescript": "^4.1.3"
32
+ "@types/jest": "^28.1.1",
33
+ "@types/node": "^18.11.9",
34
+ "jest": "^28.1.3",
35
+ "jest-each": "^28.1.3",
36
+ "jest-playwright-preset": "^2.0.0",
37
+ "playwright": "^1.27.1",
38
+ "prettier": "^2.7.1",
39
+ "ts-jest": "^28.0.8",
40
+ "typescript": "^4.8.4"
38
41
  },
39
42
  "dependencies": {
40
- "axe-core": "^4.0.1"
43
+ "picocolors": "^1.0.0",
44
+ "axe-core": "^4.5.1"
41
45
  },
42
46
  "repository": {
43
47
  "type": "git",
@@ -1,19 +0,0 @@
1
- version: 2
2
- jobs:
3
- build:
4
- docker:
5
- - image: qawolf/playwright-ci:v1.0.0
6
- steps:
7
- - checkout
8
-
9
- - run:
10
- command: npm install
11
-
12
- - run:
13
- command: |
14
- # # Start local server
15
- # npm run start &
16
- # npx wait-on http://localhost:3000
17
- # replace below with command you want to run, example for running a script below
18
- # node myScript.js
19
- npm test
@@ -1,12 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: npm
4
- directory: "/"
5
- schedule:
6
- interval: daily
7
- time: "23:30"
8
- open-pull-requests-limit: 10
9
- ignore:
10
- - dependency-name: "@types/node"
11
- versions:
12
- - 15.0.0
package/index.d.ts DELETED
@@ -1,93 +0,0 @@
1
- import { AxeResults, Check, ElementContext, ImpactValue, Locale, Result, Rule, RunOptions } from 'axe-core'
2
- import { Page } from 'playwright'
3
-
4
- export interface axeOptionsConfig {
5
- axeOptions: RunOptions
6
- }
7
-
8
- export interface ConfigOptions {
9
- branding?: {
10
- brand?: string
11
- application?: string
12
- }
13
- reporter?: 'v1' | 'v2' | 'no-passes'
14
- checks?: Check[]
15
- rules?: Rule[]
16
- locale?: Locale
17
- axeVersion?: string
18
- }
19
-
20
- /**
21
- * Implement this interface to be able to specific custom reporting behaviour for checkA11y method.
22
- * @see checkA11y
23
- */
24
- export default interface Reporter {
25
- report(violations: Result[]): Promise<void>
26
- }
27
-
28
- /**
29
- * Default implementation of a reporter which prints a summary to the console.
30
- */
31
- export class DefaultTerminalReporter implements Reporter {
32
- constructor(detailedReport: boolean | undefined, includeHtml: boolean | undefined)
33
- report(violations: Result[]): Promise<void>
34
- }
35
-
36
- export type Options = {
37
- includedImpacts?: ImpactValue[]
38
- detailedReport?: boolean
39
- detailedReportOptions?: { html?: boolean }
40
- } & axeOptionsConfig
41
-
42
- declare module 'axe-core' {
43
- interface Node {}
44
- }
45
-
46
- /**
47
- * Injects axe into browser-context
48
- */
49
- export function injectAxe(page: Page): Promise<void>
50
-
51
- /**
52
- * Performs accessibility checks in the web page
53
- * @param page
54
- * @param context
55
- * @param options
56
- * @param skipFailures
57
- */
58
- export function checkA11y(
59
- page: Page,
60
- context?: ElementContext,
61
- options?: Options,
62
- skipFailures?: boolean,
63
- ): Promise<void>
64
-
65
- /**
66
- * configure different axe configurations
67
- * @param page
68
- * @param options
69
- */
70
- export function configureAxe(page: Page, options?: ConfigOptions): Promise<void>
71
-
72
- /**
73
- * Runs axe-core tools on the relevant page and returns all results
74
- * @param page
75
- * @param context
76
- * @param options
77
- */
78
- export function getAxeResults(page: Page, context?: ElementContext, options?: RunOptions): Promise<AxeResults>
79
-
80
- /**
81
- * Runs axe-core tools on the relevant page and returns all accessibility violations detected on the page
82
- * @param page
83
- * @param context
84
- * @param options
85
- */
86
- export function getViolations(page: Page, context?: ElementContext, options?: RunOptions): Promise<Result[]>
87
-
88
- /**
89
- * Report violations given the reporter.
90
- * @param violations
91
- * @param reporter
92
- */
93
- export function reportViolations(violations: Result[], reporter: Reporter): Promise<void>
package/jest.config.js DELETED
@@ -1,10 +0,0 @@
1
- module.exports = {
2
- preset: 'jest-playwright-preset',
3
- testEnvironment: 'node',
4
- testMatch: ['**/tests/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[tj]s?(x)'],
5
- testPathIgnorePatterns: ['/node_modules/'],
6
- testTimeout: 30000,
7
- transform: {
8
- '^.+\\.tsx?$': 'ts-jest',
9
- },
10
- }
package/src/index.ts DELETED
@@ -1,115 +0,0 @@
1
- import { Page } from 'playwright'
2
- import * as fs from 'fs'
3
- import { AxeResults, ElementContext, Result, RunOptions, Spec } from 'axe-core'
4
- import { ConfigOptions, Options } from '../index'
5
- import { getImpactedViolations, testResultDependsOnViolations } from './utils'
6
- import DefaultTerminalReporter from './reporter/defaultTerminalReporter'
7
- import Reporter from './types'
8
-
9
- declare global {
10
- interface Window {
11
- axe: any
12
- }
13
- }
14
-
15
- /**
16
- * Injects axe executable commands in the active window
17
- * @param page
18
- */
19
- export const injectAxe = async (page: Page): Promise<void> => {
20
- const axe: string = fs.readFileSync(
21
- require.resolve('axe-core/axe.min.js'),
22
- 'utf8',
23
- )
24
- await page.evaluate((axe: string) => window.eval(axe), axe)
25
- }
26
-
27
- /**
28
- * Configures axe runtime options
29
- * @param page
30
- * @param configurationOptions
31
- */
32
- export const configureAxe = async (
33
- page: Page,
34
- configurationOptions: ConfigOptions = {},
35
- ): Promise<void> => {
36
- await page.evaluate(
37
- (configOptions: Spec) => window.axe.configure(configOptions),
38
- configurationOptions as Spec,
39
- )
40
- }
41
-
42
- /**
43
- * Runs axe-core tools on the relevant page and returns all results
44
- * @param page
45
- * @param context
46
- * @param options
47
- */
48
- export const getAxeResults = async (
49
- page: Page,
50
- context?: ElementContext,
51
- options?: RunOptions,
52
- ): Promise<AxeResults> => {
53
- const result = await page.evaluate(
54
- ([context, options]) => {
55
- return window.axe.run(context || window.document, options)
56
- },
57
- [context, options],
58
- )
59
-
60
- return result
61
- }
62
-
63
- /**
64
- * Runs axe-core tools on the relevant page and returns all accessibility violations detected on the page
65
- * @param page
66
- * @param context
67
- * @param options
68
- */
69
- export const getViolations = async (
70
- page: Page,
71
- context?: ElementContext,
72
- options?: RunOptions,
73
- ): Promise<Result[]> => {
74
- const result = await getAxeResults(page, context, options)
75
- return result.violations
76
- }
77
-
78
- /**
79
- * Report violations given the reporter.
80
- * @param violations
81
- * @param reporter
82
- */
83
- export const reportViolations = async (violations: Result[], reporter: Reporter): Promise<void> => {
84
- await reporter.report(violations)
85
- }
86
-
87
- /**
88
- * Performs Axe validations
89
- * @param page
90
- * @param context
91
- * @param options
92
- * @param skipFailures
93
- * @param reporter
94
- */
95
- export const checkA11y = async (
96
- page: Page,
97
- context: ElementContext | undefined = undefined,
98
- options: Options | undefined = undefined,
99
- skipFailures: boolean = false,
100
- reporter: Reporter = new DefaultTerminalReporter(options?.detailedReport, options?.detailedReportOptions?.html),
101
- ): Promise<void> => {
102
- const violations = await getViolations(page, context, options?.axeOptions)
103
-
104
- const impactedViolations = getImpactedViolations(
105
- violations,
106
- options?.includedImpacts,
107
- )
108
-
109
- await reportViolations(
110
- impactedViolations,
111
- reporter,
112
- )
113
-
114
- testResultDependsOnViolations(impactedViolations, skipFailures)
115
- }
@@ -1,43 +0,0 @@
1
- import Reporter from '../types'
2
- import { Result } from 'axe-core'
3
- import { describeViolations } from '../utils'
4
-
5
- export default class DefaultTerminalReporter implements Reporter {
6
- constructor(
7
- protected detailedReport: boolean | undefined,
8
- protected includeHtml: boolean | undefined,
9
- ) {}
10
-
11
- async report(violations: Result[]): Promise<void> {
12
- const violationData = violations.map(({ id, impact, description, nodes }) => {
13
- return {
14
- id,
15
- impact,
16
- description,
17
- nodes: nodes.length,
18
- }
19
- })
20
-
21
- if (violationData.length > 0) {
22
- // summary
23
- console.table(violationData)
24
- if (this.detailedReport) {
25
- const nodeViolations = describeViolations(violations).map(
26
- ({ target, html, violations }) => {
27
- if (!this.includeHtml) {
28
- return {
29
- target,
30
- violations,
31
- }
32
- }
33
- return { target, html, violations }
34
- },
35
- )
36
- // per node
37
- console.table(nodeViolations)
38
- }
39
- } else {
40
- console.log(`No accessibility violations detected!`)
41
- }
42
- }
43
- }
package/src/types.ts DELETED
@@ -1,19 +0,0 @@
1
- import { Result } from 'axe-core'
2
-
3
- export interface NodeViolation {
4
- target: string
5
- html: string
6
- violations: string
7
- }
8
-
9
- export interface Aggregate {
10
- [key: string]: {
11
- target: string
12
- html: string
13
- violations: number[]
14
- }
15
- }
16
-
17
- export default interface Reporter {
18
- report(violations: Result[]): Promise<void>
19
- }
package/src/utils.ts DELETED
@@ -1,61 +0,0 @@
1
- import { Aggregate, NodeViolation } from './types'
2
- import { ImpactValue, Result } from 'axe-core'
3
- import assert from 'assert'
4
-
5
- export const getImpactedViolations = (
6
- violations: Result[],
7
- includedImpacts: ImpactValue[] = [],
8
- ): Result[] => {
9
- return Array.isArray(includedImpacts) && includedImpacts.length
10
- ? violations.filter(
11
- (v: Result) => v.impact && includedImpacts.includes(v.impact),
12
- )
13
- : violations
14
- }
15
-
16
- export const testResultDependsOnViolations = (
17
- violations: Result[],
18
- skipFailures: boolean,
19
- ) => {
20
- if (!skipFailures) {
21
- assert.strictEqual(
22
- violations.length,
23
- 0,
24
- `${violations.length} accessibility violation${
25
- violations.length === 1 ? '' : 's'
26
- } ${violations.length === 1 ? 'was' : 'were'} detected`,
27
- )
28
- } else {
29
- if (violations.length) {
30
- console.warn({
31
- name: 'a11y violation summary',
32
- message: `${violations.length} accessibility violation${
33
- violations.length === 1 ? '' : 's'
34
- } ${violations.length === 1 ? 'was' : 'were'} detected`,
35
- })
36
- }
37
- }
38
- }
39
-
40
- export const describeViolations = (violations: Result[]): NodeViolation[] => {
41
- const aggregate: Aggregate = {}
42
-
43
- violations.map(({ nodes }, index) => {
44
- nodes.forEach(({ target, html }) => {
45
- const key = JSON.stringify(target) + html
46
-
47
- if (aggregate[key]) {
48
- aggregate[key].violations.push(index)
49
- } else {
50
- aggregate[key] = {
51
- target: JSON.stringify(target),
52
- html,
53
- violations: [index],
54
- }
55
- }
56
- })
57
- })
58
- return Object.values(aggregate).map(({ target, html, violations }) => {
59
- return { target, html, violations: JSON.stringify(violations) }
60
- })
61
- }
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es6",
4
- "module": "commonjs",
5
- "strict": true,
6
- "declaration": false,
7
- "rootDir": "src",
8
- "moduleResolution": "node",
9
- "typeRoots": ["node_modules/@types"],
10
- "esModuleInterop": true,
11
- "outDir": "dist",
12
- "noImplicitAny": false,
13
- "types": ["node", "jest"]
14
- },
15
- "exclude": ["node_modules"],
16
- "include": ["src/"]
17
- }