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.
Files changed (356) 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 +24 -18
  7. package/CONTAINERS.md +9 -6
  8. package/CONTRIBUTING.md +29 -3
  9. package/Dockerfile +1 -1
  10. package/README.md +73 -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/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 +372 -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 +312 -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 +62 -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/job.js +115 -1
  38. package/procs/launch.d.ts +40 -0
  39. package/procs/launch.js +239 -108
  40. package/procs/nu.d.ts +48 -0
  41. package/procs/scope.js +196 -0
  42. package/procs/shoot.d.ts +33 -0
  43. package/procs/standard.d.ts +18 -0
  44. package/procs/standard.js +83 -0
  45. package/procs/standard.ts +126 -0
  46. package/procs/testAct.js +145 -0
  47. package/procs/testaro.d.ts +20 -0
  48. package/procs/testaro.js +236 -189
  49. package/procs/testaro.ts +321 -0
  50. package/procs/userPath.js +126 -0
  51. package/procs/xPath.d.ts +4 -0
  52. package/procs/xPath.js +81 -69
  53. package/procs/xPath.ts +106 -0
  54. package/procs/xPathScript.d.ts +6 -0
  55. package/procs/xPathScript.js +70 -0
  56. package/run.js +3 -2
  57. package/surea11y/README.md +44 -0
  58. package/surea11y/surea11y.browser.js +14 -0
  59. package/testaro/adbID.d.ts +3 -0
  60. package/testaro/adbID.js +38 -41
  61. package/testaro/adbID.ts +66 -0
  62. package/testaro/allCapStyle.d.ts +3 -0
  63. package/testaro/allCapStyle.js +31 -34
  64. package/testaro/allCapStyle.ts +55 -0
  65. package/testaro/allCaps.d.ts +16 -0
  66. package/testaro/allCaps.js +179 -151
  67. package/testaro/allCaps.ts +228 -0
  68. package/testaro/allHidden.d.ts +13 -0
  69. package/testaro/allHidden.js +29 -30
  70. package/testaro/allHidden.ts +50 -0
  71. package/testaro/allSlanted.d.ts +3 -0
  72. package/testaro/allSlanted.js +30 -33
  73. package/testaro/allSlanted.ts +54 -0
  74. package/testaro/altScheme.d.ts +3 -0
  75. package/testaro/altScheme.js +27 -30
  76. package/testaro/altScheme.ts +50 -0
  77. package/testaro/attVal.d.ts +3 -0
  78. package/testaro/attVal.js +20 -21
  79. package/testaro/attVal.ts +52 -0
  80. package/testaro/autocomplete.d.ts +3 -0
  81. package/testaro/autocomplete.js +59 -75
  82. package/testaro/autocomplete.ts +101 -0
  83. package/testaro/bulk.d.ts +13 -0
  84. package/testaro/bulk.js +32 -33
  85. package/testaro/bulk.ts +55 -0
  86. package/testaro/buttonMenu.d.ts +9 -0
  87. package/testaro/buttonMenu.js +317 -319
  88. package/testaro/buttonMenu.ts +391 -0
  89. package/testaro/captionLoc.d.ts +3 -0
  90. package/testaro/captionLoc.js +17 -20
  91. package/testaro/captionLoc.ts +40 -0
  92. package/testaro/datalistRef.d.ts +3 -0
  93. package/testaro/datalistRef.js +33 -36
  94. package/testaro/datalistRef.ts +55 -0
  95. package/testaro/distortion.d.ts +3 -0
  96. package/testaro/distortion.js +57 -26
  97. package/testaro/distortion.ts +81 -0
  98. package/testaro/docType.d.ts +15 -0
  99. package/testaro/docType.js +25 -25
  100. package/testaro/docType.ts +45 -0
  101. package/testaro/dupAtt.d.ts +16 -0
  102. package/testaro/dupAtt.js +113 -104
  103. package/testaro/dupAtt.ts +144 -0
  104. package/testaro/elements.d.ts +6 -0
  105. package/testaro/elements.js +153 -153
  106. package/testaro/elements.ts +215 -0
  107. package/testaro/embAc.d.ts +3 -0
  108. package/testaro/embAc.js +19 -20
  109. package/testaro/embAc.ts +40 -0
  110. package/testaro/focAll.d.ts +13 -0
  111. package/testaro/focAll.js +185 -191
  112. package/testaro/focAll.ts +217 -0
  113. package/testaro/focAndOp.d.ts +3 -0
  114. package/testaro/focAndOp.js +100 -104
  115. package/testaro/focAndOp.ts +128 -0
  116. package/testaro/focInd.d.ts +3 -0
  117. package/testaro/focInd.js +64 -66
  118. package/testaro/focInd.ts +96 -0
  119. package/testaro/focVis.d.ts +3 -0
  120. package/testaro/focVis.js +28 -30
  121. package/testaro/focVis.ts +52 -0
  122. package/testaro/headEl.d.ts +10 -0
  123. package/testaro/headEl.js +61 -62
  124. package/testaro/headEl.ts +82 -0
  125. package/testaro/headingAmb.d.ts +3 -0
  126. package/testaro/headingAmb.js +54 -63
  127. package/testaro/headingAmb.ts +72 -0
  128. package/testaro/hovInd.d.ts +12 -0
  129. package/testaro/hovInd.js +163 -130
  130. package/testaro/hovInd.ts +199 -0
  131. package/testaro/hover.d.ts +3 -0
  132. package/testaro/hover.js +155 -126
  133. package/testaro/hover.ts +154 -0
  134. package/testaro/hr.d.ts +3 -0
  135. package/testaro/hr.js +14 -17
  136. package/testaro/hr.ts +36 -0
  137. package/testaro/imageLink.d.ts +3 -0
  138. package/testaro/imageLink.js +17 -20
  139. package/testaro/imageLink.ts +42 -0
  140. package/testaro/labClash.d.ts +3 -0
  141. package/testaro/labClash.js +31 -33
  142. package/testaro/labClash.ts +54 -0
  143. package/testaro/legendLoc.d.ts +3 -0
  144. package/testaro/legendLoc.js +17 -20
  145. package/testaro/legendLoc.ts +42 -0
  146. package/testaro/lineHeight.d.ts +3 -0
  147. package/testaro/lineHeight.js +43 -48
  148. package/testaro/lineHeight.ts +70 -0
  149. package/testaro/linkAmb.d.ts +7 -0
  150. package/testaro/linkAmb.js +79 -80
  151. package/testaro/linkAmb.ts +105 -0
  152. package/testaro/linkExt.d.ts +3 -0
  153. package/testaro/linkExt.js +13 -16
  154. package/testaro/linkExt.ts +35 -0
  155. package/testaro/linkOldAtt.d.ts +3 -0
  156. package/testaro/linkOldAtt.js +25 -28
  157. package/testaro/linkOldAtt.ts +48 -0
  158. package/testaro/linkTo.d.ts +3 -0
  159. package/testaro/linkTo.js +22 -22
  160. package/testaro/linkTo.ts +43 -0
  161. package/testaro/linkUl.d.ts +3 -0
  162. package/testaro/linkUl.js +30 -34
  163. package/testaro/linkUl.ts +54 -0
  164. package/testaro/miniText.d.ts +3 -0
  165. package/testaro/miniText.js +41 -44
  166. package/testaro/miniText.ts +68 -0
  167. package/testaro/motion.d.ts +10 -0
  168. package/testaro/motion.js +92 -96
  169. package/testaro/motion.ts +125 -0
  170. package/testaro/nonTable.d.ts +3 -0
  171. package/testaro/nonTable.js +39 -45
  172. package/testaro/nonTable.ts +66 -0
  173. package/testaro/optRoleSel.d.ts +3 -0
  174. package/testaro/optRoleSel.js +16 -19
  175. package/testaro/optRoleSel.ts +41 -0
  176. package/testaro/phOnly.d.ts +3 -0
  177. package/testaro/phOnly.js +18 -21
  178. package/testaro/phOnly.ts +43 -0
  179. package/testaro/pseudoP.d.ts +3 -0
  180. package/testaro/pseudoP.js +36 -38
  181. package/testaro/pseudoP.ts +59 -0
  182. package/testaro/radioSet.d.ts +3 -0
  183. package/testaro/radioSet.js +57 -59
  184. package/testaro/radioSet.ts +79 -0
  185. package/testaro/registry.d.ts +63 -0
  186. package/testaro/registry.js +67 -0
  187. package/testaro/registry.ts +141 -0
  188. package/testaro/role.d.ts +3 -0
  189. package/testaro/role.js +27 -29
  190. package/testaro/role.ts +53 -0
  191. package/testaro/secHeading.d.ts +3 -0
  192. package/testaro/secHeading.js +30 -33
  193. package/testaro/secHeading.ts +53 -0
  194. package/testaro/styleDiff.d.ts +25 -0
  195. package/testaro/styleDiff.js +248 -252
  196. package/testaro/styleDiff.ts +303 -0
  197. package/testaro/tabNav.d.ts +33 -0
  198. package/testaro/tabNav.js +272 -342
  199. package/testaro/tabNav.ts +454 -0
  200. package/testaro/targetsNear.d.ts +9 -0
  201. package/testaro/targetsNear.js +130 -132
  202. package/testaro/targetsNear.ts +160 -0
  203. package/testaro/textNodes.d.ts +6 -0
  204. package/testaro/textNodes.js +139 -135
  205. package/testaro/textNodes.ts +185 -0
  206. package/testaro/textSem.d.ts +3 -0
  207. package/testaro/textSem.js +25 -28
  208. package/testaro/textSem.ts +47 -0
  209. package/testaro/title.d.ts +9 -0
  210. package/testaro/title.js +16 -13
  211. package/testaro/title.ts +31 -0
  212. package/testaro/titledEl.d.ts +3 -0
  213. package/testaro/titledEl.js +15 -18
  214. package/testaro/titledEl.ts +38 -0
  215. package/testaro/zIndex.d.ts +3 -0
  216. package/testaro/zIndex.js +19 -22
  217. package/testaro/zIndex.ts +42 -0
  218. package/tests/alfa.d.ts +45 -0
  219. package/tests/alfa.js +138 -141
  220. package/tests/alfa.ts +214 -0
  221. package/tests/aslint.d.ts +33 -0
  222. package/tests/aslint.js +272 -249
  223. package/tests/aslint.ts +301 -0
  224. package/tests/axe.d.ts +27 -0
  225. package/tests/axe.js +199 -200
  226. package/tests/axe.ts +277 -0
  227. package/tests/ed11y.d.ts +28 -0
  228. package/tests/ed11y.js +141 -99
  229. package/tests/ed11y.ts +178 -0
  230. package/tests/htmlcs.d.ts +21 -0
  231. package/tests/htmlcs.js +174 -140
  232. package/tests/htmlcs.ts +181 -0
  233. package/tests/ibm.d.ts +52 -0
  234. package/tests/ibm.js +164 -166
  235. package/tests/ibm.ts +251 -0
  236. package/tests/nuVal.d.ts +13 -0
  237. package/tests/nuVal.js +107 -112
  238. package/tests/nuVal.ts +145 -0
  239. package/tests/nuVnu.d.ts +15 -0
  240. package/tests/nuVnu.js +141 -111
  241. package/tests/nuVnu.ts +144 -0
  242. package/tests/pour.d.ts +31 -0
  243. package/tests/pour.js +242 -0
  244. package/tests/pour.ts +273 -0
  245. package/tests/qualWeb.d.ts +39 -0
  246. package/tests/qualWeb.js +302 -272
  247. package/tests/qualWeb.ts +415 -0
  248. package/tests/surea11y.d.ts +33 -0
  249. package/tests/surea11y.js +288 -0
  250. package/tests/surea11y.ts +334 -0
  251. package/tests/testaro.d.ts +25 -0
  252. package/tests/testaro.js +745 -652
  253. package/tests/testaro.ts +862 -0
  254. package/tests/wave.d.ts +46 -0
  255. package/tests/wave.js +166 -177
  256. package/tests/wave.ts +252 -0
  257. package/tsconfig.json +17 -0
  258. package/types.d.ts +243 -0
  259. package/types.js +10 -0
  260. package/types.ts +376 -0
  261. package/validation/act/README.md +46 -0
  262. package/validation/act/capture.js +424 -0
  263. package/validation/act/chromium-issue-draft.md +66 -0
  264. package/validation/act/fp-triage-2026-08-22.md +86 -0
  265. package/validation/act/isolation-notes.md +159 -0
  266. package/validation/act/playwright-issue-draft.md +73 -0
  267. package/validation/act/propose-mappings.js +0 -0
  268. package/validation/act/repro-cdp-raw.js +105 -0
  269. package/validation/act/repro-metarefresh.js +65 -0
  270. package/validation/act/score.js +184 -0
  271. package/validation/act/stage3a-stress-report.md +69 -0
  272. package/validation/act/stage3b-mapping-proposals.md +94 -0
  273. package/validation/act/stage3b-triage-draft.md +138 -0
  274. package/validation/act/surea11y-track-a-2026-09-01.md +50 -0
  275. package/validation/executors/netWatch.js +180 -90
  276. package/validation/executors/test.js +17 -2
  277. package/validation/executors/tests.js +118 -10
  278. package/validation/jobs/reports/raw/260901T1000-surea11y-validation.json +964 -0
  279. package/validation/jobs/todo/240101T1200-simple-example.json +14 -6
  280. package/validation/jobs/todo/240101T1300-shoot-example.json +2 -1
  281. package/validation/jobs/todo/260821T1900-pour-validation.json +45 -0
  282. package/validation/jobs/todo/260901T1000-surea11y-validation.json +45 -0
  283. package/validation/knownFailures.json +1 -0
  284. package/validation/tests/jobProperties/adbID.json +27 -2
  285. package/validation/tests/jobProperties/{focOp.json → allCapStyle.json} +56 -53
  286. package/validation/tests/jobProperties/allCaps.json +25 -0
  287. package/validation/tests/jobProperties/allHidden.json +133 -13
  288. package/validation/tests/jobProperties/allSlanted.json +3 -3
  289. package/validation/tests/jobProperties/altScheme.json +23 -8
  290. package/validation/tests/jobProperties/attVal.json +57 -57
  291. package/validation/tests/jobProperties/autocomplete.json +11 -1
  292. package/validation/tests/jobProperties/bulk.json +6 -1
  293. package/validation/tests/jobProperties/buttonMenu.json +63 -42
  294. package/validation/tests/jobProperties/captionLoc.json +1 -6
  295. package/validation/tests/jobProperties/checkpoint-browser.json +401 -0
  296. package/validation/tests/jobProperties/checkpoint-page.json +397 -0
  297. package/validation/tests/jobProperties/checkpoint.json +395 -0
  298. package/validation/tests/jobProperties/datalistRef.json +20 -5
  299. package/validation/tests/jobProperties/distortion.json +28 -3
  300. package/validation/tests/jobProperties/docType.json +2 -2
  301. package/validation/tests/jobProperties/dupAtt.json +48 -33
  302. package/validation/tests/jobProperties/elements.json +28 -28
  303. package/validation/tests/jobProperties/embAc.json +36 -31
  304. package/validation/tests/jobProperties/focAndOp.json +284 -0
  305. package/validation/tests/jobProperties/focInd.json +34 -34
  306. package/validation/tests/jobProperties/focVis.json +1 -1
  307. package/validation/tests/jobProperties/hover.json +39 -37
  308. package/validation/tests/jobProperties/hr.json +13 -3
  309. package/validation/tests/jobProperties/imageLink.json +0 -5
  310. package/validation/tests/jobProperties/labClash.json +68 -33
  311. package/validation/tests/jobProperties/legendLoc.json +1 -6
  312. package/validation/tests/jobProperties/lineHeight.json +2 -2
  313. package/validation/tests/jobProperties/linkAmb.json +13 -18
  314. package/validation/tests/jobProperties/linkExt.json +1 -1
  315. package/validation/tests/jobProperties/linkOldAtt.json +12 -2
  316. package/validation/tests/jobProperties/linkTo.json +1 -1
  317. package/validation/tests/jobProperties/linkUl.json +65 -65
  318. package/validation/tests/jobProperties/miniText.json +7 -2
  319. package/validation/tests/jobProperties/motion.json +4 -50
  320. package/validation/tests/jobProperties/nonTable.json +48 -3
  321. package/validation/tests/jobProperties/optRoleSel.json +12 -2
  322. package/validation/tests/jobProperties/phOnly.json +6 -16
  323. package/validation/tests/jobProperties/pseudoP.json +17 -2
  324. package/validation/tests/jobProperties/radioSet.json +30 -30
  325. package/validation/tests/jobProperties/role.json +25 -5
  326. package/validation/tests/jobProperties/secHeading.json +26 -21
  327. package/validation/tests/jobProperties/styleDiff.json +35 -5
  328. package/validation/tests/jobProperties/tabNav.json +3 -1
  329. package/validation/tests/jobProperties/targetsNear.json +237 -0
  330. package/validation/tests/jobProperties/textNodes.json +29 -29
  331. package/validation/tests/jobProperties/textSem.json +26 -1
  332. package/validation/tests/jobProperties/title.json +12 -2
  333. package/validation/tests/jobProperties/titledEl.json +39 -9
  334. package/validation/tests/jobProperties/userPath.json +317 -0
  335. package/validation/tests/jobProperties/zIndex.json +40 -35
  336. package/validation/tests/targets/allCapStyle/index.html +26 -0
  337. package/validation/tests/targets/checkpoint/index.html +38 -0
  338. package/validation/tests/targets/datalistRef/index.html +1 -1
  339. package/validation/tests/targets/focAndOp/bad.html +29 -0
  340. package/validation/tests/targets/{focOp → focAndOp}/good.html +3 -1
  341. package/validation/tests/targets/focInd/bad.html +2 -1
  342. package/validation/tests/targets/headEl/index.html +10 -1
  343. package/validation/tests/targets/{targetSmall → targetsNear}/index.html +15 -1
  344. package/validation/tests/targets/userPath/index.html +42 -0
  345. package/validation/validateTest.js +61 -9
  346. package/.claude/settings.local.json +0 -11
  347. package/.eslintrc.json +0 -41
  348. package/htmlcs/.eslintrc.json +0 -67
  349. package/validation/tests/jobProperties/linkTitle.json +0 -127
  350. package/validation/tests/jobProperties/opFoc.json +0 -164
  351. package/validation/tests/jobProperties/targetSmall.json +0 -152
  352. package/validation/tests/jobProperties/targetTiny.json +0 -142
  353. package/validation/tests/targets/focOp/bad.html +0 -25
  354. package/validation/tests/targets/linkTitle/index.html +0 -24
  355. package/validation/tests/targets/opFoc/bad.html +0 -26
  356. package/validation/tests/targets/opFoc/good.html +0 -23
