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/procs/testaro.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /*
2
3
  © 2023–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
4
  © 2026 Jeff Witt.
@@ -7,209 +8,255 @@
7
8
 
8
9
  SPDX-License-Identifier: MIT
9
10
  */
10
-
11
- /*
12
- testaro
13
- Utilities for Testaro tests.
14
- */
15
-
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getBasicResult = exports.doTest = void 0;
16
13
  // ########## IMPORTS
17
-
18
14
  // Function to get a catalog index from an XPath.
19
- const {getXPathCatalogIndex} = require('./xPath');
20
-
15
+ const xPath_1 = require("./xPath");
16
+ // Function to build a standard instance.
17
+ const standard_1 = require("./standard");
21
18
  // ########## FUNCTIONS
22
-
19
+ // Returns a standard instance, leaving the outcome unset if the violation did not specify one, so
20
+ // that the testaro tool can apply the rule's default outcome.
21
+ const getRuleInstance = (spec) => {
22
+ const instance = (0, standard_1.getInstance)(spec);
23
+ if (!spec.outcome) {
24
+ instance.outcome = undefined;
25
+ }
26
+ return instance;
27
+ };
23
28
  // Tests for a testaro rule.
24
- exports.doTest = async (
25
- page,
26
- report,
27
- withItems,
28
- ruleID,
29
- candidateSelector,
30
- whats,
31
- severity,
32
- getBadWhatString
33
- ) => {
34
- const ruleData = await page.evaluate(async args => {
35
- // Get the arguments.
36
- const [
37
- withItems,
38
- candidateSelector,
39
- severity,
40
- getBadWhatString
41
- ] = args;
42
- // Get all violator candidates.
43
- const candidates = document.querySelectorAll(candidateSelector);
44
- let violationCount = 0;
45
- // Initialize proto-instances.
46
- const protoInstances = [];
47
- // Parse the supplied string to get the classifier.
48
- const getBadWhat = eval(`(${getBadWhatString})`);
49
- // Initialize data on the rule.
50
- let data = {};
51
- const totals = [0, 0, 0, 0];
52
- // For each candidate:
53
- for (const candidate of candidates) {
54
- // Classify it as and get a violation description if a violator or undefined if not.
55
- const violationWhat = await getBadWhat(candidate);
56
- // If the candidate violates the rule:
57
- if (violationWhat) {
58
- // Increment the violation count.
59
- violationCount++;
60
- let ruleWhat;
61
- const violationType = typeof violationWhat;
62
- // If data on the violation were provided (unusual):
63
- if (violationType === 'object') {
64
- // Get the description and add the data to the rule data.
65
- ruleWhat = violationWhat.description;
66
- data[violationCount - 1] = violationWhat.data;
29
+ const doTest = async (page, report, withItems, ruleID, candidateSelector, whats, severity, getBadWhatString) => {
30
+ // The subtree roots the rule is restricted to, if the test act has scope changed and the
31
+ // testaro tool judged the rule element-local (set per rule by tests/testaro.ts).
32
+ const scopeRoots = report.ruleScopeRoots ?? null;
33
+ const ruleData = await page.evaluate(async (args) => {
34
+ // Get the arguments.
35
+ const [withItems, candidateSelector, severity, getBadWhatString, scopeRoots] = args;
36
+ // Get all violator candidates, within the scope roots if any.
37
+ let candidates = Array.from(document.querySelectorAll(candidateSelector));
38
+ if (scopeRoots && scopeRoots.length) {
39
+ const roots = scopeRoots
40
+ .map(selector => {
41
+ try {
42
+ return document.querySelector(selector);
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ })
48
+ .filter((root) => Boolean(root));
49
+ candidates = candidates.filter(candidate => roots.some(root => root.contains(candidate)));
67
50
  }
68
- // Otherwise, i.e. if only a description of the violation was provided:
69
- else if (violationType === 'string') {
70
- // Get it.
71
- ruleWhat = violationWhat;
51
+ let violationCount = 0;
52
+ // Initialize proto-instances.
53
+ const protoInstances = [];
54
+ // Initialize counts of cantTell violations by ordinal severity, for summary instances.
55
+ const cantTellTotals = [0, 0, 0, 0];
56
+ /*
57
+ Parse the supplied string to get the classifier. The predicate travels as
58
+ source text (serialized with toString() by the rule module) because it
59
+ must run inside the page; this cast is the single point where its type is
60
+ asserted rather than checked (issue #73, RFC decision 4). The eval input
61
+ is first-party rule-module source from this repository, never target-page
62
+ or user data; replacing the eval pipeline with a bundled artifact is the
63
+ Phase 3 reassessment recorded on issue #73.
64
+ */
65
+ const getBadWhat = eval(`(${getBadWhatString})`);
66
+ // Initialize data on the rule.
67
+ let data = {};
68
+ const totals = [0, 0, 0, 0];
69
+ // For each candidate:
70
+ for (const candidate of candidates) {
71
+ // Classify it as and get a violation description if a violator or undefined if not.
72
+ const violationWhat = await getBadWhat(candidate);
73
+ // If the candidate violates the rule:
74
+ if (violationWhat) {
75
+ // Increment the violation count.
76
+ violationCount++;
77
+ let ruleWhat;
78
+ const violationType = typeof violationWhat;
79
+ // If data on the violation were provided (unusual):
80
+ if (violationType === 'object') {
81
+ // Get the description and add the data to the rule data.
82
+ ruleWhat = violationWhat.description;
83
+ data[violationCount - 1] = violationWhat.data;
84
+ }
85
+ // Otherwise, i.e. if only a description of the violation was provided:
86
+ else if (violationType === 'string') {
87
+ // Get it.
88
+ ruleWhat = violationWhat;
89
+ }
90
+ let ordinalSeverity = severity;
91
+ let outcome;
92
+ // A predicate that returns a truthy non-object non-string would make this throw,
93
+ // exactly as in the JavaScript original.
94
+ // If this violation has a custom severity or outcome prefix (e.g. 2:, 2?:, or ?:):
95
+ const prefixMatch = ruleWhat.match(/^([0-3])?(\?)?:/);
96
+ if (prefixMatch) {
97
+ // If the prefix has a severity, get it.
98
+ if (prefixMatch[1]) {
99
+ ordinalSeverity = Number(prefixMatch[1]);
100
+ }
101
+ // If the prefix marks the violation as uncertain, record this.
102
+ if (prefixMatch[2]) {
103
+ outcome = 'cantTell';
104
+ cantTellTotals[ordinalSeverity]++;
105
+ }
106
+ // Remove the prefix from the violation description.
107
+ ruleWhat = ruleWhat.slice(prefixMatch[0].length);
108
+ }
109
+ // Increment the applicable rule-violation total.
110
+ totals[ordinalSeverity]++;
111
+ // If itemization is required:
112
+ if (withItems) {
113
+ const protoInstance = {
114
+ what: ruleWhat,
115
+ ordinalSeverity,
116
+ outcome,
117
+ xPath: window.getXPath(candidate) ?? '/html'
118
+ };
119
+ // Add a proto-instance to the proto-instances.
120
+ protoInstances.push(protoInstance);
121
+ }
122
+ }
72
123
  }
73
- const ruleWhatStart = ruleWhat.slice(0, 2);
74
- let ordinalSeverity = severity;
75
- // If this violation has a custom severity:
76
- if (/[0-3]:/.test(ruleWhatStart)) {
77
- // Get it.
78
- ordinalSeverity = Number(ruleWhat[0]);
79
- // Remove it from the violation description.
80
- ruleWhat = ruleWhat.slice(2);
81
- }
82
- // Increment the applicable rule-violation total.
83
- totals[ordinalSeverity]++;
84
- // If itemization is required:
85
- if (withItems) {
86
- const protoInstance = {
87
- what: ruleWhat,
88
- ordinalSeverity,
89
- xPath: window.getXPath(candidate) ?? '/html'
90
- };
91
- // Add a proto-instance to the proto-instances.
92
- protoInstances.push(protoInstance);
93
- }
94
- }
95
- }
96
- return {
97
- data,
98
- totals,
99
- protoInstances
124
+ return {
125
+ data,
126
+ totals,
127
+ cantTellTotals,
128
+ protoInstances
129
+ };
130
+ }, [
131
+ withItems,
132
+ candidateSelector,
133
+ severity,
134
+ getBadWhatString,
135
+ scopeRoots
136
+ ]);
137
+ // Initialize the standard instances. Any instance without an outcome gets the rule's default
138
+ // outcome from the testaro tool.
139
+ let standardInstances = [];
140
+ const { data, totals, cantTellTotals, protoInstances } = ruleData;
141
+ // If itemization is required:
142
+ if (withItems) {
143
+ // For each proto-instance:
144
+ protoInstances.forEach(protoInstance => {
145
+ const { what, ordinalSeverity, outcome, xPath } = protoInstance;
146
+ // Add a standard instance to the standard instances.
147
+ standardInstances.push(getRuleInstance({
148
+ ruleID,
149
+ what,
150
+ ordinalSeverity,
151
+ outcome,
152
+ catalogIndex: xPath ? (0, xPath_1.getXPathCatalogIndex)(report, xPath) : undefined
153
+ }));
154
+ });
100
155
  }
101
- }, [
102
- withItems,
103
- candidateSelector,
104
- severity,
105
- getBadWhatString
106
- ]
107
- );
108
- // Initialize the standard instances.
109
- let standardInstances = [];
110
- const {data, totals, protoInstances} = ruleData;
111
- // If itemization is required:
112
- if (withItems) {
113
- // For each proto-instance:
114
- protoInstances.forEach(protoInstance => {
115
- const {what, ordinalSeverity, xPath} = protoInstance;
116
- // Initialize a standard instance.
117
- const standardInstance = {
118
- ruleID,
119
- what,
120
- ordinalSeverity,
121
- count: 1
122
- };
123
- // If the proto-instance includes an XPath:
124
- if (xPath) {
125
- // Add the catalog index to the standard instance.
126
- standardInstance.catalogIndex = getXPathCatalogIndex(report, xPath);
127
- }
128
- // Add the standard instance to the standard instances.
129
- standardInstances.push(standardInstance);
130
- });
131
- }
132
- // Otherwise, i.e. if itemization is not required:
133
- else {
134
- // For each ordinal severity:
135
- for (const index in totals) {
136
- // If there were any violations at that severity:
137
- if (totals[index]) {
138
- // Add a summary standard instance to the standard instances.
139
- standardInstances.push({
140
- ruleID,
141
- what: whats,
142
- ordinalSeverity: index,
143
- count: totals[index]
156
+ // Otherwise, i.e. if itemization is not required:
157
+ else {
158
+ // For each ordinal severity:
159
+ totals.forEach((total, ordinalSeverity) => {
160
+ const cantTellTotal = cantTellTotals[ordinalSeverity];
161
+ // If there were any asserted violations at that severity:
162
+ if (total - cantTellTotal) {
163
+ // Add a summary standard instance to the standard instances.
164
+ standardInstances.push(getRuleInstance({
165
+ ruleID,
166
+ what: whats,
167
+ ordinalSeverity,
168
+ count: total - cantTellTotal
169
+ }));
170
+ }
171
+ // If there were any uncertain violations at that severity:
172
+ if (cantTellTotal) {
173
+ // Add a summary standard instance for them.
174
+ standardInstances.push(getRuleInstance({
175
+ ruleID,
176
+ what: whats,
177
+ ordinalSeverity,
178
+ outcome: 'cantTell',
179
+ count: cantTellTotal
180
+ }));
181
+ }
144
182
  });
145
- }
146
183
  }
147
- }
148
- // Return the data, totals, and standard instances.
149
- return {
150
- data,
151
- totals,
152
- standardInstances
153
- };
184
+ // Return the data, totals, and standard instances.
185
+ return {
186
+ data,
187
+ totals: totals,
188
+ standardInstances
189
+ };
154
190
  };
191
+ exports.doTest = doTest;
155
192
  // Adds a catalog index or, if necessary, an XPath to a proto-instance.
156
193
  const addCatalogIndex = async (protoInstance, locator, report) => {
157
- // Get the XPath of the element referenced by the locator.
158
- const xPath = await locator.evaluate(element => window.getXPath(element) ?? '/html');
159
- // Add a catalog index to the proto-instance.
160
- protoInstance.catalogIndex = getXPathCatalogIndex(report, xPath);
161
- // Return the proto-instance with any modification.
162
- return protoInstance;
194
+ // Get the XPath of the element referenced by the locator.
195
+ const xPath = await locator.evaluate(element => window.getXPath(element) ?? '/html');
196
+ // Add a catalog index to the proto-instance.
197
+ protoInstance.catalogIndex = (0, xPath_1.getXPathCatalogIndex)(report, xPath);
198
+ // Return the proto-instance with any modification.
199
+ return protoInstance;
163
200
  };
164
201
  // Tests for a doTest-ineligible Testaro rule.
165
- exports.getBasicResult = async (
166
- report, withItems, ruleID, ordinalSeverity, whats, data, violations
167
- ) => {
168
- // If the test was prevented:
169
- if (data.prevented) {
170
- // Return this.
202
+ const getBasicResult = async (report, withItems, ruleID, ordinalSeverity, whats, data, violations) => {
203
+ // If the test was prevented:
204
+ if (data.prevented) {
205
+ // Return this.
206
+ return {
207
+ data,
208
+ totals: [0, 0, 0, 0],
209
+ standardInstances: []
210
+ };
211
+ }
212
+ // Otherwise, i.e. if the test was not prevented:
213
+ const totals = [0, 0, 0, 0];
214
+ totals[ordinalSeverity] = violations.length;
215
+ const standardInstances = [];
216
+ // If itemization is required:
217
+ if (withItems) {
218
+ // For each violation:
219
+ for (const violation of violations) {
220
+ const { loc, what, outcome, uncertainty, needed } = violation;
221
+ // Initialize a standard instance.
222
+ const protoInstance = getRuleInstance({
223
+ ruleID,
224
+ what,
225
+ ordinalSeverity,
226
+ outcome,
227
+ uncertainty,
228
+ needed
229
+ });
230
+ // Add a catalog index to it, awaited so the index is present before the
231
+ // report can be serialized (issue #100).
232
+ await addCatalogIndex(protoInstance, loc, report);
233
+ // Add the standard instance to the standard instances.
234
+ standardInstances.push(protoInstance);
235
+ }
236
+ }
237
+ // Otherwise, i.e. if itemization is not required:
238
+ else {
239
+ // Add a summary instance per outcome to the instances.
240
+ const outcomeCounts = {};
241
+ violations.forEach(violation => {
242
+ const outcome = violation.outcome || 'failed';
243
+ outcomeCounts[outcome] = (outcomeCounts[outcome] || 0) + 1;
244
+ });
245
+ Object.keys(outcomeCounts).forEach(outcome => {
246
+ standardInstances.push(getRuleInstance({
247
+ ruleID,
248
+ what: whats,
249
+ ordinalSeverity,
250
+ outcome,
251
+ count: outcomeCounts[outcome]
252
+ }));
253
+ });
254
+ }
255
+ // Return the result.
171
256
  return {
172
- data,
173
- totals: [0, 0, 0, 0],
174
- standardInstances: []
257
+ data,
258
+ totals,
259
+ standardInstances
175
260
  };
176
- }
177
- // Otherwise, i.e. if the test was not prevented:
178
- const totals = [0, 0, 0, 0];
179
- totals[ordinalSeverity] = violations.length;
180
- const standardInstances = [];
181
- // If itemization is required:
182
- if (withItems) {
183
- // For each violation:
184
- for (const violation of violations) {
185
- const {loc, what} = violation;
186
- // Initialize a standard instance.
187
- const protoInstance = {
188
- ruleID,
189
- what,
190
- ordinalSeverity,
191
- count: 1
192
- };
193
- // Add a catalog index to it.
194
- addCatalogIndex(protoInstance, loc, report);
195
- // Add the standard instance to the standard instances.
196
- standardInstances.push(protoInstance);
197
- }
198
- }
199
- // Otherwise, i.e. if itemization is not required:
200
- else {
201
- // Add a summary instance to the instances.
202
- standardInstances.push({
203
- ruleID,
204
- what: whats,
205
- ordinalSeverity,
206
- count: violations.length
207
- });
208
- }
209
- // Return the result.
210
- return {
211
- data,
212
- totals,
213
- standardInstances
214
- };
215
261
  };
262
+ exports.getBasicResult = getBasicResult;