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
@@ -0,0 +1,181 @@
1
+ /*
2
+ © 2022–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 {getAttributeXPath, getXPathCatalogIndex} from '../procs/xPath';
17
+ import {getStandardResult, pushInstance} from '../procs/standard';
18
+ import type {Act, Report, StandardInstance, StandardResult} from '../types';
19
+
20
+ // TYPES
21
+
22
+ // The htmlcs-act properties this reporter consumes.
23
+ interface HtmlcsAct extends Act {
24
+ rules?: string[];
25
+ }
26
+ // The native result: violation totals and the parts of error and warning messages.
27
+ interface HtmlcsNativeResult {
28
+ totals: {
29
+ failed: number;
30
+ cantTell: number;
31
+ };
32
+ error: string[][];
33
+ warning: string[][];
34
+ }
35
+
36
+ /*
37
+ htmlcs
38
+ Implements the HTML CodeSniffer ruleset.
39
+ Compiled to htmlcs.js by tsc (issue #73); edit this file, not the emitted one.
40
+ */
41
+
42
+ // FUNCTIONS
43
+
44
+ // Conducts and reports the HTML CodeSniffer tests.
45
+ export const reporter = async (page: Page, report: Report, actIndex: number) => {
46
+ const act = report.acts[actIndex] as HtmlcsAct;
47
+ const {rules} = act;
48
+ // Initialize the act report.
49
+ const data: {prevented?: boolean; error?: string} = {};
50
+ const result: {nativeResult: HtmlcsNativeResult; standardResult: StandardResult} = {
51
+ nativeResult: {
52
+ totals: {
53
+ failed: 0,
54
+ cantTell: 0
55
+ },
56
+ error: [],
57
+ warning: []
58
+ },
59
+ standardResult: {}
60
+ };
61
+ const standard = report.standard !== 'no';
62
+ // If standard results are to be reported:
63
+ if (standard) {
64
+ // Initialize the standard result.
65
+ result.standardResult = getStandardResult();
66
+ }
67
+ const {nativeResult, standardResult} = result;
68
+ // Get the HTMLCS script.
69
+ const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
70
+ const scriptNonce = (report.jobData && report.jobData.lastScriptNonce) as string | undefined;
71
+ let messageStrings: string[] = [];
72
+ // For each class of standards to be tested for:
73
+ for (const actStandard of ['WCAG2AAA']) {
74
+ const nextViolations = await page.evaluate(args => {
75
+ const actStandard = args[0] as string;
76
+ const rules = args[1] as string[] | undefined;
77
+ const scriptText = args[2] as string;
78
+ const scriptNonce = args[3] as string;
79
+ const script = document.createElement('script');
80
+ script.nonce = scriptNonce;
81
+ script.textContent = scriptText;
82
+ // 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.
83
+ const umdDefine = window.define;
84
+ const umdExports = window.exports;
85
+ const umdModule = window.module;
86
+ window.define = undefined;
87
+ window.exports = undefined;
88
+ // The cast erases; window.module otherwise types as Node's module global.
89
+ window.module = undefined as unknown as typeof window.module;
90
+ // Add the HTMLCS script to the page.
91
+ document.head.insertAdjacentElement('beforeend', script);
92
+ // Restore the loader globals.
93
+ window.define = umdDefine;
94
+ window.exports = umdExports;
95
+ window.module = umdModule;
96
+ // If only some rules are to be employed:
97
+ if (rules && Array.isArray(rules) && rules.length) {
98
+ // Redefine WCAG 2 AAA as including only them.
99
+ if (! window.HTMLCS_WCAG2AAA) {
100
+ window.HTMLCS_WCAG2AAA = {};
101
+ }
102
+ window.HTMLCS_WCAG2AAA.sniffs = rules;
103
+ }
104
+ let violations: string[] | null = null;
105
+ // Run the tests.
106
+ try {
107
+ violations = window.HTMLCS_RUNNER!.run(actStandard);
108
+ }
109
+ catch(error) {
110
+ console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${(error as Error).message})`);
111
+ }
112
+ // Return the reported violations of that standard.
113
+ return violations;
114
+ }, [actStandard, rules, scriptText, scriptNonce]);
115
+ // If all reported violations of the standard are validly described:
116
+ if (nextViolations?.every(violation => typeof violation === 'string')) {
117
+ // Add their descriptions to the violation descriptions.
118
+ messageStrings.push(... nextViolations);
119
+ }
120
+ // Otherwise, i.e. if any reported violations are invalidly described:
121
+ else {
122
+ // Report this.
123
+ data.prevented = true;
124
+ data.error = 'ERROR executing HTMLCS_RUNNER in the page';
125
+ break;
126
+ }
127
+ }
128
+ // If no error was thrown:
129
+ if (! data.prevented) {
130
+ // Sort the violations by class and standard.
131
+ messageStrings.sort();
132
+ // Remove any duplicate violations.
133
+ messageStrings = [... new Set(messageStrings)];
134
+ // For each violation:
135
+ for (const string of messageStrings) {
136
+ // Split its message into severity class, rule ID, tagname, ID, rule description, and excerpt.
137
+ const parts = string.split(/\|/, 6);
138
+ const partCount = parts.length;
139
+ // If the message partitions are too few:
140
+ if (partCount < 6) {
141
+ // Report this.
142
+ console.log(`ERROR: Violation string ${string} has too few parts`);
143
+ }
144
+ // Otherwise, if the message reports an error:
145
+ else if (parts[0] === 'Error') {
146
+ // Add the rest of its message to the native-result errors.
147
+ nativeResult.error.push(parts.slice(1));
148
+ // Increment the error total.
149
+ nativeResult.totals.failed++;
150
+ }
151
+ // Otherwise, if the message reports a warning:
152
+ else if (parts[0] === 'Warning') {
153
+ // Add the rest of its message to the native-result warnings.
154
+ nativeResult.warning.push(parts.slice(1));
155
+ // Increment the warning total.
156
+ nativeResult.totals.cantTell++;
157
+ }
158
+ // If standard results are to be reported and the message reports an error or warning:
159
+ if (standard && ['Error', 'Warning'].includes(parts[0])) {
160
+ const xPath = getAttributeXPath(parts[5]);
161
+ pushInstance(standardResult, {
162
+ ruleID: `${parts[0][0]}-${parts[1]}`,
163
+ what: parts[4],
164
+ ordinalSeverity: parts[0] === 'Warning' ? 0 : 2,
165
+ outcome: parts[0] === 'Warning' ? 'cantTell' : 'failed',
166
+ catalogIndex: getXPathCatalogIndex(report, xPath)
167
+ });
168
+ }
169
+ }
170
+ // If standard results are to be reported:
171
+ if (standard) {
172
+ // Populate the standard-result totals.
173
+ standardResult.totals![0] = nativeResult.totals.cantTell;
174
+ standardResult.totals![2] = nativeResult.totals.failed;
175
+ }
176
+ }
177
+ return {
178
+ data,
179
+ result
180
+ };
181
+ };
package/tests/ibm.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import type { Page } from 'playwright';
2
+ import type { Report, StandardResult } from '../types';
3
+ interface IbmItem {
4
+ ruleId: string;
5
+ level: string;
6
+ message: string;
7
+ snippet: string;
8
+ apiArgs?: unknown;
9
+ category?: unknown;
10
+ ignored?: unknown;
11
+ messageArgs?: unknown;
12
+ reasonId?: unknown;
13
+ ruleTime?: unknown;
14
+ value?: unknown;
15
+ }
16
+ interface IbmCounts {
17
+ violation: number;
18
+ recommendation: number;
19
+ [key: string]: number;
20
+ }
21
+ interface IbmActReport {
22
+ summary?: {
23
+ counts?: IbmCounts;
24
+ };
25
+ results: IbmItem[];
26
+ items?: IbmItem[];
27
+ }
28
+ type IbmTrimmedReport = {
29
+ totals: IbmCounts;
30
+ items: IbmItem[] | undefined;
31
+ error?: undefined;
32
+ } | {
33
+ totals: null;
34
+ items: IbmItem[];
35
+ error: string;
36
+ };
37
+ export declare const reporter: (page: Page, report: Report, actIndex: number) => Promise<{
38
+ data: {};
39
+ result: {
40
+ nativeResult: IbmTrimmedReport | Record<string, never>;
41
+ standardResult: StandardResult;
42
+ };
43
+ } | {
44
+ data: {
45
+ report: IbmActReport;
46
+ } | {
47
+ prevented: boolean;
48
+ error: string;
49
+ };
50
+ result: {};
51
+ }>;
52
+ export {};
package/tests/ibm.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,12 @@
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 accessibilityChecker = require('accessibility-checker');
17
+ const { getCompliance } = accessibilityChecker;
12
18
  /*
13
19
  ibm
14
20
  Implements the IBM Equal Access ruleset for accessibility.
@@ -17,192 +23,184 @@
17
23
 
18
24
  This rule engine is compatible with Windows only if the accessibility-checker package
19
25
  is revised. See README.md for details.
26
+ Compiled to ibm.js by tsc (issue #73); edit this file, not the emitted one.
20
27
  */
21
-
22
- // IMPORTS
23
-
24
- const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
25
- const accessibilityChecker = require('accessibility-checker');
26
- const {getCompliance} = accessibilityChecker;
27
-
28
28
  // FUNCTIONS
29
-
30
29
  // Runs the IBM test and returns the result.
31
- const run = async content => {
32
- const nowLabel = (new Date()).toISOString().slice(0, 19);
33
- try {
34
- const ibmReport = await getCompliance(content, nowLabel);
35
- if (typeof ibmReport === 'object' && ibmReport.report) {
36
- return ibmReport;
30
+ const run = async (content) => {
31
+ const nowLabel = (new Date()).toISOString().slice(0, 19);
32
+ try {
33
+ const ibmReport = await getCompliance(content, nowLabel);
34
+ if (typeof ibmReport === 'object' && ibmReport.report) {
35
+ return ibmReport;
36
+ }
37
+ else {
38
+ return {
39
+ prevented: true,
40
+ error: 'ibm getCompliance produced no report'
41
+ };
42
+ }
37
43
  }
38
- else {
39
- return {
40
- prevented: true,
41
- error: 'ibm getCompliance produced no report'
42
- };
44
+ catch (error) {
45
+ console.log('ibm getCompliance failed');
46
+ return {
47
+ prevented: true,
48
+ error: error.message.slice(0, 200)
49
+ };
43
50
  }
44
- }
45
- catch(error) {
46
- console.log('ibm getCompliance failed');
47
- return {
48
- prevented: true,
49
- error: error.message.slice(0, 200)
50
- };
51
- }
52
51
  };
53
52
  // Revises act-report totals for any rule limitation.
54
53
  const limitRuleTotals = (actReport, rules) => {
55
- if (rules && Array.isArray(rules) && rules.length) {
56
- const totals = actReport.summary.counts;
57
- const items = actReport.results;
58
- totals.violation = totals.recommendation = 0;
59
- items.forEach(item => {
60
- if (rules.includes(item.ruleId)) {
61
- totals[item.level]++;
62
- }
63
- });
64
- }
54
+ if (rules && Array.isArray(rules) && rules.length) {
55
+ const totals = actReport.summary.counts;
56
+ const items = actReport.results;
57
+ totals.violation = totals.recommendation = 0;
58
+ items.forEach(item => {
59
+ if (rules.includes(item.ruleId)) {
60
+ totals[item.level]++;
61
+ }
62
+ });
63
+ }
65
64
  };
66
65
  // Trims an IBM report.
67
66
  const trimActReport = (actReport, withItems, rules) => {
68
- // If the act report includes a summary:
69
- if (actReport && actReport.summary) {
70
- // Remove excluded rules from the act report.
71
- limitRuleTotals(actReport, rules);
72
- const totals = actReport.summary.counts;
73
- // If the act report includes totals:
74
- if (totals) {
75
- // If itemization is required:
76
- if (withItems) {
77
- // Trim the items.
78
- if (rules && Array.isArray(rules) && rules.length) {
79
- actReport.items = actReport.results.filter(item => rules.includes(item.ruleId));
67
+ // If the act report includes a summary:
68
+ if (actReport && actReport.summary) {
69
+ // Remove excluded rules from the act report.
70
+ limitRuleTotals(actReport, rules);
71
+ const totals = actReport.summary.counts;
72
+ // If the act report includes totals:
73
+ if (totals) {
74
+ // If itemization is required:
75
+ if (withItems) {
76
+ // Trim the items.
77
+ if (rules && Array.isArray(rules) && rules.length) {
78
+ actReport.items = actReport.results.filter(item => rules.includes(item.ruleId));
79
+ }
80
+ else {
81
+ actReport.items = actReport.results;
82
+ }
83
+ actReport.items.forEach(item => {
84
+ delete item.apiArgs;
85
+ delete item.category;
86
+ delete item.ignored;
87
+ delete item.messageArgs;
88
+ delete item.reasonId;
89
+ delete item.ruleTime;
90
+ delete item.value;
91
+ });
92
+ }
93
+ // Return the act report, trimmed.
94
+ return {
95
+ totals,
96
+ items: actReport.items
97
+ };
80
98
  }
99
+ // Otherwise, i.e. if it excludes totals:
81
100
  else {
82
- actReport.items = actReport.results;
101
+ // Return an act report with this error.
102
+ return {
103
+ totals: null,
104
+ items: [],
105
+ error: 'No totals reported'
106
+ };
83
107
  }
84
- actReport.items.forEach(item => {
85
- delete item.apiArgs;
86
- delete item.category;
87
- delete item.ignored;
88
- delete item.messageArgs;
89
- delete item.reasonId;
90
- delete item.ruleTime;
91
- delete item.value;
92
- });
93
- }
94
- // Return the act report, trimmed.
95
- return {
96
- totals,
97
- items: actReport.items
98
- };
99
108
  }
100
- // Otherwise, i.e. if it excludes totals:
109
+ // Otherwise, i.e. if it excludes a summary:
101
110
  else {
102
- // Return an act report with this error.
103
- return {
104
- totals: null,
105
- items: [],
106
- error: 'No totals reported'
107
- };
111
+ // Return an act report with this error.
112
+ return {
113
+ totals: null,
114
+ items: [],
115
+ error: 'No summary reported'
116
+ };
108
117
  }
109
- }
110
- // Otherwise, i.e. if it excludes a summary:
111
- else {
112
- // Return an act report with this error.
113
- return {
114
- totals: null,
115
- items: [],
116
- error: 'No summary reported'
117
- };
118
- }
119
118
  };
120
119
  // Conducts and reports the IBM Equal Access tests.
121
- exports.reporter = async (page, report, actIndex) => {
122
- const act = report.acts[actIndex];
123
- const {withItems, rules} = act;
124
- // Initialize the act report.
125
- const result = {
126
- nativeResult: {},
127
- standardResult: {}
128
- };
129
- const standard = report.standard !== 'no';
130
- // If standard results are to be reported:
131
- if (standard) {
132
- // Initialize the standard result.
133
- result.standardResult = {
134
- prevented: false,
135
- totals: [0, 0, 0, 0],
136
- instances: []
120
+ const reporter = async (page, report, actIndex) => {
121
+ const act = report.acts[actIndex];
122
+ const { withItems, rules } = act;
123
+ // Initialize the act report.
124
+ const result = {
125
+ nativeResult: {},
126
+ standardResult: {}
137
127
  };
138
- }
139
- try {
140
- // Conduct the tests.
141
- const runReport = await run(page);
142
- const actReport = runReport.report;
143
- // If there were results:
144
- if (actReport) {
145
- // Trim them.
146
- result.nativeResult = trimActReport(actReport, withItems, rules);
147
- const {nativeResult, standardResult} = result;
148
- const {error, totals} = nativeResult;
149
- // If they were not trimmable:
150
- if (error) {
151
- // Return an act report with this error.
152
- return {
153
- data: {
154
- prevented: true,
155
- error
156
- },
157
- result: {}
128
+ const standard = report.standard !== 'no';
129
+ // If standard results are to be reported:
130
+ if (standard) {
131
+ // Initialize the standard result.
132
+ result.standardResult = (0, standard_1.getStandardResult)();
133
+ }
134
+ try {
135
+ // Conduct the tests.
136
+ const runReport = await run(page);
137
+ const actReport = runReport.report;
138
+ // If there were results:
139
+ if (actReport) {
140
+ // Trim them.
141
+ result.nativeResult = trimActReport(actReport, withItems, rules);
142
+ const { nativeResult, standardResult } = result;
143
+ const { error, totals } = nativeResult;
144
+ // If they were not trimmable:
145
+ if (error) {
146
+ // Return an act report with this error.
147
+ return {
148
+ data: {
149
+ prevented: true,
150
+ error
151
+ },
152
+ result: {}
153
+ };
154
+ }
155
+ // Otherwise, i.e. if they were trimmable, and if standard results are to be reported:
156
+ if (standard) {
157
+ // Populate the totals of the standard result.
158
+ standardResult.totals = [totals.recommendation, 0, totals.violation, 0];
159
+ // For each item of the native result (without itemization, items is
160
+ // undefined and this throws, caught below; verbatim from the original):
161
+ nativeResult.items.forEach(item => {
162
+ // Populate a standard instance. Potential violations, potential recommendations, and
163
+ // manual checks are engine-flagged uncertainty.
164
+ const standardItem = {
165
+ ruleID: item.ruleId,
166
+ what: item.message,
167
+ ordinalSeverity: item.level === 'recommendation' ? 0 : 2,
168
+ outcome: ['violation', 'recommendation'].includes(item.level) ? 'failed' : 'cantTell'
169
+ };
170
+ // Get the XPath from the added attribute, because path.dom is wrong.
171
+ const xPath = (0, xPath_1.getAttributeXPath)(item.snippet);
172
+ // If the XPath was obtained:
173
+ if (xPath) {
174
+ // Add the catalog index to the standard instance.
175
+ standardItem.catalogIndex = (0, xPath_1.getXPathCatalogIndex)(report, xPath);
176
+ }
177
+ // Add the standard instance to the standard result.
178
+ (0, standard_1.pushInstance)(standardResult, standardItem);
179
+ });
180
+ }
181
+ return {
182
+ data: {},
183
+ result
184
+ };
158
185
  }
159
- }
160
- // Otherwise, i.e. if they were trimmable, and if standard results are to be reported:
161
- if (standard) {
162
- // Populate the totals of the standard result.
163
- standardResult.totals = [totals.recommendation, 0, totals.violation, 0];
164
- // For each item of the native result:
165
- nativeResult.items.forEach(item => {
166
- // Populate a standard instance.
167
- const standardItem = {
168
- ruleID: item.ruleId,
169
- what: item.message,
170
- ordinalSeverity: item.level === 'recommendation' ? 0 : 2,
171
- count: 1
172
- };
173
- // Get the XPath from the added attribute, because path.dom is wrong.
174
- const xPath = getAttributeXPath(item.snippet);
175
- // If the XPath was obtained:
176
- if (xPath) {
177
- // Add the catalog index to the standard instance.
178
- standardItem.catalogIndex = getXPathCatalogIndex(report, xPath);
179
- }
180
- // Add the standard instance to the standard result.
181
- standardResult.instances.push(standardItem);
182
- });
183
- }
184
- return {
185
- data: {},
186
- result
187
- };
186
+ // Otherwise, i.e. if there was only an error, return it in an act report.
187
+ return {
188
+ data: runReport,
189
+ result: {}
190
+ };
188
191
  }
189
- // Otherwise, i.e. if there was only an error, return it in an act report.
190
- return {
191
- data: runReport,
192
- result: {}
192
+ // If an error occurred:
193
+ catch (error) {
194
+ const message = `Act failed (${error.message.slice(0, 200)})`;
195
+ console.log(message);
196
+ // Return it in an act report.
197
+ return {
198
+ data: {
199
+ prevented: true,
200
+ error: message
201
+ },
202
+ result: {}
203
+ };
193
204
  }
194
- }
195
- // If an error occurred:
196
- catch(error) {
197
- const message = `Act failed (${error.message.slice(0, 200)})`;
198
- console.log(message);
199
- // Return it in an act report.
200
- return {
201
- data: {
202
- prevented: true,
203
- error: message
204
- },
205
- result: {}
206
- };
207
- }
208
205
  };
206
+ exports.reporter = reporter;