package/tests/ed11y.ts ADDED
@@ -0,0 +1,178 @@
1
+ /*
2
+ © 2023–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
+ © 2026 Jeff Witt.
4
+ © 2025–2026 Jonathan Robert Pool.
5
+
6
+ Licensed under the MIT License. See LICENSE file at the project root or
7
+ https://opensource.org/license/mit/ for details.
8
+
9
+ SPDX-License-Identifier: MIT
10
+ */
11
+
12
+ // IMPORTS
13
+
14
+ import * as fs from 'fs/promises';
15
+ import type {Page} from 'playwright';
16
+ import {getXPathCatalogIndex} from '../procs/xPath';
17
+ import {getStandardResult, pushInstance} from '../procs/standard';
18
+ import type {Act, Report, SeverityTotals, StandardInstance, StandardResult} from '../types';
19
+
20
+ // TYPES
21
+
22
+ // The ed11y-act properties this reporter consumes.
23
+ interface Ed11yAct extends Act {
24
+ rules?: string[];
25
+ }
26
+ // One test result exposed by the Ed11y global.
27
+ interface Ed11yToolResult {
28
+ test: string;
29
+ content: string;
30
+ dismissalKey: string;
31
+ element: Element;
32
+ }
33
+ // One instance of the native result.
34
+ interface Ed11yNativeInstance {
35
+ test: string;
36
+ content: string;
37
+ dismissalKey: string;
38
+ html: string;
39
+ xPath: string | null | undefined;
40
+ }
41
+ // The native result: totals and instances, or a prevention report.
42
+ interface Ed11yNativeResult {
43
+ resultCount?: number;
44
+ errorCount?: number;
45
+ warningCount?: number;
46
+ results?: Ed11yNativeInstance[];
47
+ prevented?: boolean;
48
+ error?: string;
49
+ }
50
+
51
+ /*
52
+ The Ed11y global that the tool script defines in the page: a constructor whose
53
+ test results are exposed as static properties. Declared without a value, so
54
+ this declaration is erased at emit and the references inside the page.evaluate
55
+ callback remain bare page-global references.
56
+ */
57
+ declare const Ed11y: {
58
+ new (options: {alertMode: string}): unknown;
59
+ results: Ed11yToolResult[];
60
+ errorCount: number;
61
+ warningCount: number;
62
+ };
63
+
64
+ /*
65
+ ed11y
66
+ Implements the Editoria11y ruleset for accessibility.
67
+ Compiled to ed11y.js by tsc (issue #73); edit this file, not the emitted one.
68
+ */
69
+
70
+ // FUNCTIONS
71
+
72
+ // Performs and reports the Editoria11y tests.
73
+ export const reporter = async (page: Page, report: Report, actIndex: number) => {
74
+ // Get the nonce, if any.
75
+ const act = report.acts[actIndex] as Ed11yAct;
76
+ const {jobData} = report;
77
+ const scriptNonce = (jobData && jobData.lastScriptNonce) as string | undefined;
78
+ // Initialize the act report.
79
+ let data: {prevented?: boolean; error?: string} = {};
80
+ const result: {nativeResult: Ed11yNativeResult; standardResult: StandardResult} = {
81
+ nativeResult: {},
82
+ standardResult: {}
83
+ };
84
+ const standard = report.standard !== 'no';
85
+ // If standard results are to be reported:
86
+ if (standard) {
87
+ // Initialize the standard result.
88
+ result.standardResult = getStandardResult();
89
+ }
90
+ // Get the tool script.
91
+ const script = await fs.readFile(`${__dirname}/../ed11y/editoria11y.min.js`, 'utf8');
92
+ // Perform the specified tests and populate the native result.
93
+ result.nativeResult = await page.evaluate(args => new Promise<Ed11yNativeResult>(
94
+ async resolve => {
95
+ const {scriptNonce, script, rulesToTest} = args;
96
+ // When the script has been executed, creating data in an Ed11y object:
97
+ document.addEventListener('ed11yResults', async () => {
98
+ let {results} = Ed11y;
99
+ // If rules were selected:
100
+ if (rulesToTest) {
101
+ // Remove results of other rules.
102
+ results = results.filter(result => rulesToTest.includes(result.test));
103
+ }
104
+ // Return the native result.
105
+ resolve({
106
+ resultCount: results.length,
107
+ errorCount: Ed11y.errorCount,
108
+ warningCount: Ed11y.warningCount,
109
+ results: results.map(result => ({
110
+ test: result.test,
111
+ content: result.content.replace(/\s+/g, ' ').trim(),
112
+ dismissalKey: result.dismissalKey,
113
+ html: result.element.outerHTML.slice(0, 500),
114
+ xPath: window.getXPath(result.element)
115
+ }))
116
+ });
117
+ });
118
+ // Add the tool script to the page.
119
+ const toolScript = document.createElement('script');
120
+ if (scriptNonce) {
121
+ toolScript.nonce = scriptNonce;
122
+ console.log(`Added nonce ${scriptNonce} to tool script`);
123
+ }
124
+ toolScript.textContent = script;
125
+ document.body.insertAdjacentElement('beforeend', toolScript);
126
+ // Execute the tool script, creating Ed11y and triggering the event listener.
127
+ try {
128
+ await new Ed11y({
129
+ alertMode: 'headless'
130
+ });
131
+ }
132
+ catch(error) {
133
+ resolve({
134
+ prevented: true,
135
+ error: (error as Error).message
136
+ });
137
+ };
138
+ }
139
+ ), {
140
+ scriptNonce,
141
+ script,
142
+ rulesToTest: act.rules
143
+ });
144
+ // If the tool script failed to run:
145
+ if (result.nativeResult.prevented) {
146
+ // Report the prevention.
147
+ data.prevented = true;
148
+ data.error = result.nativeResult.error as string;
149
+ if (standard) {
150
+ result.standardResult.prevented = true;
151
+ }
152
+ }
153
+ // Otherwise, i.e. if it ran, and if a standard result is to be reported:
154
+ else if (standard) {
155
+ const {standardResult} = result;
156
+ const {warningCount, errorCount, results} = result.nativeResult as Required<Ed11yNativeResult>;
157
+ // Populate the standard-result totals.
158
+ standardResult.totals = [warningCount, 0, errorCount, 0] as SeverityTotals;
159
+ // For each native-result instance:
160
+ results.forEach(nativeInstance => {
161
+ // Create a standard-result instance.
162
+ const {test, content, dismissalKey, xPath} = nativeInstance;
163
+ // A dismissable warning is a manual check.
164
+ pushInstance(standardResult, {
165
+ ruleID: test,
166
+ what: content,
167
+ ordinalSeverity: dismissalKey ? 0 : 2,
168
+ outcome: dismissalKey ? 'cantTell' : 'failed',
169
+ uncertainty: dismissalKey ? 'judgement-required' : undefined,
170
+ catalogIndex: getXPathCatalogIndex(report, xPath as string)
171
+ });
172
+ });
173
+ }
174
+ return {
175
+ data,
176
+ result
177
+ };
178
+ };
@@ -0,0 +1,21 @@
1
+ import type { Page } from 'playwright';
2
+ import type { Report, StandardResult } from '../types';
3
+ interface HtmlcsNativeResult {
4
+ totals: {
5
+ failed: number;
6
+ cantTell: number;
7
+ };
8
+ error: string[][];
9
+ warning: string[][];
10
+ }
11
+ export declare const reporter: (page: Page, report: Report, actIndex: number) => Promise<{
12
+ data: {
13
+ prevented?: boolean;
14
+ error?: string;
15
+ };
16
+ result: {
17
+ nativeResult: HtmlcsNativeResult;
18
+ standardResult: StandardResult;
19
+ };
20
+ }>;
21
+ export {};
package/tests/htmlcs.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /*
2
3
  © 2022–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
4
  © 2026 Jeff Witt.
@@ -8,154 +9,187 @@
8
9
 
9
10
  SPDX-License-Identifier: MIT
10
11
  */
