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