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/testaro.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2023–2025 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2026 Jeff Witt.
|
|
@@ -8,670 +9,762 @@
|
|
|
8
9
|
|
|
9
10
|
SPDX-License-Identifier: MIT
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// Shared configuration for timeout multiplier.
|
|
20
|
-
const {applyMultiplier} = require('../procs/config');
|
|
21
|
-
const {launch} = require('../procs/launch');
|
|
22
|
-
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.reporter = void 0;
|
|
14
|
+
const config_1 = require("../procs/config");
|
|
15
|
+
const launch_1 = require("../procs/launch");
|
|
16
|
+
// Function to get an empty standard result.
|
|
17
|
+
const standard_1 = require("../procs/standard");
|
|
18
|
+
const registry_1 = require("../testaro/registry");
|
|
23
19
|
// CONSTANTS
|
|
24
|
-
|
|
25
20
|
// Metadata of all rules in default execution order.
|
|
26
21
|
const allRules = [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
22
|
+
{
|
|
23
|
+
id: 'adbID',
|
|
24
|
+
what: 'elements with ambiguous or missing referenced descriptions',
|
|
25
|
+
contaminates: false,
|
|
26
|
+
needsAccessibleName: false,
|
|
27
|
+
local: true,
|
|
28
|
+
timeOut: 5,
|
|
29
|
+
defaultOn: true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'allCapStyle',
|
|
33
|
+
what: 'elements with all-capital text transformation styles',
|
|
34
|
+
contaminates: false,
|
|
35
|
+
needsAccessibleName: false,
|
|
36
|
+
local: true,
|
|
37
|
+
timeOut: 5,
|
|
38
|
+
defaultOn: false
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'allCaps',
|
|
42
|
+
what: 'elements with unnecessarily all-capital text substrings',
|
|
43
|
+
contaminates: false,
|
|
44
|
+
needsAccessibleName: false,
|
|
45
|
+
local: true,
|
|
46
|
+
outcome: 'cantTell',
|
|
47
|
+
uncertainty: 'judgement-required',
|
|
48
|
+
timeOut: 30,
|
|
49
|
+
defaultOn: true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'allHidden',
|
|
53
|
+
what: 'page that is entirely or mostly hidden',
|
|
54
|
+
contaminates: false,
|
|
55
|
+
needsAccessibleName: false,
|
|
56
|
+
local: false,
|
|
57
|
+
timeOut: 5,
|
|
58
|
+
defaultOn: true
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'allSlanted',
|
|
62
|
+
what: 'leaf elements with entirely italic or oblique text longer than 39 characters',
|
|
63
|
+
contaminates: false,
|
|
64
|
+
needsAccessibleName: false,
|
|
65
|
+
local: true,
|
|
66
|
+
timeOut: 5,
|
|
67
|
+
defaultOn: true
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'altScheme',
|
|
71
|
+
what: 'img elements with alt attributes having URLs as their entire values',
|
|
72
|
+
contaminates: false,
|
|
73
|
+
needsAccessibleName: false,
|
|
74
|
+
local: true,
|
|
75
|
+
timeOut: 5,
|
|
76
|
+
defaultOn: true
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'attVal',
|
|
80
|
+
what: 'elements with attributes having illicit values',
|
|
81
|
+
contaminates: false,
|
|
82
|
+
needsAccessibleName: false,
|
|
83
|
+
local: true,
|
|
84
|
+
timeOut: 5,
|
|
85
|
+
defaultOn: false
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'bulk',
|
|
89
|
+
what: 'large count of visible elements',
|
|
90
|
+
contaminates: false,
|
|
91
|
+
needsAccessibleName: false,
|
|
92
|
+
local: false,
|
|
93
|
+
timeOut: 5,
|
|
94
|
+
defaultOn: true
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 'captionLoc',
|
|
98
|
+
what: 'caption elements that are not first children of table elements',
|
|
99
|
+
contaminates: false,
|
|
100
|
+
needsAccessibleName: false,
|
|
101
|
+
local: true,
|
|
102
|
+
timeOut: 5,
|
|
103
|
+
defaultOn: true
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 'datalistRef',
|
|
107
|
+
what: 'elements with ambiguous or missing referenced datalist elements',
|
|
108
|
+
contaminates: false,
|
|
109
|
+
needsAccessibleName: false,
|
|
110
|
+
local: true,
|
|
111
|
+
timeOut: 5,
|
|
112
|
+
defaultOn: true
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: 'distortion',
|
|
116
|
+
what: 'distorted text',
|
|
117
|
+
contaminates: false,
|
|
118
|
+
needsAccessibleName: false,
|
|
119
|
+
local: true,
|
|
120
|
+
timeOut: 5,
|
|
121
|
+
defaultOn: true
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: 'docType',
|
|
125
|
+
what: 'document without a doctype property',
|
|
126
|
+
contaminates: false,
|
|
127
|
+
needsAccessibleName: false,
|
|
128
|
+
local: false,
|
|
129
|
+
timeOut: 5,
|
|
130
|
+
defaultOn: true
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: 'embAc',
|
|
134
|
+
what: 'active elements embedded in links or buttons',
|
|
135
|
+
contaminates: false,
|
|
136
|
+
needsAccessibleName: false,
|
|
137
|
+
local: true,
|
|
138
|
+
timeOut: 5,
|
|
139
|
+
defaultOn: true
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'headEl',
|
|
143
|
+
what: 'invalid elements within the head',
|
|
144
|
+
contaminates: false,
|
|
145
|
+
needsAccessibleName: false,
|
|
146
|
+
local: false,
|
|
147
|
+
timeOut: 5,
|
|
148
|
+
defaultOn: true
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: 'headingAmb',
|
|
152
|
+
what: 'same-level sibling headings with identical texts',
|
|
153
|
+
contaminates: false,
|
|
154
|
+
needsAccessibleName: false,
|
|
155
|
+
local: false,
|
|
156
|
+
timeOut: 5,
|
|
157
|
+
defaultOn: true
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'hr',
|
|
161
|
+
what: 'hr element instead of styles used for vertical segmentation',
|
|
162
|
+
contaminates: false,
|
|
163
|
+
needsAccessibleName: false,
|
|
164
|
+
local: true,
|
|
165
|
+
timeOut: 5,
|
|
166
|
+
defaultOn: true
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'imageLink',
|
|
170
|
+
what: 'links with image files as their destinations',
|
|
171
|
+
contaminates: false,
|
|
172
|
+
needsAccessibleName: false,
|
|
173
|
+
local: true,
|
|
174
|
+
timeOut: 5,
|
|
175
|
+
defaultOn: true
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 'labClash',
|
|
179
|
+
what: 'labeling inconsistencies',
|
|
180
|
+
contaminates: false,
|
|
181
|
+
needsAccessibleName: false,
|
|
182
|
+
local: false,
|
|
183
|
+
timeOut: 5,
|
|
184
|
+
defaultOn: true
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
id: 'legendLoc',
|
|
188
|
+
what: 'legend elements that are not first children of fieldset elements',
|
|
189
|
+
contaminates: false,
|
|
190
|
+
needsAccessibleName: false,
|
|
191
|
+
local: true,
|
|
192
|
+
timeOut: 5,
|
|
193
|
+
defaultOn: true
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: 'lineHeight',
|
|
197
|
+
what: 'text with a line height less than 1.5 times its font size',
|
|
198
|
+
contaminates: false,
|
|
199
|
+
needsAccessibleName: false,
|
|
200
|
+
local: true,
|
|
201
|
+
timeOut: 5,
|
|
202
|
+
defaultOn: true
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: 'linkAmb',
|
|
206
|
+
what: 'links with identical texts but different destinations',
|
|
207
|
+
contaminates: false,
|
|
208
|
+
needsAccessibleName: false,
|
|
209
|
+
local: false,
|
|
210
|
+
timeOut: 20,
|
|
211
|
+
defaultOn: true
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: 'linkExt',
|
|
215
|
+
what: 'links that automatically open new windows',
|
|
216
|
+
contaminates: false,
|
|
217
|
+
needsAccessibleName: false,
|
|
218
|
+
local: true,
|
|
219
|
+
timeOut: 5,
|
|
220
|
+
defaultOn: true
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 'linkOldAtt',
|
|
224
|
+
what: 'links with deprecated attributes',
|
|
225
|
+
contaminates: false,
|
|
226
|
+
needsAccessibleName: false,
|
|
227
|
+
local: true,
|
|
228
|
+
timeOut: 5,
|
|
229
|
+
defaultOn: true
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: 'linkTo',
|
|
233
|
+
what: 'links without destinations',
|
|
234
|
+
contaminates: false,
|
|
235
|
+
needsAccessibleName: false,
|
|
236
|
+
local: true,
|
|
237
|
+
timeOut: 5,
|
|
238
|
+
defaultOn: true
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: 'linkUl',
|
|
242
|
+
what: 'missing underlines on inline links',
|
|
243
|
+
contaminates: false,
|
|
244
|
+
needsAccessibleName: false,
|
|
245
|
+
local: true,
|
|
246
|
+
timeOut: 5,
|
|
247
|
+
defaultOn: true
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
id: 'miniText',
|
|
251
|
+
what: 'text smaller than 11 pixels',
|
|
252
|
+
contaminates: false,
|
|
253
|
+
needsAccessibleName: false,
|
|
254
|
+
local: true,
|
|
255
|
+
timeOut: 5,
|
|
256
|
+
defaultOn: true
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: 'nonTable',
|
|
260
|
+
what: 'table elements used for layout',
|
|
261
|
+
contaminates: false,
|
|
262
|
+
needsAccessibleName: false,
|
|
263
|
+
local: true,
|
|
264
|
+
timeOut: 5,
|
|
265
|
+
defaultOn: true
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: 'optRoleSel',
|
|
269
|
+
what: 'Non-option elements with option roles that have no aria-selected attributes',
|
|
270
|
+
contaminates: false,
|
|
271
|
+
needsAccessibleName: false,
|
|
272
|
+
local: true,
|
|
273
|
+
timeOut: 5,
|
|
274
|
+
defaultOn: true
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: 'pseudoP',
|
|
278
|
+
what: 'adjacent br elements suspected of nonsemantically simulating p elements',
|
|
279
|
+
contaminates: false,
|
|
280
|
+
needsAccessibleName: false,
|
|
281
|
+
local: true,
|
|
282
|
+
timeOut: 5,
|
|
283
|
+
defaultOn: true
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: 'radioSet',
|
|
287
|
+
what: 'radio buttons not grouped into standard field sets',
|
|
288
|
+
contaminates: false,
|
|
289
|
+
needsAccessibleName: false,
|
|
290
|
+
local: false,
|
|
291
|
+
timeOut: 5,
|
|
292
|
+
defaultOn: true
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 'role',
|
|
296
|
+
what: 'native-replacing explicit roles',
|
|
297
|
+
contaminates: false,
|
|
298
|
+
needsAccessibleName: false,
|
|
299
|
+
local: false,
|
|
300
|
+
timeOut: 20,
|
|
301
|
+
defaultOn: true
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
id: 'secHeading',
|
|
305
|
+
what: 'headings that violate the logical level order in their sectioning containers',
|
|
306
|
+
contaminates: false,
|
|
307
|
+
needsAccessibleName: false,
|
|
308
|
+
local: false,
|
|
309
|
+
timeOut: 5,
|
|
310
|
+
defaultOn: true
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
id: 'styleDiff',
|
|
314
|
+
what: 'style inconsistencies',
|
|
315
|
+
contaminates: false,
|
|
316
|
+
needsAccessibleName: false,
|
|
317
|
+
local: false,
|
|
318
|
+
timeOut: 5,
|
|
319
|
+
defaultOn: true
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: 'targetsNear',
|
|
323
|
+
what: 'labels, buttons, inputs, and links too near each other',
|
|
324
|
+
contaminates: false,
|
|
325
|
+
needsAccessibleName: false,
|
|
326
|
+
local: false,
|
|
327
|
+
timeOut: 5,
|
|
328
|
+
defaultOn: true
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
id: 'textSem',
|
|
332
|
+
what: 'semantically vague elements i, b, and/or small',
|
|
333
|
+
contaminates: false,
|
|
334
|
+
needsAccessibleName: false,
|
|
335
|
+
local: true,
|
|
336
|
+
timeOut: 5,
|
|
337
|
+
defaultOn: true
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
id: 'title',
|
|
341
|
+
what: 'page title',
|
|
342
|
+
contaminates: false,
|
|
343
|
+
needsAccessibleName: false,
|
|
344
|
+
local: false,
|
|
345
|
+
timeOut: 5,
|
|
346
|
+
defaultOn: false
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
id: 'titledEl',
|
|
350
|
+
what: 'title attributes on inappropriate elements',
|
|
351
|
+
contaminates: false,
|
|
352
|
+
needsAccessibleName: false,
|
|
353
|
+
local: true,
|
|
354
|
+
timeOut: 5,
|
|
355
|
+
defaultOn: true
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
id: 'zIndex',
|
|
359
|
+
what: 'non-default Z indexes',
|
|
360
|
+
contaminates: false,
|
|
361
|
+
needsAccessibleName: false,
|
|
362
|
+
local: true,
|
|
363
|
+
timeOut: 5,
|
|
364
|
+
defaultOn: true
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
id: 'motion',
|
|
368
|
+
what: 'motion without user request',
|
|
369
|
+
contaminates: false,
|
|
370
|
+
needsAccessibleName: false,
|
|
371
|
+
local: false,
|
|
372
|
+
// The budget must cover a full-page screenshot (itself allowed 4 seconds in
|
|
373
|
+
// procs/shoot.js), decoding two full-page PNGs, and a pixel comparison; 5
|
|
374
|
+
// seconds made the rule time out whenever an initial image existed.
|
|
375
|
+
timeOut: 30,
|
|
376
|
+
defaultOn: true
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
id: 'dupAtt',
|
|
380
|
+
what: 'duplicate attribute values',
|
|
381
|
+
contaminates: false,
|
|
382
|
+
needsAccessibleName: false,
|
|
383
|
+
local: false,
|
|
384
|
+
timeOut: 5,
|
|
385
|
+
defaultOn: true
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
id: 'autocomplete',
|
|
389
|
+
what: 'name and email inputs without autocomplete attributes',
|
|
390
|
+
contaminates: false,
|
|
391
|
+
needsAccessibleName: true,
|
|
392
|
+
local: true,
|
|
393
|
+
timeOut: 5,
|
|
394
|
+
defaultOn: true
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
id: 'phOnly',
|
|
398
|
+
what: 'input elements with placeholders but no accessible names',
|
|
399
|
+
contaminates: false,
|
|
400
|
+
needsAccessibleName: true,
|
|
401
|
+
local: true,
|
|
402
|
+
timeOut: 5,
|
|
403
|
+
defaultOn: true
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: 'buttonMenu',
|
|
407
|
+
what: 'nonstandard keyboard navigation between items of button-controlled menus',
|
|
408
|
+
contaminates: true,
|
|
409
|
+
needsAccessibleName: false,
|
|
410
|
+
local: false,
|
|
411
|
+
timeOut: 15,
|
|
412
|
+
defaultOn: true
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
id: 'elements',
|
|
416
|
+
what: 'data on specified elements',
|
|
417
|
+
contaminates: true,
|
|
418
|
+
needsAccessibleName: false,
|
|
419
|
+
local: false,
|
|
420
|
+
timeOut: 10,
|
|
421
|
+
defaultOn: false
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
id: 'focAll',
|
|
425
|
+
what: 'discrepancies between focusable and Tab-focused elements',
|
|
426
|
+
contaminates: true,
|
|
427
|
+
needsAccessibleName: false,
|
|
428
|
+
local: false,
|
|
429
|
+
timeOut: 10,
|
|
430
|
+
defaultOn: true
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
id: 'focAndOp',
|
|
434
|
+
what: 'Tab-focusable elements that are not operable or vice versa',
|
|
435
|
+
contaminates: true,
|
|
436
|
+
needsAccessibleName: false,
|
|
437
|
+
local: false,
|
|
438
|
+
timeOut: 5,
|
|
439
|
+
defaultOn: true
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
id: 'focInd',
|
|
443
|
+
what: 'missing and nonstandard focus indicators',
|
|
444
|
+
contaminates: true,
|
|
445
|
+
needsAccessibleName: false,
|
|
446
|
+
local: false,
|
|
447
|
+
timeOut: 10,
|
|
448
|
+
defaultOn: true
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: 'focVis',
|
|
452
|
+
what: 'links that are not entirely visible when focused',
|
|
453
|
+
contaminates: true,
|
|
454
|
+
needsAccessibleName: false,
|
|
455
|
+
local: false,
|
|
456
|
+
timeOut: 10,
|
|
457
|
+
defaultOn: true
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
id: 'hover',
|
|
461
|
+
what: 'hover-caused content changes',
|
|
462
|
+
contaminates: true,
|
|
463
|
+
needsAccessibleName: false,
|
|
464
|
+
local: false,
|
|
465
|
+
timeOut: 20,
|
|
466
|
+
defaultOn: true
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
id: 'hovInd',
|
|
470
|
+
what: 'hover indication nonstandard',
|
|
471
|
+
contaminates: true,
|
|
472
|
+
needsAccessibleName: false,
|
|
473
|
+
local: false,
|
|
474
|
+
timeOut: 10,
|
|
475
|
+
defaultOn: true
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
id: 'tabNav',
|
|
479
|
+
what: 'nonstandard keyboard navigation between elements with the tab role',
|
|
480
|
+
contaminates: true,
|
|
481
|
+
needsAccessibleName: false,
|
|
482
|
+
local: false,
|
|
483
|
+
timeOut: 10,
|
|
484
|
+
defaultOn: true
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
id: 'textNodes',
|
|
488
|
+
what: 'data on specified text nodes',
|
|
489
|
+
contaminates: true,
|
|
490
|
+
needsAccessibleName: false,
|
|
491
|
+
local: false,
|
|
492
|
+
timeOut: 10,
|
|
493
|
+
defaultOn: false
|
|
494
|
+
}
|
|
438
495
|
];
|
|
439
|
-
|
|
440
496
|
// ERROR HANDLER
|
|
441
497
|
process.on('unhandledRejection', reason => {
|
|
442
|
-
|
|
498
|
+
console.error(`ERROR: Unhandled Promise Rejection (${reason})`);
|
|
443
499
|
});
|
|
444
|
-
|
|
445
500
|
// FUNCTIONS
|
|
446
|
-
|
|
447
501
|
// Conducts and reports Testaro tests.
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
instances: []
|
|
502
|
+
const reporter = async (page, report, actIndex) => {
|
|
503
|
+
const act = report.acts[actIndex];
|
|
504
|
+
const givenPage = page;
|
|
505
|
+
const { args, stopOnFail, withItems } = act;
|
|
506
|
+
// A testaro act always has a target on itself or the report; verbatim from the original.
|
|
507
|
+
const target = (act.target || report.target);
|
|
508
|
+
const url = target.url;
|
|
509
|
+
const browserID = act.launch ? act.launch.browserID || report.browserID : report.browserID;
|
|
510
|
+
const argRules = args ? Object.keys(args) : null;
|
|
511
|
+
// Get the specification of rules to be tested for or, by default, all rules with defaultOn true.
|
|
512
|
+
const ruleSpec = act.rules
|
|
513
|
+
|| ['y', ...allRules.filter(rule => rule.defaultOn).map(rule => rule.id)];
|
|
514
|
+
// Initialize the act data.
|
|
515
|
+
const data = {
|
|
516
|
+
prevented: false,
|
|
517
|
+
error: '',
|
|
518
|
+
rulePreventions: {},
|
|
519
|
+
rulesInvalid: [],
|
|
520
|
+
ruleTestTimes: [],
|
|
521
|
+
ruleData: {}
|
|
522
|
+
};
|
|
523
|
+
// The changed subtree roots the act is scoped to, if any (report.scope, set by the acts loop).
|
|
524
|
+
const scopeRoots = report.scope?.roots ?? null;
|
|
525
|
+
if (scopeRoots) {
|
|
526
|
+
data.scope = { localRules: [], pageRules: [] };
|
|
474
527
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
528
|
+
// Initialize the act result.
|
|
529
|
+
const result = {
|
|
530
|
+
nativeResult: {},
|
|
531
|
+
standardResult: (0, standard_1.getStandardResult)()
|
|
532
|
+
};
|
|
533
|
+
const { standardResult } = result;
|
|
534
|
+
const allRuleIDs = allRules.map(rule => rule.id);
|
|
535
|
+
if (
|
|
479
536
|
// If the rule specification has at least 2 items
|
|
480
537
|
ruleSpec.length > 1
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
538
|
+
// and the first item is y or n
|
|
539
|
+
&& ['y', 'n'].includes(ruleSpec[0])
|
|
540
|
+
// and all subsequent items are rule IDs to be included (if y) or excluded (if n):
|
|
541
|
+
&& ruleSpec.slice(1).every(ruleID => allRuleIDs.includes(ruleID))) {
|
|
542
|
+
// Get the rules to be tested for and their execution order.
|
|
543
|
+
const excludeIDs = ruleSpec.slice(1);
|
|
544
|
+
const jobRuleIDs = ruleSpec[0] === 'y'
|
|
545
|
+
? excludeIDs
|
|
546
|
+
: allRules
|
|
547
|
+
.filter(rule => rule.defaultOn && !excludeIDs.includes(rule.id))
|
|
548
|
+
.map(rule => rule.id);
|
|
549
|
+
const jobRules = allRules.filter(rule => jobRuleIDs.includes(rule.id));
|
|
550
|
+
let justPrevented = false;
|
|
551
|
+
// For each rule to be tested for:
|
|
552
|
+
for (let ruleIndex = 0; ruleIndex < jobRules.length; ruleIndex++) {
|
|
553
|
+
const rule = jobRules[ruleIndex];
|
|
554
|
+
// Initialize the rule result.
|
|
555
|
+
const ruleResult = {
|
|
556
|
+
id: rule.id,
|
|
557
|
+
prevented: false,
|
|
558
|
+
error: '',
|
|
559
|
+
data: {},
|
|
560
|
+
totals: [0, 0, 0, 0],
|
|
561
|
+
instances: [],
|
|
562
|
+
elapsedTime: 0
|
|
563
|
+
};
|
|
564
|
+
console.log(`Starting rule ${ruleResult.id}`);
|
|
565
|
+
// Make the browser emulate headedness in all cases, because performance does not suffer.
|
|
566
|
+
const headEmulation = ruleResult.id.startsWith('shoot') ? 'high' : 'high';
|
|
567
|
+
// Get whether the rule needs a new browser launched. Under page isolation the first rules
|
|
568
|
+
// run on the live page provided; a contaminating rule still gets a fresh page.
|
|
569
|
+
const previousRule = ruleIndex > 0 ? jobRules[ruleIndex - 1] : null;
|
|
570
|
+
const needsLaunch = (ruleIndex === 0 && !(page && report.jobData?.isolation === 'page'))
|
|
571
|
+
|| justPrevented
|
|
572
|
+
|| Boolean(previousRule?.contaminates)
|
|
573
|
+
|| jobRules[ruleIndex].needsAccessibleName && !previousRule?.needsAccessibleName
|
|
574
|
+
&& !(ruleIndex === 0 && page);
|
|
575
|
+
const pageClosed = page && page.isClosed();
|
|
576
|
+
// If it does, or if the page has closed:
|
|
577
|
+
if (needsLaunch || pageClosed) {
|
|
578
|
+
// If the page has closed when it is expected to be open:
|
|
579
|
+
if (pageClosed && !needsLaunch) {
|
|
580
|
+
// Report this.
|
|
581
|
+
console.log(`WARNING: Relaunching browser for test ${rule} after abnormal closure`);
|
|
582
|
+
}
|
|
583
|
+
// Create a browser, replace the page, and visit the target, retrying twice if necessary.
|
|
584
|
+
page = await (0, launch_1.launch)({
|
|
585
|
+
report,
|
|
586
|
+
actIndex,
|
|
587
|
+
tempBrowserID: browserID,
|
|
588
|
+
tempURL: url,
|
|
589
|
+
headEmulation,
|
|
590
|
+
xPathNeed: 'script',
|
|
591
|
+
needsAccessibleName: jobRules[ruleIndex].needsAccessibleName,
|
|
592
|
+
retries: Number.isInteger(act.retries) && act.retries >= 0
|
|
593
|
+
? act.retries
|
|
594
|
+
: config_1.ruleLaunchRetries
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
// If no page exists, the launch (or the replay of a checkpoint's acts) failed: the
|
|
598
|
+
// target is unreachable, so prevent the act and stop testing rules.
|
|
599
|
+
if (!page) {
|
|
600
|
+
const message = String(report.jobData?.abortMessage
|
|
601
|
+
|| `Launch or checkpoint replay failed before rule ${ruleResult.id}`);
|
|
602
|
+
ruleResult.prevented = true;
|
|
603
|
+
ruleResult.error = message;
|
|
604
|
+
data.rulePreventions[ruleResult.id] = message;
|
|
605
|
+
data.prevented = true;
|
|
606
|
+
data.error = message;
|
|
607
|
+
standardResult.prevented = true;
|
|
608
|
+
console.log(`ERROR: ${message}`);
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
// Report crashes and disconnections during this test.
|
|
612
|
+
let crashHandler;
|
|
613
|
+
let disconnectHandler;
|
|
614
|
+
if (page && !page.isClosed()) {
|
|
615
|
+
crashHandler = () => {
|
|
616
|
+
console.log(`ERROR: Page crashed during ${rule} test`);
|
|
617
|
+
};
|
|
618
|
+
page.on('crash', crashHandler);
|
|
619
|
+
}
|
|
620
|
+
// The page exists whenever this runs; verbatim from the original.
|
|
621
|
+
const browser = page.context().browser();
|
|
622
|
+
if (browser) {
|
|
623
|
+
disconnectHandler = () => {
|
|
624
|
+
console.log(`ERROR: Browser disconnected during ${rule} test`);
|
|
625
|
+
};
|
|
626
|
+
browser.on('disconnected', disconnectHandler);
|
|
627
|
+
}
|
|
628
|
+
// Restrict an element-local rule to the scope roots; a page-level rule tests the page.
|
|
629
|
+
if (scopeRoots) {
|
|
630
|
+
report.ruleScopeRoots = rule.local ? scopeRoots : null;
|
|
631
|
+
(rule.local ? data.scope.localRules : data.scope.pageRules).push(rule.id);
|
|
632
|
+
}
|
|
633
|
+
// Initialize an argument array for the reporter.
|
|
634
|
+
const ruleArgs = [page, report, actIndex, withItems];
|
|
635
|
+
// If the rule needs a temporary directory:
|
|
636
|
+
if (rule.needsTmpDir) {
|
|
637
|
+
// Add its path to the argument array.
|
|
638
|
+
ruleArgs.push(report.jobData.tmpDir);
|
|
639
|
+
}
|
|
640
|
+
// If the testaro test act specifies extra arguments for this rule:
|
|
641
|
+
if (argRules?.includes(ruleResult.id)) {
|
|
642
|
+
// Add them to the argument array.
|
|
643
|
+
ruleArgs.push(...args[ruleResult.id]);
|
|
644
|
+
}
|
|
645
|
+
const startTime = Date.now();
|
|
646
|
+
let timer;
|
|
647
|
+
try {
|
|
648
|
+
// Apply a time limit to the test.
|
|
649
|
+
const timeLimit = (0, config_1.applyMultiplier)(1000 * rule.timeOut);
|
|
650
|
+
let timeout;
|
|
651
|
+
// If the time limit expires during the test:
|
|
652
|
+
timer = new Promise(resolve => {
|
|
653
|
+
timeout = setTimeout(() => {
|
|
654
|
+
// Add data about the timeout to the rule result.
|
|
655
|
+
justPrevented = true;
|
|
656
|
+
ruleResult.prevented = true;
|
|
657
|
+
ruleResult.error = 'Timeout';
|
|
658
|
+
console.log(`ERROR: Test of testaro rule ${ruleResult.id} timed out`);
|
|
659
|
+
resolve({ timedOut: true });
|
|
660
|
+
}, timeLimit);
|
|
661
|
+
});
|
|
662
|
+
// Try to perform the test and get a test report, loading the rule via the registry.
|
|
663
|
+
// The RuleModule cast widens the per-rule signature union to the registry contract.
|
|
664
|
+
const testReport = registry_1.ruleModules[ruleResult.id]().reporter(...ruleArgs);
|
|
665
|
+
// Get a test or timeout report.
|
|
666
|
+
const ruleReport = await Promise.race([timer, testReport]);
|
|
667
|
+
clearTimeout(timeout);
|
|
668
|
+
// If it was a test report:
|
|
669
|
+
if (!ruleReport.timedOut) {
|
|
670
|
+
// Add the rule-report properties to the rule result.
|
|
671
|
+
ruleResult.data = ruleReport.data;
|
|
672
|
+
ruleResult.totals = ruleReport.totals;
|
|
673
|
+
ruleResult.instances = ruleReport.standardInstances;
|
|
674
|
+
// Add the rule-result properties to the result.
|
|
675
|
+
if (Object.keys(ruleReport.data).length) {
|
|
676
|
+
data.ruleData[ruleResult.id] = ruleResult.data;
|
|
677
|
+
}
|
|
678
|
+
if (ruleResult.totals) {
|
|
679
|
+
ruleResult.totals.forEach((total, index) => {
|
|
680
|
+
standardResult.totals[index] += Math.round(total);
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
if (ruleResult.instances?.length) {
|
|
684
|
+
// Apply the rule's default outcome to instances without their own.
|
|
685
|
+
ruleResult.instances.forEach(instance => {
|
|
686
|
+
instance.outcome ??= rule.outcome ?? 'failed';
|
|
687
|
+
if (instance.outcome === 'cantTell' && rule.uncertainty) {
|
|
688
|
+
instance.uncertainty ??= rule.uncertainty;
|
|
689
|
+
}
|
|
690
|
+
standardResult.outcomeTotals[instance.outcome] += instance.count || 1;
|
|
691
|
+
});
|
|
692
|
+
standardResult.instances.push(...ruleResult.instances);
|
|
693
|
+
}
|
|
694
|
+
justPrevented = false;
|
|
695
|
+
// If testing is to stop after a failure and the page failed the test:
|
|
696
|
+
if (stopOnFail && ruleReport.totals?.some(total => total)) {
|
|
697
|
+
// Test for no more rules.
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
// If an error is thrown by the test:
|
|
703
|
+
catch (error) {
|
|
704
|
+
ruleResult.prevented = true;
|
|
705
|
+
justPrevented = true;
|
|
706
|
+
const isPageClosed = ['closed', 'Protocol error', 'Target page'].some(phrase => error.message.includes(phrase));
|
|
707
|
+
// If the page has closed:
|
|
708
|
+
if (isPageClosed) {
|
|
709
|
+
// Report this.
|
|
710
|
+
console.log(`ERROR: Test ${ruleResult.id} failed because page closed`);
|
|
711
|
+
}
|
|
712
|
+
// Otherwise, i.e. if the page is open:
|
|
713
|
+
else {
|
|
714
|
+
// Add this to the rule result.
|
|
715
|
+
ruleResult.error = error.message;
|
|
716
|
+
console.log(`ERROR: Test of testaro rule ${ruleResult.id} prevented (${error.message})`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
finally {
|
|
720
|
+
// Add the elapsed time to the rule result.
|
|
721
|
+
ruleResult.elapsedTime = Math.round((Date.now() - startTime) / 1000);
|
|
722
|
+
// Add the elapsed time to the data.
|
|
723
|
+
data.ruleTestTimes.push([ruleResult.id, ruleResult.elapsedTime]);
|
|
724
|
+
// If the test timed out or otherwise failed:
|
|
725
|
+
if (ruleResult.prevented) {
|
|
726
|
+
// Add this and the error to the data.
|
|
727
|
+
data.rulePreventions[ruleResult.id] = ruleResult.error;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
// Sort the rule test times.
|
|
731
|
+
data.ruleTestTimes.sort((a, b) => b[1] - a[1]);
|
|
732
|
+
// Clear the error listeners.
|
|
733
|
+
if (page && !page.isClosed() && crashHandler) {
|
|
734
|
+
page.off('crash', crashHandler);
|
|
735
|
+
crashHandler = null;
|
|
736
|
+
}
|
|
737
|
+
if (browser && disconnectHandler) {
|
|
738
|
+
browser.off('disconnected', disconnectHandler);
|
|
739
|
+
disconnectHandler = null;
|
|
740
|
+
}
|
|
741
|
+
// Force a garbage collection.
|
|
742
|
+
try {
|
|
743
|
+
if (global.gc) {
|
|
744
|
+
global.gc();
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
catch (error) { }
|
|
623
748
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
// Sort the rule test times.
|
|
645
|
-
data.ruleTestTimes.sort((a, b) => b[1] - a[1]);
|
|
646
|
-
// Clear the error listeners.
|
|
647
|
-
if (page && ! page.isClosed() && crashHandler) {
|
|
648
|
-
page.off('crash', crashHandler);
|
|
649
|
-
crashHandler = null;
|
|
650
|
-
}
|
|
651
|
-
if (browser && disconnectHandler) {
|
|
652
|
-
browser.off('disconnected', disconnectHandler);
|
|
653
|
-
disconnectHandler = null;
|
|
654
|
-
}
|
|
655
|
-
// Force a garbage collection.
|
|
656
|
-
try {
|
|
657
|
-
if (global.gc) {
|
|
658
|
-
global.gc();
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
catch(error) {}
|
|
749
|
+
;
|
|
750
|
+
}
|
|
751
|
+
// Otherwise, i.e. if the rule specification is invalid:
|
|
752
|
+
else {
|
|
753
|
+
// Report this and stop testing.
|
|
754
|
+
standardResult.prevented = true;
|
|
755
|
+
data.prevented = true;
|
|
756
|
+
const message = 'ERROR: Testaro rule specification invalid';
|
|
757
|
+
data.error = message;
|
|
758
|
+
console.log(message);
|
|
759
|
+
}
|
|
760
|
+
// Close the last page the tool launched, unless it is the live page it was given.
|
|
761
|
+
if (page && page !== givenPage) {
|
|
762
|
+
await (0, launch_1.browserClose)(page);
|
|
763
|
+
}
|
|
764
|
+
delete report.ruleScopeRoots;
|
|
765
|
+
return {
|
|
766
|
+
data,
|
|
767
|
+
result
|
|
662
768
|
};
|
|
663
|
-
}
|
|
664
|
-
// Otherwise, i.e. if the rule specification is invalid:
|
|
665
|
-
else {
|
|
666
|
-
// Report this and stop testing.
|
|
667
|
-
standardResult.prevented = true;
|
|
668
|
-
data.prevented = true;
|
|
669
|
-
const message = 'ERROR: Testaro rule specification invalid';
|
|
670
|
-
data.error = message;
|
|
671
|
-
console.log(message);
|
|
672
|
-
}
|
|
673
|
-
return {
|
|
674
|
-
data,
|
|
675
|
-
result
|
|
676
|
-
};
|
|
677
769
|
};
|
|
770
|
+
exports.reporter = reporter;
|