axe-playwright 1.2.3 → 2.0.1

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.
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. [Axe](https://www.deque.com/axe/) seamlessly functions across all Playwright browsers: Chromium, Firefox, and WebKit.
10
10
 
11
11
  ## Install and configure
12
12
 
@@ -118,16 +118,16 @@ The `detailedReport` key is a boolean whether to print the more detailed report
118
118
 
119
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
120
 
121
+ ##### skipFailures (optional, defaults to false)
122
+
123
+ Disables assertions based on violations and only logs violations to the console output. If you set `skipFailures` as `true`, although accessibility check is not passed, your test will not fail. It will simply print the violations in the console, but will not make the test fail.
124
+
121
125
  ##### reporter (optional)
122
126
 
123
127
  A class instance that implements the `Reporter` interface or values `default`, `v2` and `html`. 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). `html` reporter will generate external HTML file.
124
128
 
125
129
  Note! `html` reporter will disable printed to logs violations.
126
130
 
127
- ##### skipFailures (optional, defaults to false)
128
-
129
- Disables assertions based on violations and only logs violations to the console output. If you set `skipFailures` as `true`, although accessibility check is not passed, your test will not fail. It will simply print the violations in the console, but will not make the test fail.
130
-
131
131
  ##### options (dedicated for axe-html-reporter)
132
132
 
133
133
  Options dedicated for HTML reporter.
@@ -305,7 +305,8 @@ await checkA11y(
305
305
  },
306
306
  },
307
307
  },
308
- true, 'default',
308
+ true,
309
+ 'html',
309
310
  {
310
311
  outputDirPath: 'results',
311
312
  outputDir: 'accessibility',
@@ -313,8 +314,29 @@ await checkA11y(
313
314
  }
314
315
  )