11
-
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.reporter = void 0;
47
+ // IMPORTS
48
+ const fs = __importStar(require("fs/promises"));
49
+ const xPath_1 = require("../procs/xPath");
50
+ const standard_1 = require("../procs/standard");
12
51
  /*
13
52
  htmlcs
14
53
  Implements the HTML CodeSniffer ruleset.
54
+ Compiled to htmlcs.js by tsc (issue #73); edit this file, not the emitted one.
15
55
  */
16
-
17
- // IMPORTS
18
-
19
- const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
20
- const fs = require('fs/promises');
21
-
22
56
  // FUNCTIONS
23
-
24
57
  // Conducts and reports the HTML CodeSniffer tests.
25
- exports.reporter = async (page, report, actIndex) => {
26
- const act = report.acts[actIndex];
27
- const {rules} = act;
28
- // Initialize the act report.
29
- const data = {};
30
- const result = {
31
- nativeResult: {
32
- totals: {
33
- failed: 0,
34
- cantTell: 0
35
- },
36
- error: [],
37
- warning: []
38
- },
39
- standardResult: {}
40
- };
41
- const standard = report.standard !== 'no';
42
- // If standard results are to be reported:
43
- if (standard) {
44
- // Initialize the standard result.
45
- result.standardResult = {
46
- prevented: false,
47
- totals: [0, 0, 0, 0],
48
- instances: []
58
+ const reporter = async (page, report, actIndex) => {
59
+ const act = report.acts[actIndex];
60
+ const { rules } = act;
61
+ // Initialize the act report.
62
+ const data = {};
63
+ const result = {
64
+ nativeResult: {
65
+ totals: {
66
+ failed: 0,
67
+ cantTell: 0
68
+ },
69
+ error: [],
70
+ warning: []
71
+ },
72
+ standardResult: {}
49
73
  };
50
- }
51
- const {nativeResult, standardResult} = result;
52
- // Get the HTMLCS script.
53
- const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
54
- const scriptNonce = report.jobData && report.jobData.lastScriptNonce;
55
- let messageStrings = [];
56
- // For each class of standards to be tested for:
57
- for (const actStandard of ['WCAG2AAA']) {
58
- const nextViolations = await page.evaluate(args => {
59
- const actStandard = args[0];
60
- const rules = args[1];
61
- const scriptText = args[2];
62
- const scriptNonce = args[3];
63
- const script = document.createElement('script');
64
- script.nonce = scriptNonce;
65
- script.textContent = scriptText;
66
- // HTMLCS.js is a UMD bundle. If the page exposes an AMD loader (define.amd, e.g. Wix or RequireJS) or leaked CommonJS globals (exports, module), the UMD wrapper registers HTMLCS as a module and never attaches HTMLCS_RUNNER to window, so the run() call below throws and the tool is reported prevented. Hide those loader globals for the duration of the synchronous script execution, so the wrapper falls through to its browser-global branch.
67
- const umdDefine = window.define;
68
- const umdExports = window.exports;
69
- const umdModule = window.module;
70
- window.define = undefined;
71
- window.exports = undefined;
72
- window.module = undefined;
73
- // Add the HTMLCS script to the page.
74
- document.head.insertAdjacentElement('beforeend', script);
75
- // Restore the loader globals.
76
- window.define = umdDefine;
77
- window.exports = umdExports;
78
- window.module = umdModule;
79
- // If only some rules are to be employed:
80
- if (rules && Array.isArray(rules) && rules.length) {
81
- // Redefine WCAG 2 AAA as including only them.
82
- if (! window.HTMLCS_WCAG2AAA) {
83
- window.HTMLCS_WCAG2AAA = {};
84
- }
85
- window.HTMLCS_WCAG2AAA.sniffs = rules;
86
- }
87
- let violations = null;
88
- // Run the tests.
89
- try {
90
- violations = window.HTMLCS_RUNNER.run(actStandard);
91
- }
92
- catch(error) {
93
- console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
94
- }
95
- // Return the reported violations of that standard.
96
- return violations;
97
- }, [actStandard, rules, scriptText, scriptNonce]);
98
- // If all reported violations of the standard are validly described:
99
- if (nextViolations?.every(violation => typeof violation === 'string')) {
100
- // Add their descriptions to the violation descriptions.
101
- messageStrings.push(... nextViolations);
74
+ const standard = report.standard !== 'no';
75
+ // If standard results are to be reported:
76
+ if (standard) {
77
+ // Initialize the standard result.
78
+ result.standardResult = (0, standard_1.getStandardResult)();
102
79
  }
103
- // Otherwise, i.e. if any reported violations are invalidly described:
104
- else {
105
- // Report this.
106
- data.prevented = true;
107
- data.error = 'ERROR executing HTMLCS_RUNNER in the page';
108
- break;
80
+ const { nativeResult, standardResult } = result;
81
+ // Get the HTMLCS script.
82
+ const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
83
+ const scriptNonce = (report.jobData && report.jobData.lastScriptNonce);
84
+ let messageStrings = [];
85
+ // For each class of standards to be tested for:
86
+ for (const actStandard of ['WCAG2AAA']) {
87
+ const nextViolations = await page.evaluate(args => {
88
+ const actStandard = args[0];
89
+ const rules = args[1];
90
+ const scriptText = args[2];
91
+ const scriptNonce = args[3];
92
+ const script = document.createElement('script');
93
+ script.nonce = scriptNonce;
94
+ script.textContent = scriptText;
95
+ // HTMLCS.js is a UMD bundle. If the page exposes an AMD loader (define.amd, e.g. Wix or RequireJS) or leaked CommonJS globals (exports, module), the UMD wrapper registers HTMLCS as a module and never attaches HTMLCS_RUNNER to window, so the run() call below throws and the tool is reported prevented. Hide those loader globals for the duration of the synchronous script execution, so the wrapper falls through to its browser-global branch.
96
+ const umdDefine = window.define;
97
+ const umdExports = window.exports;
98
+ const umdModule = window.module;
99
+ window.define = undefined;
100
+ window.exports = undefined;
101
+ // The cast erases; window.module otherwise types as Node's module global.
102
+ window.module = undefined;
103
+ // Add the HTMLCS script to the page.
104
+ document.head.insertAdjacentElement('beforeend', script);
105
+ // Restore the loader globals.
106
+ window.define = umdDefine;
107
+ window.exports = umdExports;
108
+ window.module = umdModule;
109
+ // If only some rules are to be employed:
110
+ if (rules && Array.isArray(rules) && rules.length) {
111
+ // Redefine WCAG 2 AAA as including only them.
112
+ if (!window.HTMLCS_WCAG2AAA) {
113
+ window.HTMLCS_WCAG2AAA = {};
114
+ }
115
+ window.HTMLCS_WCAG2AAA.sniffs = rules;
116
+ }
117
+ let violations = null;
118
+ // Run the tests.
119
+ try {
120
+ violations = window.HTMLCS_RUNNER.run(actStandard);
121
+ }
122
+ catch (error) {
123
+ console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
124
+ }
125
+ // Return the reported violations of that standard.
126
+ return violations;
127
+ }, [actStandard, rules, scriptText, scriptNonce]);
128
+ // If all reported violations of the standard are validly described:
129
+ if (nextViolations?.every(violation => typeof violation === 'string')) {
130
+ // Add their descriptions to the violation descriptions.
131
+ messageStrings.push(...nextViolations);
132
+ }
133
+ // Otherwise, i.e. if any reported violations are invalidly described:
134
+ else {
135
+ // Report this.
136
+ data.prevented = true;
137
+ data.error = 'ERROR executing HTMLCS_RUNNER in the page';
138
+ break;
139
+ }
109
140
  }
110
- }
111
- // If no error was thrown:
112
- if (! data.prevented) {
113
- // Sort the violations by class and standard.
114
- messageStrings.sort();
115
- // Remove any duplicate violations.
116
- messageStrings = [... new Set(messageStrings)];
117
- // For each violation:
118
- for (const string of messageStrings) {
119
- // Split its message into severity class, rule ID, tagname, ID, rule description, and excerpt.
120
- const parts = string.split(/\|/, 6);
121
- const partCount = parts.length;
122
- // If the message partitions are too few:
123
- if (partCount < 6) {
124
- // Report this.
125
- console.log(`ERROR: Violation string ${string} has too few parts`);
126
- }
127
- // Otherwise, if the message reports an error:
128
- else if (parts[0] === 'Error') {
129
- // Add the rest of its message to the native-result errors.
130
- nativeResult.error.push(parts.slice(1));
131
- // Increment the error total.
132
- nativeResult.totals.failed++;
133
- }
134
- // Otherwise, if the message reports a warning:
135
- else if (parts[0] === 'Warning') {
136
- // Add the rest of its message to the native-result warnings.
137
- nativeResult.warning.push(parts.slice(1));
138
- // Increment the warning total.
139
- nativeResult.totals.cantTell++;
140
- }
141
- // If standard results are to be reported and the message reports an error or warning:
142
- if (standard && ['Error', 'Warning'].includes(parts[0])) {
143
- const xPath = getAttributeXPath(parts[5]);
144
- const instance = {
145
- ruleID: `${parts[0][0]}-${parts[1]}`,
146
- what: parts[4],
147
- ordinalSeverity: parts[0] === 'Warning' ? 0 : 2,
148
- count: 1,
149
- catalogIndex: getXPathCatalogIndex(report, xPath)
150
- };
151
- standardResult.instances.push(instance);
152
- }
141
+ // If no error was thrown:
142
+ if (!data.prevented) {
143
+ // Sort the violations by class and standard.
144
+ messageStrings.sort();
145
+ // Remove any duplicate violations.
146
+ messageStrings = [...new Set(messageStrings)];
147
+ // For each violation:
148
+ for (const string of messageStrings) {
149
+ // Split its message into severity class, rule ID, tagname, ID, rule description, and excerpt.
150
+ const parts = string.split(/\|/, 6);
151
+ const partCount = parts.length;
152
+ // If the message partitions are too few:
153
+ if (partCount < 6) {
154
+ // Report this.
155
+ console.log(`ERROR: Violation string ${string} has too few parts`);
156
+ }
157
+ // Otherwise, if the message reports an error:
158
+ else if (parts[0] === 'Error') {
159
+ // Add the rest of its message to the native-result errors.
160
+ nativeResult.error.push(parts.slice(1));
161
+ // Increment the error total.
162
+ nativeResult.totals.failed++;
163
+ }
164
+ // Otherwise, if the message reports a warning:
165
+ else if (parts[0] === 'Warning') {
166
+ // Add the rest of its message to the native-result warnings.
167
+ nativeResult.warning.push(parts.slice(1));
168
+ // Increment the warning total.
169
+ nativeResult.totals.cantTell++;
170
+ }
171
+ // If standard results are to be reported and the message reports an error or warning:
172
+ if (standard && ['Error', 'Warning'].includes(parts[0])) {
173
+ const xPath = (0, xPath_1.getAttributeXPath)(parts[5]);
174
+ (0, standard_1.pushInstance)(standardResult, {
175
+ ruleID: `${parts[0][0]}-${parts[1]}`,
176
+ what: parts[4],
177
+ ordinalSeverity: parts[0] === 'Warning' ? 0 : 2,
178
+ outcome: parts[0] === 'Warning' ? 'cantTell' : 'failed',
179
+ catalogIndex: (0, xPath_1.getXPathCatalogIndex)(report, xPath)
180
+ });
181
+ }
182
+ }
183
+ // If standard results are to be reported:
184
+ if (standard) {
185
+ // Populate the standard-result totals.
186
+ standardResult.totals[0] = nativeResult.totals.cantTell;
187
+ standardResult.totals[2] = nativeResult.totals.failed;
188
+ }
153
189
  }
154
- standardResult.totals[0] = nativeResult.totals.cantTell;
155
- standardResult.totals[2] = nativeResult.totals.failed;
156
- }
157
- return {
158
- data,
159
- result
160
- };
190
+ return {
191
+ data,
192
+ result
193
+ };
161
194
  };
195
+ exports.reporter = reporter;