testaro 78.0.8 → 78.4.0
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/.gitattributes +94 -0
- package/.github/workflows/ci.yml +58 -0
- package/.github/workflows/publish.yml +49 -0
- package/.github/workflows/typescript.yml +35 -0
- package/AGENTS.md +2 -2
- package/CLAUDE.md +24 -18
- package/CONTAINERS.md +9 -6
- package/CONTRIBUTING.md +29 -3
- package/Dockerfile +1 -1
- package/README.md +73 -19
- package/UPGRADES.md +4 -0
- package/actSpecs-doc.md +13 -1
- package/actSpecs.js +29 -5
- package/call.js +6 -5
- package/docker-compose.yml +8 -2
- package/docs/checkpoint-scanning.md +199 -0
- package/docs/standard-result-outcome.md +165 -0
- package/env.example +44 -10
- package/eslint.config.mjs +101 -0
- package/netWatch.js +372 -222
- package/package.json +46 -31
- package/pour/README.md +47 -0
- package/pour/pour.min.js +8 -0
- package/procs/actDo.js +808 -0
- package/procs/catalog.d.ts +17 -0
- package/procs/catalog.js +312 -221
- package/procs/catalog.ts +398 -0
- package/procs/checkpoint.js +110 -0
- package/procs/config.d.ts +35 -0
- package/procs/config.js +62 -0
- package/procs/dateTime.js +2 -1
- package/procs/doActs.js +442 -849
- package/procs/doTestAct.js +27 -121
- package/procs/flow.js +221 -0
- package/procs/generateRuleRegistry.js +94 -0
- package/procs/getSource.d.ts +26 -0
- package/procs/job.js +115 -1
- package/procs/launch.d.ts +40 -0
- package/procs/launch.js +239 -108
- package/procs/nu.d.ts +48 -0
- package/procs/scope.js +196 -0
- package/procs/shoot.d.ts +33 -0
- package/procs/standard.d.ts +18 -0
- package/procs/standard.js +83 -0
- package/procs/standard.ts +126 -0
- package/procs/testAct.js +145 -0
- package/procs/testaro.d.ts +20 -0
- package/procs/testaro.js +236 -189
- package/procs/testaro.ts +321 -0
- package/procs/userPath.js +126 -0
- package/procs/xPath.d.ts +4 -0
- package/procs/xPath.js +81 -69
- package/procs/xPath.ts +106 -0
- package/procs/xPathScript.d.ts +6 -0
- package/procs/xPathScript.js +70 -0
- package/run.js +3 -2
- package/surea11y/README.md +44 -0
- package/surea11y/surea11y.browser.js +14 -0
- package/testaro/adbID.d.ts +3 -0
- package/testaro/adbID.js +38 -41
- package/testaro/adbID.ts +66 -0
- package/testaro/allCapStyle.d.ts +3 -0
- package/testaro/allCapStyle.js +31 -34
- package/testaro/allCapStyle.ts +55 -0
- package/testaro/allCaps.d.ts +16 -0
- package/testaro/allCaps.js +179 -151
- package/testaro/allCaps.ts +228 -0
- package/testaro/allHidden.d.ts +13 -0
- package/testaro/allHidden.js +29 -30
- package/testaro/allHidden.ts +50 -0
- package/testaro/allSlanted.d.ts +3 -0
- package/testaro/allSlanted.js +30 -33
- package/testaro/allSlanted.ts +54 -0
- package/testaro/altScheme.d.ts +3 -0
- package/testaro/altScheme.js +27 -30
- package/testaro/altScheme.ts +50 -0
- package/testaro/attVal.d.ts +3 -0
- package/testaro/attVal.js +20 -21
- package/testaro/attVal.ts +52 -0
- package/testaro/autocomplete.d.ts +3 -0
- package/testaro/autocomplete.js +59 -75
- package/testaro/autocomplete.ts +101 -0
- package/testaro/bulk.d.ts +13 -0
- package/testaro/bulk.js +32 -33
- package/testaro/bulk.ts +55 -0
- package/testaro/buttonMenu.d.ts +9 -0
- package/testaro/buttonMenu.js +317 -319
- package/testaro/buttonMenu.ts +391 -0
- package/testaro/captionLoc.d.ts +3 -0
- package/testaro/captionLoc.js +17 -20
- package/testaro/captionLoc.ts +40 -0
- package/testaro/datalistRef.d.ts +3 -0
- package/testaro/datalistRef.js +33 -36
- package/testaro/datalistRef.ts +55 -0
- package/testaro/distortion.d.ts +3 -0
- package/testaro/distortion.js +57 -26
- package/testaro/distortion.ts +81 -0
- package/testaro/docType.d.ts +15 -0
- package/testaro/docType.js +25 -25
- package/testaro/docType.ts +45 -0
- package/testaro/dupAtt.d.ts +16 -0
- package/testaro/dupAtt.js +113 -104
- package/testaro/dupAtt.ts +144 -0
- package/testaro/elements.d.ts +6 -0
- package/testaro/elements.js +153 -153
- package/testaro/elements.ts +215 -0
- package/testaro/embAc.d.ts +3 -0
- package/testaro/embAc.js +19 -20
- package/testaro/embAc.ts +40 -0
- package/testaro/focAll.d.ts +13 -0
- package/testaro/focAll.js +185 -191
- package/testaro/focAll.ts +217 -0
- package/testaro/focAndOp.d.ts +3 -0
- package/testaro/focAndOp.js +100 -104
- package/testaro/focAndOp.ts +128 -0
- package/testaro/focInd.d.ts +3 -0
- package/testaro/focInd.js +64 -66
- package/testaro/focInd.ts +96 -0
- package/testaro/focVis.d.ts +3 -0
- package/testaro/focVis.js +28 -30
- package/testaro/focVis.ts +52 -0
- package/testaro/headEl.d.ts +10 -0
- package/testaro/headEl.js +61 -62
- package/testaro/headEl.ts +82 -0
- package/testaro/headingAmb.d.ts +3 -0
- package/testaro/headingAmb.js +54 -63
- package/testaro/headingAmb.ts +72 -0
- package/testaro/hovInd.d.ts +12 -0
- package/testaro/hovInd.js +163 -130
- package/testaro/hovInd.ts +199 -0
- package/testaro/hover.d.ts +3 -0
- package/testaro/hover.js +155 -126
- package/testaro/hover.ts +154 -0
- package/testaro/hr.d.ts +3 -0
- package/testaro/hr.js +14 -17
- package/testaro/hr.ts +36 -0
- package/testaro/imageLink.d.ts +3 -0
- package/testaro/imageLink.js +17 -20
- package/testaro/imageLink.ts +42 -0
- package/testaro/labClash.d.ts +3 -0
- package/testaro/labClash.js +31 -33
- package/testaro/labClash.ts +54 -0
- package/testaro/legendLoc.d.ts +3 -0
- package/testaro/legendLoc.js +17 -20
- package/testaro/legendLoc.ts +42 -0
- package/testaro/lineHeight.d.ts +3 -0
- package/testaro/lineHeight.js +43 -48
- package/testaro/lineHeight.ts +70 -0
- package/testaro/linkAmb.d.ts +7 -0
- package/testaro/linkAmb.js +79 -80
- package/testaro/linkAmb.ts +105 -0
- package/testaro/linkExt.d.ts +3 -0
- package/testaro/linkExt.js +13 -16
- package/testaro/linkExt.ts +35 -0
- package/testaro/linkOldAtt.d.ts +3 -0
- package/testaro/linkOldAtt.js +25 -28
- package/testaro/linkOldAtt.ts +48 -0
- package/testaro/linkTo.d.ts +3 -0
- package/testaro/linkTo.js +22 -22
- package/testaro/linkTo.ts +43 -0
- package/testaro/linkUl.d.ts +3 -0
- package/testaro/linkUl.js +30 -34
- package/testaro/linkUl.ts +54 -0
- package/testaro/miniText.d.ts +3 -0
- package/testaro/miniText.js +41 -44
- package/testaro/miniText.ts +68 -0
- package/testaro/motion.d.ts +10 -0
- package/testaro/motion.js +92 -96
- package/testaro/motion.ts +125 -0
- package/testaro/nonTable.d.ts +3 -0
- package/testaro/nonTable.js +39 -45
- package/testaro/nonTable.ts +66 -0
- package/testaro/optRoleSel.d.ts +3 -0
- package/testaro/optRoleSel.js +16 -19
- package/testaro/optRoleSel.ts +41 -0
- package/testaro/phOnly.d.ts +3 -0
- package/testaro/phOnly.js +18 -21
- package/testaro/phOnly.ts +43 -0
- package/testaro/pseudoP.d.ts +3 -0
- package/testaro/pseudoP.js +36 -38
- package/testaro/pseudoP.ts +59 -0
- package/testaro/radioSet.d.ts +3 -0
- package/testaro/radioSet.js +57 -59
- package/testaro/radioSet.ts +79 -0
- package/testaro/registry.d.ts +63 -0
- package/testaro/registry.js +67 -0
- package/testaro/registry.ts +141 -0
- package/testaro/role.d.ts +3 -0
- package/testaro/role.js +27 -29
- package/testaro/role.ts +53 -0
- package/testaro/secHeading.d.ts +3 -0
- package/testaro/secHeading.js +30 -33
- package/testaro/secHeading.ts +53 -0
- package/testaro/styleDiff.d.ts +25 -0
- package/testaro/styleDiff.js +248 -252
- package/testaro/styleDiff.ts +303 -0
- package/testaro/tabNav.d.ts +33 -0
- package/testaro/tabNav.js +272 -342
- package/testaro/tabNav.ts +454 -0
- package/testaro/targetsNear.d.ts +9 -0
- package/testaro/targetsNear.js +130 -132
- package/testaro/targetsNear.ts +160 -0
- package/testaro/textNodes.d.ts +6 -0
- package/testaro/textNodes.js +139 -135
- package/testaro/textNodes.ts +185 -0
- package/testaro/textSem.d.ts +3 -0
- package/testaro/textSem.js +25 -28
- package/testaro/textSem.ts +47 -0
- package/testaro/title.d.ts +9 -0
- package/testaro/title.js +16 -13
- package/testaro/title.ts +31 -0
- package/testaro/titledEl.d.ts +3 -0
- package/testaro/titledEl.js +15 -18
- package/testaro/titledEl.ts +38 -0
- package/testaro/zIndex.d.ts +3 -0
- package/testaro/zIndex.js +19 -22
- package/testaro/zIndex.ts +42 -0
- package/tests/alfa.d.ts +45 -0
- package/tests/alfa.js +138 -141
- package/tests/alfa.ts +214 -0
- package/tests/aslint.d.ts +33 -0
- package/tests/aslint.js +272 -249
- package/tests/aslint.ts +301 -0
- package/tests/axe.d.ts +27 -0
- package/tests/axe.js +199 -200
- package/tests/axe.ts +277 -0
- package/tests/ed11y.d.ts +28 -0
- package/tests/ed11y.js +141 -99
- package/tests/ed11y.ts +178 -0
- package/tests/htmlcs.d.ts +21 -0
- package/tests/htmlcs.js +174 -140
- package/tests/htmlcs.ts +181 -0
- package/tests/ibm.d.ts +52 -0
- package/tests/ibm.js +164 -166
- package/tests/ibm.ts +251 -0
- package/tests/nuVal.d.ts +13 -0
- package/tests/nuVal.js +107 -112
- package/tests/nuVal.ts +145 -0
- package/tests/nuVnu.d.ts +15 -0
- package/tests/nuVnu.js +141 -111
- package/tests/nuVnu.ts +144 -0
- package/tests/pour.d.ts +31 -0
- package/tests/pour.js +242 -0
- package/tests/pour.ts +273 -0
- package/tests/qualWeb.d.ts +39 -0
- package/tests/qualWeb.js +302 -272
- package/tests/qualWeb.ts +415 -0
- package/tests/surea11y.d.ts +33 -0
- package/tests/surea11y.js +288 -0
- package/tests/surea11y.ts +334 -0
- package/tests/testaro.d.ts +25 -0
- package/tests/testaro.js +745 -652
- package/tests/testaro.ts +862 -0
- package/tests/wave.d.ts +46 -0
- package/tests/wave.js +166 -177
- package/tests/wave.ts +252 -0
- package/tsconfig.json +17 -0
- package/types.d.ts +243 -0
- package/types.js +10 -0
- package/types.ts +376 -0
- package/validation/act/README.md +46 -0
- package/validation/act/capture.js +424 -0
- package/validation/act/chromium-issue-draft.md +66 -0
- package/validation/act/fp-triage-2026-08-22.md +86 -0
- package/validation/act/isolation-notes.md +159 -0
- package/validation/act/playwright-issue-draft.md +73 -0
- package/validation/act/propose-mappings.js +0 -0
- package/validation/act/repro-cdp-raw.js +105 -0
- package/validation/act/repro-metarefresh.js +65 -0
- package/validation/act/score.js +184 -0
- package/validation/act/stage3a-stress-report.md +69 -0
- package/validation/act/stage3b-mapping-proposals.md +94 -0
- package/validation/act/stage3b-triage-draft.md +138 -0
- package/validation/act/surea11y-track-a-2026-09-01.md +50 -0
- package/validation/executors/netWatch.js +180 -90
- package/validation/executors/test.js +17 -2
- package/validation/executors/tests.js +118 -10
- package/validation/jobs/reports/raw/260901T1000-surea11y-validation.json +964 -0
- package/validation/jobs/todo/240101T1200-simple-example.json +14 -6
- package/validation/jobs/todo/240101T1300-shoot-example.json +2 -1
- package/validation/jobs/todo/260821T1900-pour-validation.json +45 -0
- package/validation/jobs/todo/260901T1000-surea11y-validation.json +45 -0
- package/validation/knownFailures.json +1 -0
- package/validation/tests/jobProperties/adbID.json +27 -2
- package/validation/tests/jobProperties/{focOp.json → allCapStyle.json} +56 -53
- package/validation/tests/jobProperties/allCaps.json +25 -0
- package/validation/tests/jobProperties/allHidden.json +133 -13
- package/validation/tests/jobProperties/allSlanted.json +3 -3
- package/validation/tests/jobProperties/altScheme.json +23 -8
- package/validation/tests/jobProperties/attVal.json +57 -57
- package/validation/tests/jobProperties/autocomplete.json +11 -1
- package/validation/tests/jobProperties/bulk.json +6 -1
- package/validation/tests/jobProperties/buttonMenu.json +63 -42
- package/validation/tests/jobProperties/captionLoc.json +1 -6
- package/validation/tests/jobProperties/checkpoint-browser.json +401 -0
- package/validation/tests/jobProperties/checkpoint-page.json +397 -0
- package/validation/tests/jobProperties/checkpoint.json +395 -0
- package/validation/tests/jobProperties/datalistRef.json +20 -5
- package/validation/tests/jobProperties/distortion.json +28 -3
- package/validation/tests/jobProperties/docType.json +2 -2
- package/validation/tests/jobProperties/dupAtt.json +48 -33
- package/validation/tests/jobProperties/elements.json +28 -28
- package/validation/tests/jobProperties/embAc.json +36 -31
- package/validation/tests/jobProperties/focAndOp.json +284 -0
- package/validation/tests/jobProperties/focInd.json +34 -34
- package/validation/tests/jobProperties/focVis.json +1 -1
- package/validation/tests/jobProperties/hover.json +39 -37
- package/validation/tests/jobProperties/hr.json +13 -3
- package/validation/tests/jobProperties/imageLink.json +0 -5
- package/validation/tests/jobProperties/labClash.json +68 -33
- package/validation/tests/jobProperties/legendLoc.json +1 -6
- package/validation/tests/jobProperties/lineHeight.json +2 -2
- package/validation/tests/jobProperties/linkAmb.json +13 -18
- package/validation/tests/jobProperties/linkExt.json +1 -1
- package/validation/tests/jobProperties/linkOldAtt.json +12 -2
- package/validation/tests/jobProperties/linkTo.json +1 -1
- package/validation/tests/jobProperties/linkUl.json +65 -65
- package/validation/tests/jobProperties/miniText.json +7 -2
- package/validation/tests/jobProperties/motion.json +4 -50
- package/validation/tests/jobProperties/nonTable.json +48 -3
- package/validation/tests/jobProperties/optRoleSel.json +12 -2
- package/validation/tests/jobProperties/phOnly.json +6 -16
- package/validation/tests/jobProperties/pseudoP.json +17 -2
- package/validation/tests/jobProperties/radioSet.json +30 -30
- package/validation/tests/jobProperties/role.json +25 -5
- package/validation/tests/jobProperties/secHeading.json +26 -21
- package/validation/tests/jobProperties/styleDiff.json +35 -5
- package/validation/tests/jobProperties/tabNav.json +3 -1
- package/validation/tests/jobProperties/targetsNear.json +237 -0
- package/validation/tests/jobProperties/textNodes.json +29 -29
- package/validation/tests/jobProperties/textSem.json +26 -1
- package/validation/tests/jobProperties/title.json +12 -2
- package/validation/tests/jobProperties/titledEl.json +39 -9
- package/validation/tests/jobProperties/userPath.json +317 -0
- package/validation/tests/jobProperties/zIndex.json +40 -35
- package/validation/tests/targets/allCapStyle/index.html +26 -0
- package/validation/tests/targets/checkpoint/index.html +38 -0
- package/validation/tests/targets/datalistRef/index.html +1 -1
- package/validation/tests/targets/focAndOp/bad.html +29 -0
- package/validation/tests/targets/{focOp → focAndOp}/good.html +3 -1
- package/validation/tests/targets/focInd/bad.html +2 -1
- package/validation/tests/targets/headEl/index.html +10 -1
- package/validation/tests/targets/{targetSmall → targetsNear}/index.html +15 -1
- package/validation/tests/targets/userPath/index.html +42 -0
- package/validation/validateTest.js +61 -9
- package/.claude/settings.local.json +0 -11
- package/.eslintrc.json +0 -41
- package/htmlcs/.eslintrc.json +0 -67
- package/validation/tests/jobProperties/linkTitle.json +0 -127
- package/validation/tests/jobProperties/opFoc.json +0 -164
- package/validation/tests/jobProperties/targetSmall.json +0 -152
- package/validation/tests/jobProperties/targetTiny.json +0 -142
- package/validation/tests/targets/focOp/bad.html +0 -25
- package/validation/tests/targets/linkTitle/index.html +0 -24
- package/validation/tests/targets/opFoc/bad.html +0 -26
- package/validation/tests/targets/opFoc/good.html +0 -23
package/tests/axe.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2021–2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2026 Jeff Witt.
|
|
@@ -8,7 +9,19 @@
|
|
|
8
9
|
|
|
9
10
|
SPDX-License-Identifier: MIT
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.reporter = void 0;
|
|
14
|
+
const xPath_1 = require("../procs/xPath");
|
|
15
|
+
const standard_1 = require("../procs/standard");
|
|
16
|
+
const axePlaywright = require('axe-playwright');
|
|
17
|
+
// CONSTANTS
|
|
18
|
+
const { injectAxe } = axePlaywright;
|
|
19
|
+
const severityWeights = {
|
|
20
|
+
minor: 0,
|
|
21
|
+
moderate: 0,
|
|
22
|
+
serious: 1,
|
|
23
|
+
critical: 1
|
|
24
|
+
};
|
|
12
25
|
/*
|
|
13
26
|
axe
|
|
14
27
|
Implements the axe-core ruleset for accessibility.
|
|
@@ -28,215 +41,201 @@
|
|
|
28
41
|
incomplete categories, node totals by severity. It does not show rule or node totals by test
|
|
29
42
|
category (“tag”), such as 'wcag21aaa'. Scoring can consider test categories by getting the value
|
|
30
43
|
of the 'tags' property of each rule.
|
|
44
|
+
Compiled to axe.js by tsc (issue #73); edit this file, not the emitted one.
|
|
31
45
|
*/
|
|
32
|
-
|
|
33
|
-
// IMPORTS
|
|
34
|
-
|
|
35
|
-
const axePlaywright = require('axe-playwright');
|
|
36
|
-
const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
|
|
37
|
-
|
|
38
|
-
// CONSTANTS
|
|
39
|
-
|
|
40
|
-
const {injectAxe} = axePlaywright;
|
|
41
|
-
const severityWeights = {
|
|
42
|
-
minor: 0,
|
|
43
|
-
moderate: 0,
|
|
44
|
-
serious: 1,
|
|
45
|
-
critical: 1
|
|
46
|
-
};
|
|
47
|
-
|
|
48
46
|
// FUNCTIONS
|
|
49
|
-
|
|
50
47
|
// Conducts and reports the Axe tests.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
const standard = report.standard !== 'no';
|
|
61
|
-
// If standard results are to be reported:
|
|
62
|
-
if (standard) {
|
|
63
|
-
// Initialize the standard result.
|
|
64
|
-
result.standardResult = {
|
|
65
|
-
prevented: false,
|
|
66
|
-
totals: [0, 0, 0, 0],
|
|
67
|
-
instances: []
|
|
48
|
+
const reporter = async (page, report, actIndex) => {
|
|
49
|
+
const act = report.acts[actIndex];
|
|
50
|
+
const { detailLevel, rules } = act;
|
|
51
|
+
// Initialize the act report.
|
|
52
|
+
let data = {};
|
|
53
|
+
const result = {
|
|
54
|
+
nativeResult: {},
|
|
55
|
+
standardResult: {}
|
|
68
56
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.log(`ERROR: Axe injection failed (${error.message})`);
|
|
75
|
-
data.prevented = true;
|
|
76
|
-
data.error = 'ERROR: axe injection failed';
|
|
77
|
-
});
|
|
78
|
-
// If the injection succeeded:
|
|
79
|
-
if (! data.prevented) {
|
|
80
|
-
// Get the data on the elements violating the specified axe-core rules.
|
|
81
|
-
const axeOptions = {
|
|
82
|
-
resultTypes: ['violations', 'incomplete']
|
|
83
|
-
};
|
|
84
|
-
if (rules && rules.length) {
|
|
85
|
-
axeOptions.runOnly = rules;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
axeOptions.runOnly = ['experimental', 'best-practice', 'wcag2a', 'wcag2aa', 'wcag2aaa', 'wcag21a', 'wcag21aa', 'wcag21aaa'];
|
|
57
|
+
const standard = report.standard !== 'no';
|
|
58
|
+
// If standard results are to be reported:
|
|
59
|
+
if (standard) {
|
|
60
|
+
// Initialize the standard result.
|
|
61
|
+
result.standardResult = (0, standard_1.getStandardResult)();
|
|
89
62
|
}
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
minor: 0,
|
|
108
|
-
moderate: 0,
|
|
109
|
-
serious: 0,
|
|
110
|
-
critical: 0
|
|
63
|
+
const { nativeResult, standardResult } = result;
|
|
64
|
+
// Inject axe-core into the page.
|
|
65
|
+
await injectAxe(page)
|
|
66
|
+
.catch(error => {
|
|
67
|
+
console.log(`ERROR: Axe injection failed (${error.message})`);
|
|
68
|
+
data.prevented = true;
|
|
69
|
+
data.error = 'ERROR: axe injection failed';
|
|
70
|
+
});
|
|
71
|
+
// If the injection succeeded:
|
|
72
|
+
if (!data.prevented) {
|
|
73
|
+
// Get the data on the elements violating the specified axe-core rules.
|
|
74
|
+
const axeOptions = {
|
|
75
|
+
resultTypes: ['violations', 'incomplete']
|
|
76
|
+
};
|
|
77
|
+
if (rules && rules.length) {
|
|
78
|
+
// A bare array would be read as tag names; rule IDs need the object form.
|
|
79
|
+
axeOptions.runOnly = { type: 'rule', values: rules };
|
|
111
80
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
81
|
+
else {
|
|
82
|
+
axeOptions.runOnly = ['experimental', 'best-practice', 'wcag2a', 'wcag2aa', 'wcag2aaa', 'wcag21a', 'wcag21aa', 'wcag21aaa'];
|
|
83
|
+
}
|
|
84
|
+
// If the act is scoped to changed subtrees, test only them (axe's include context).
|
|
85
|
+
const scopeRoots = report.scope?.roots;
|
|
86
|
+
const context = scopeRoots && scopeRoots.length
|
|
87
|
+
? { include: scopeRoots }
|
|
88
|
+
: null;
|
|
89
|
+
const axeReport = await axePlaywright.getAxeResults(page, context, axeOptions);
|
|
90
|
+
const { inapplicable, passes, incomplete, violations } = axeReport;
|
|
91
|
+
// If the test succeeded:
|
|
92
|
+
if (violations) {
|
|
93
|
+
// Initialize the native result.
|
|
94
|
+
nativeResult.totals = {
|
|
95
|
+
rulesNA: 0,
|
|
96
|
+
rulesPassed: 0,
|
|
97
|
+
rulesWarned: 0,
|
|
98
|
+
rulesViolated: 0,
|
|
99
|
+
warnings: {
|
|
100
|
+
minor: 0,
|
|
101
|
+
moderate: 0,
|
|
102
|
+
serious: 0,
|
|
103
|
+
critical: 0
|
|
104
|
+
},
|
|
105
|
+
violations: {
|
|
106
|
+
minor: 0,
|
|
107
|
+
moderate: 0,
|
|
108
|
+
serious: 0,
|
|
109
|
+
critical: 0
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
nativeResult.details = axeReport;
|
|
113
|
+
// Populate the native-result totals.
|
|
114
|
+
const { totals } = nativeResult;
|
|
115
|
+
totals.rulesNA = inapplicable.length;
|
|
116
|
+
totals.rulesPassed = passes.length;
|
|
117
|
+
incomplete.forEach(rule => {
|
|
118
|
+
totals.rulesWarned++;
|
|
119
|
+
rule.nodes.forEach(node => {
|
|
120
|
+
totals.warnings[node.impact]++;
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
violations.forEach(rule => {
|
|
124
|
+
totals.rulesViolated++;
|
|
125
|
+
rule.nodes.forEach(node => {
|
|
126
|
+
totals.violations[node.impact]++;
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
// If standard results are to be reported and there are any suspicions:
|
|
130
|
+
if (standard && (totals.rulesViolated || totals.rulesWarned)) {
|
|
131
|
+
// Resolve each suspected element's FULL data-xpath from the live DOM,
|
|
132
|
+
// keyed by its axe target. axe-core truncates node.html (~300 chars,
|
|
133
|
+
// appends '...'), so parsing data-xpath out of node.html yields a
|
|
134
|
+
// truncated XPath for elements with long attribute lists. node.target
|
|
135
|
+
// is a reliable CSS selector; read the injected data-xpath directly off
|
|
136
|
+
// the element instead. Falls back to the node.html parse on any failure.
|
|
137
|
+
const fullXPathByTargetKey = {};
|
|
138
|
+
try {
|
|
139
|
+
const suspectNodes = ['incomplete', 'violations']
|
|
140
|
+
.filter(certainty => nativeResult?.details?.[certainty])
|
|
141
|
+
.flatMap(certainty => nativeResult.details[certainty].flatMap(rule => rule.nodes));
|
|
142
|
+
const targets = suspectNodes.map(node => node.target);
|
|
143
|
+
const resolvedXPaths = await page.evaluate(targetList => targetList.map(target => {
|
|
144
|
+
try {
|
|
145
|
+
// axe target is an array of selectors (nested arrays for frames/
|
|
146
|
+
// shadow roots). Use the deepest plain-string selector for the
|
|
147
|
+
// common, non-framed case; skip otherwise.
|
|
148
|
+
const selector = Array.isArray(target)
|
|
149
|
+
? (typeof target[target.length - 1] === 'string' ? target[target.length - 1] : null)
|
|
150
|
+
: (typeof target === 'string' ? target : null);
|
|
151
|
+
if (!selector) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const element = document.querySelector(selector);
|
|
155
|
+
return element ? element.getAttribute('data-xpath') : null;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}), targets);
|
|
161
|
+
suspectNodes.forEach((node, index) => {
|
|
162
|
+
if (resolvedXPaths[index]) {
|
|
163
|
+
fullXPathByTargetKey[JSON.stringify(node.target)] = resolvedXPaths[index];
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
// Leave the map empty; every instance falls back to node.html below.
|
|
169
|
+
}
|
|
170
|
+
// For each certainty type:
|
|
171
|
+
['incomplete', 'violations'].forEach(certainty => {
|
|
172
|
+
// If there are any suspicions of this type:
|
|
173
|
+
if (nativeResult?.details?.[certainty]) {
|
|
174
|
+
// For each rule with any suspicions:
|
|
175
|
+
nativeResult.details[certainty].forEach(rule => {
|
|
176
|
+
// For each element suspected of violating the rule:
|
|
177
|
+
rule.nodes.forEach((node) => {
|
|
178
|
+
// Get descriptions of the rule.
|
|
179
|
+
const whatSet = new Set([
|
|
180
|
+
rule.help,
|
|
181
|
+
...node.any.map(anyItem => anyItem.message),
|
|
182
|
+
...node.all.map(allItem => allItem.message)
|
|
183
|
+
]);
|
|
184
|
+
// Get the ordinal severity of the suspicion.
|
|
185
|
+
const ordinalSeverity = severityWeights[node.impact]
|
|
186
|
+
+ (certainty === 'violations' ? 2 : 0);
|
|
187
|
+
// Get the XPath of the suspected element from its data-xpath
|
|
188
|
+
// attribute. Prefer the full value resolved from the live DOM
|
|
189
|
+
// (above); fall back to parsing it out of axe's node.html,
|
|
190
|
+
// which axe truncates and can corrupt the XPath.
|
|
191
|
+
const xPath = fullXPathByTargetKey[JSON.stringify(node.target)]
|
|
192
|
+
|| (0, xPath_1.getAttributeXPath)(node.html);
|
|
193
|
+
(0, standard_1.addInstance)(standardResult, {
|
|
194
|
+
ruleID: rule.id,
|
|
195
|
+
what: Array.from(whatSet.values()).join('; '),
|
|
196
|
+
ordinalSeverity,
|
|
197
|
+
outcome: certainty === 'violations' ? 'failed' : 'cantTell',
|
|
198
|
+
catalogIndex: (0, xPath_1.getXPathCatalogIndex)(report, xPath)
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
171
204
|
}
|
|
172
|
-
|
|
205
|
+
// Delete the properties of the report details that the detail level excludes, after the
|
|
206
|
+
// standard result has been made from them, so the standard result does not depend on
|
|
207
|
+
// the detail level.
|
|
208
|
+
const irrelevants = ['inapplicable', 'passes', 'incomplete', 'violations']
|
|
209
|
+
.slice(0, 4 - detailLevel);
|
|
210
|
+
irrelevants.forEach(irrelevant => {
|
|
211
|
+
delete axeReport[irrelevant];
|
|
212
|
+
});
|
|
173
213
|
}
|
|
174
|
-
|
|
175
|
-
|
|
214
|
+
// Otherwise, i.e. if the test failed:
|
|
215
|
+
else {
|
|
216
|
+
// Report this.
|
|
217
|
+
data.prevented = true;
|
|
218
|
+
data.error = 'ERROR: Act failed';
|
|
219
|
+
if (standard) {
|
|
220
|
+
standardResult.prevented = true;
|
|
221
|
+
}
|
|
176
222
|
}
|
|
177
|
-
// For each certainty type:
|
|
178
|
-
['incomplete', 'violations'].forEach(certainty => {
|
|
179
|
-
// If there are any suspicions of this type:
|
|
180
|
-
if (nativeResult?.details?.[certainty]) {
|
|
181
|
-
// For each rule with any suspicions:
|
|
182
|
-
nativeResult.details[certainty].forEach(rule => {
|
|
183
|
-
// For each element suspected of violating the rule:
|
|
184
|
-
rule.nodes.forEach(node => {
|
|
185
|
-
// Get descriptions of the rule.
|
|
186
|
-
const whatSet = new Set([
|
|
187
|
-
rule.help,
|
|
188
|
-
... node.any.map(anyItem => anyItem.message),
|
|
189
|
-
... node.all.map(allItem => allItem.message)
|
|
190
|
-
]);
|
|
191
|
-
// Get the ordinal severity of the suspicion.
|
|
192
|
-
const ordinalSeverity = severityWeights[node.impact]
|
|
193
|
-
+ (certainty === 'violations' ? 2 : 0);
|
|
194
|
-
// Increment the standard total.
|
|
195
|
-
standardResult.totals[ordinalSeverity]++;
|
|
196
|
-
// Get the XPath of the suspected element from its data-xpath
|
|
197
|
-
// attribute. Prefer the full value resolved from the live DOM
|
|
198
|
-
// (above); fall back to parsing it out of axe's node.html,
|
|
199
|
-
// which axe truncates and can corrupt the XPath.
|
|
200
|
-
const xPath = fullXPathByTargetKey[JSON.stringify(node.target)]
|
|
201
|
-
|| getAttributeXPath(node.html);
|
|
202
|
-
const instance = {
|
|
203
|
-
ruleID: rule.id,
|
|
204
|
-
what: Array.from(whatSet.values()).join('; '),
|
|
205
|
-
ordinalSeverity,
|
|
206
|
-
count: 1,
|
|
207
|
-
catalogIndex: getXPathCatalogIndex(report, xPath)
|
|
208
|
-
};
|
|
209
|
-
standardResult.instances.push(instance);
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
223
|
}
|
|
216
|
-
//
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
+
// Return the result.
|
|
225
|
+
try {
|
|
226
|
+
JSON.stringify(data);
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
const message = `ERROR: Axe result cannot be made JSON (${error.message})`;
|
|
230
|
+
console.log(message);
|
|
231
|
+
data = {
|
|
232
|
+
prevented: true,
|
|
233
|
+
error: message
|
|
234
|
+
};
|
|
224
235
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
JSON.stringify(data);
|
|
229
|
-
}
|
|
230
|
-
catch(error) {
|
|
231
|
-
const message = `ERROR: Axe result cannot be made JSON (${error.message})`;
|
|
232
|
-
console.log(message);
|
|
233
|
-
data = {
|
|
234
|
-
prevented: true,
|
|
235
|
-
error: message
|
|
236
|
+
return {
|
|
237
|
+
data,
|
|
238
|
+
result
|
|
236
239
|
};
|
|
237
|
-
}
|
|
238
|
-
return {
|
|
239
|
-
data,
|
|
240
|
-
result
|
|
241
|
-
};
|
|
242
240
|
};
|
|
241
|
+
exports.reporter = reporter;
|