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