315
316
  ```
317
+ #### JUnit Report
316
318
 
317
-
319
+ ```
320
+ await checkA11y(
321
+ page,
322
+ 'form',
323
+ {
324
+ axeOptions: {
325
+ runOnly: {
326
+ type: 'tag',
327
+ values: ['wcag2a'],
328
+ },
329
+ },
330
+ },
331
+ true,
332
+ 'junit',
333
+ {
334
+ outputDirPath: 'results',
335
+ outputDir: 'accessibility',
336
+ reportFileName: 'accessibility-audit.xml',
337
+ },
338
+ )
339
+ ```
318
340
  ## Before you Go
319
341
 
320
342
  If it works for you , leave a [Star](https://github.com/abhinaba-ghosh/axe-playwright)! :star:
package/dist/index.d.ts CHANGED
@@ -52,5 +52,5 @@ export declare const reportViolations: (violations: Result[], reporter: Reporter
52
52
  * @param reporter
53
53
  * @param options
54
54
  */
55
- export declare const checkA11y: (page: Page, context?: ElementContext | undefined, axeOptions?: AxeOptions | undefined, skipFailures?: boolean, reporter?: Reporter | 'default' | 'html' | 'v2', options?: Options | undefined) => Promise<void>;
55
+ export declare const checkA11y: (page: Page, context?: ElementContext | undefined, axeOptions?: AxeOptions | undefined, skipFailures?: boolean, reporter?: Reporter | 'default' | 'html' | 'junit' | 'v2', options?: Options | undefined) => Promise<void>;
56
56
  export { DefaultTerminalReporter };
package/dist/index.js CHANGED
@@ -42,6 +42,8 @@ const defaultTerminalReporter_1 = __importDefault(require("./reporter/defaultTer
42
42
  exports.DefaultTerminalReporter = defaultTerminalReporter_1.default;
43
43
  const terminalReporterV2_1 = __importDefault(require("./reporter/terminalReporterV2"));
44
44
  const axe_html_reporter_1 = require("axe-html-reporter");
45
+ const junitReporter_1 = __importDefault(require("./reporter/junitReporter"));
46
+ const path = __importStar(require("path"));
45
47
  /**
46
48
  * Injects axe executable commands in the active window
47
49
  * @param page
@@ -115,17 +117,26 @@ const checkA11y = (page, context = undefined, axeOptions = undefined, skipFailur
115
117
  }
116
118
  else if (reporter === 'html') {
117
119
  if (violations.length > 0) {
118
- yield (0, axe_html_reporter_1.createHtmlReport)({ results: { violations }, options });
120
+ yield (0, axe_html_reporter_1.createHtmlReport)({
121
+ results: { violations },
122
+ options,
123
+ });
119
124
  }
120
125
  else
121
- console.log("There were no violations to save in report");
126
+ console.log('There were no violations to save in report');
127
+ }
128
+ else if (reporter === 'junit') {
129
+ // Get the system root directory
130
+ // Construct the file path
131
+ const outputFilePath = path.join(process.cwd(), options === null || options === void 0 ? void 0 : options.outputDirPath, options === null || options === void 0 ? void 0 : options.outputDir, options === null || options === void 0 ? void 0 : options.reportFileName);
132
+ reporterWithOptions = new junitReporter_1.default(axeOptions === null || axeOptions === void 0 ? void 0 : axeOptions.detailedReport, page, outputFilePath);
122
133
  }
123
134
  else {
124
135
  reporterWithOptions = reporter;
125
136
  }
126
137
  if (reporter !== 'html')
127
138
  yield (0, exports.reportViolations)(impactedViolations, reporterWithOptions);
128
- if (reporter === 'v2' || reporter !== 'html')
139
+ if (reporter === 'v2' || (reporter !== 'html' && reporter !== 'junit'))
129
140
  (0, utils_1.testResultDependsOnViolations)(impactedViolations, skipFailures);
130
141
  });
131
142
  exports.checkA11y = checkA11y;
@@ -0,0 +1,10 @@
1
+ import Reporter from '../types';
2
+ import { Result } from 'axe-core';
3
+ import { Page } from 'playwright';
4
+ export default class JUnitReporter implements Reporter {
5
+ protected verbose: boolean | undefined;
6
+ protected page: Page | undefined;
7
+ protected outputFilename: string | undefined;
8
+ constructor(verbose: boolean | undefined, page: Page | undefined, outputFilename: string | undefined);
9
+ report(violations: Result[]): Promise<void>;
10
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = 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);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ const junit_report_builder_1 = __importDefault(require("junit-report-builder"));
39
+ const assert_1 = __importDefault(require("assert"));
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ class JUnitReporter {
43
+ constructor(verbose, page, outputFilename) {
44
+ this.verbose = verbose;
45
+ this.page = page;
46
+ this.outputFilename = outputFilename;
47
+ }
48
+ report(violations) {
49
+ var _a;
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ let lineBreak = '\n';
52
+ let pageUrl = ((_a = this.page) === null || _a === void 0 ? void 0 : _a.url()) || 'Page';
53
+ let suite = junit_report_builder_1.default.testSuite().name(pageUrl);
54
+ const message = violations.length === 0
55
+ ? 'No accessibility violations detected!'
56
+ : `Found ${violations.length} accessibility violations`;
57
+ violations.map((violation) => {
58
+ const errorBody = violation.nodes
59
+ .map((node) => {
60
+ const selector = node.target.join(', ');
61
+ const expectedText = `Expected the HTML found at $('${selector}') to have no violations:` +
62
+ '\n';
63
+ return (expectedText +
64
+ node.html +
65
+ lineBreak +
66
+ `Received:\n` +
67
+ `${violation.help} (${violation.id})` +
68
+ lineBreak +
69
+ node.failureSummary +
70
+ lineBreak +
71
+ (violation.helpUrl
72
+ ? `You can find more information on this issue here: \n${violation.helpUrl}`
73
+ : '') +
74
+ '\n');
75
+ })
76
+ .join(lineBreak);
77
+ suite
78
+ .testCase()
79
+ .className(violation.id)
80
+ .name(violation.description)
81
+ .failure(errorBody);
82
+ });
83
+ const pass = violations.length === 0;
84
+ if (pass) {
85
+ junit_report_builder_1.default.testCase().name('Accesibility testing - A11Y');
86
+ this.verbose && console.log(`No accessibility violations detected!`);
87
+ }
88
+ let location = this.outputFilename || 'a11y-tests.xml';
89
+ const dir = path.dirname(location);
90
+ if (!fs.existsSync(dir)) {
91
+ fs.mkdirSync(dir, { recursive: true });
92
+ }
93
+ // Check if the file exists, if not create it
94
+ if (!fs.existsSync(location)) {
95
+ fs.writeFileSync(location, ''); // Create an empty file
96
+ }
97
+ junit_report_builder_1.default.writeTo(location);
98
+ if (!pass) {
99
+ assert_1.default.fail(message);
100
+ }
101
+ });
102
+ }
103
+ }
104
+ exports.default = JUnitReporter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axe-playwright",
3
- "version": "1.2.3",
3
+ "version": "2.0.1",
4
4
  "description": "Custom Playwright commands to inject axe-core and test for a11y",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,9 +40,11 @@
40
40
  "typescript": "^4.8.4"
41
41
  },
42
42
  "dependencies": {
43
- "picocolors": "^1.0.0",
43
+ "@types/junit-report-builder": "^3.0.0",
44
44
  "axe-core": "^4.5.1",
45
- "axe-html-reporter": "2.2.3"
45
+ "axe-html-reporter": "2.2.3",
46
+ "junit-report-builder": "^3.0.1",
47
+ "picocolors": "^1.0.0"
46
48
  },
47
49
  "repository": {
48
50
  "type": "git",