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/qualWeb.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.
@@ -8,297 +9,326 @@
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");
12
16
  /*
13
- qualWeb
14
- Implements the QualWeb ruleset for accessibility.
17
+ The @qualweb packages declare their types only in package-exports maps, which
18
+ this project's node10 module resolution cannot read, so the imports stay
19
+ requires and are untyped.
15
20
  */
16
-
17
- // IMPORTS
18
-
19
- const {QualWeb} = require('@qualweb/core');
20
- const {ACTRules} = require('@qualweb/act-rules');
21
- const {WCAGTechniques} = require('@qualweb/wcag-techniques');
22
- const {BestPractices} = require('@qualweb/best-practices');
23
- const {PlaywrightDriver} = require('@qualweb/playwright-driver');
24
- const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
25
-
26
- // CONSTANTS
27
-
28
- // QualWeb core engine with Playwright as driver.
29
- const qualWeb = new QualWeb(undefined, new PlaywrightDriver({
30
- adBlock: true,
31
- stealth: true
32
- }));
21
+ const { QualWeb } = require('@qualweb/core');
22
+ const { ACTRules } = require('@qualweb/act-rules');
23
+ const { WCAGTechniques } = require('@qualweb/wcag-techniques');
24
+ const { BestPractices } = require('@qualweb/best-practices');
25
+ const { PlaywrightDriver } = require('@qualweb/playwright-driver');
26
+ const config_1 = require("../procs/config");
27
+ const qualWebInstances = {};
28
+ const getQualWeb = (options) => {
29
+ const key = `${options.stealth}:${options.adBlock}`;
30
+ if (!qualWebInstances[key]) {
31
+ let launcher;
32
+ if (options.stealth) {
33
+ const { chromium } = require('playwright-extra');
34
+ chromium.use(require('puppeteer-extra-plugin-stealth')());
35
+ launcher = chromium;
36
+ }
37
+ const qualWeb = new QualWeb(undefined, new PlaywrightDriver(launcher ? { launcher } : {}));
38
+ if (options.adBlock) {
39
+ const { PlaywrightBlocker } = require('@ghostery/adblocker-playwright');
40
+ let blockerPromise = null;
41
+ qualWeb.use({
42
+ async beforePageLoad(page) {
43
+ blockerPromise ??= PlaywrightBlocker.fromPrebuiltAdsAndTracking(fetch, {
44
+ path: require('path').join(require('os').tmpdir(), 'qualweb-adblocker-engine.bin'),
45
+ read: require('fs').promises.readFile,
46
+ write: require('fs').promises.writeFile
47
+ }).catch((error) => {
48
+ console.log(`qualWeb: ad blocker unavailable, continuing without it (${error.message})`);
49
+ return null;
50
+ });
51
+ const blocker = await blockerPromise;
52
+ if (blocker) {
53
+ await blocker.enableBlockingInPage(page.nativePage);
54
+ }
55
+ }
56
+ });
57
+ }
58
+ qualWebInstances[key] = qualWeb;
59
+ }
60
+ return qualWebInstances[key];
61
+ };
33
62
  const actRulesModule = new ACTRules({});
34
63
  const wcagModule = new WCAGTechniques({});
35
64
  const bpModule = new BestPractices({});
36
65
  // Mapping of QualWeb module violation types to ordinal severities.
37
66
  const ordinalSeverities = {
38
- 'act-rules': {
39
- 'warning': 1,
40
- 'failed': 3
41
- },
42
- 'wcag-techniques': {
43
- 'warning': 0,
44
- 'failed': 2
45
- },
46
- 'best-practices': {
47
- 'warning': 0,
48
- 'failed': 1
49
- }
50
- }
51
-
67
+ 'act-rules': {
68
+ 'warning': 1,
69
+ 'failed': 3
70
+ },
71
+ 'wcag-techniques': {
72
+ 'warning': 0,
73
+ 'failed': 2
74
+ },
75
+ 'best-practices': {
76
+ 'warning': 0,
77
+ 'failed': 1
78
+ }
79
+ };
80
+ /*
81
+ qualWeb
82
+ Implements the QualWeb ruleset for accessibility.
83
+ Compiled to qualWeb.js by tsc (issue #73); edit this file, not the emitted one.
84
+ */
52
85
  // FUNCTIONS
53
-
54
86
  // Conducts and reports the QualWeb tests.
55
- exports.reporter = async (page, report, actIndex, timeLimit) => {
56
- const act = report.acts[actIndex];
57
- const {rules} = act;
58
- const clusterOptions = {
59
- maxConcurrency: 1,
60
- timeout: timeLimit * 1000,
61
- monitor: false
62
- };
63
- // Initialize the act report.
64
- const data = {};
65
- const result = {
66
- nativeResult: {},
67
- standardResult: {}
68
- };
69
- const standard = report.standard !== 'no';
70
- // If standard results are to be reported:
71
- if (standard) {
72
- // Initialize the standard result.
73
- result.standardResult = {
74
- prevented: false,
75
- totals: [0, 0, 0, 0],
76
- instances: []
87
+ const reporter = async (page, report, actIndex, timeLimit) => {
88
+ const qualWebAct = report.acts[actIndex];
89
+ const qualWeb = getQualWeb({
90
+ stealth: qualWebAct.stealth ?? config_1.qualWebDefaults.stealth,
91
+ adBlock: qualWebAct.adBlock ?? config_1.qualWebDefaults.adBlock
92
+ });
93
+ const act = report.acts[actIndex];
94
+ const { rules } = act;
95
+ const clusterOptions = {
96
+ maxConcurrency: 1,
97
+ timeout: timeLimit * 1000,
98
+ monitor: false
77
99
  };
78
- }
79
- try {
80
- // Start the QualWeb core engine, which launches a Playwright browser.
81
- await qualWeb.start(clusterOptions);
82
- }
83
- // If the start fails:
84
- catch(error) {
85
- return {
86
- data: {
87
- prevented: true,
88
- error: `Core engine start failed (${error.message})`
89
- },
90
- result
100
+ // Initialize the act report.
101
+ const data = {};
102
+ const result = {
103
+ nativeResult: {},
104
+ standardResult: {}
91
105
  };
92
- }
93
- // Otherwise, i.e. if the start succeeds, specify the invariant test options.
94
- const qualWebOptions = {
95
- log: {
96
- console: false,
97
- file: false
98
- },
99
- crawlOptions: {
100
- maxDepth: 0,
101
- maxUrls: 1,
102
- timeout: timeLimit * 1000,
103
- maxParallelCrawls: 1,
104
- logging: true
105
- },
106
- execute: {
107
- counter: true
108
- },
109
- modules: []
110
- };
111
- try {
112
- // Provide the page content, including the data-xpath attributes.
113
- qualWebOptions.html = await page.content();
114
- // Specify which rules to test for, adding a custom execute property for report processing.
115
- const actSpec = rules ? rules.find(typeRules => typeRules.startsWith('act:')) : null;
116
- const wcagSpec = rules ? rules.find(typeRules => typeRules.startsWith('wcag:')) : null;
117
- const bestSpec = rules ? rules.find(typeRules => typeRules.startsWith('best:')) : null;
118
- if (actSpec) {
119
- if (actSpec === 'act:') {
120
- qualWebOptions.execute.act = false;
121
- }
122
- else {
123
- const actRules = actSpec.slice(4).split(',').map(num => `QW-ACT-R${num}`);
124
- qualWebOptions['act-rules'] = {rules: actRules};
125
- qualWebOptions.modules.push(actRulesModule);
126
- qualWebOptions.execute.act = true;
127
- }
128
- }
129
- else {
130
- qualWebOptions['act-rules'] = {
131
- levels: ['A', 'AA', 'AAA'],
132
- principles: ['Perceivable', 'Operable', 'Understandable', 'Robust']
133
- };
134
- qualWebOptions.modules.push(actRulesModule);
135
- qualWebOptions.execute.act = true;
136
- }
137
- if (wcagSpec) {
138
- if (wcagSpec === 'wcag:') {
139
- qualWebOptions.execute.wcag = false;
140
- }
141
- else {
142
- const wcagTechniques = wcagSpec.slice(5).split(',').map(num => `QW-WCAG-T${num}`);
143
- qualWebOptions['wcag-techniques'] = {techniques: wcagTechniques};
144
- qualWebOptions.modules.push(wcagModule);
145
- qualWebOptions.execute.wcag = true;
146
- }
106
+ const standard = report.standard !== 'no';
107
+ // If standard results are to be reported:
108
+ if (standard) {
109
+ // Initialize the standard result.
110
+ result.standardResult = (0, standard_1.getStandardResult)();
147
111
  }
148
- else {
149
- qualWebOptions['wcag-techniques'] = {
150
- levels: ['A', 'AA', 'AAA'],
151
- principles: ['Perceivable', 'Operable', 'Understandable', 'Robust']
152
- };
153
- qualWebOptions.modules.push(wcagModule);
154
- qualWebOptions.execute.wcag = true;
155
- }
156
- if (bestSpec) {
157
- if (bestSpec === 'best:') {
158
- qualWebOptions.execute.bp = false;
159
- }
160
- else {
161
- const bestPractices = bestSpec.slice(5).split(',').map(num => `QW-BP${num}`);
162
- qualWebOptions['best-practices'] = {bestPractices};
163
- qualWebOptions.modules.push(bpModule);
164
- qualWebOptions.execute.bp = true;
165
- }
166
- }
167
- else {
168
- qualWebOptions['best-practices'] = {};
169
- qualWebOptions.modules.push(bpModule);
170
- qualWebOptions.execute.bp = true;
171
- }
172
- let qwReport;
173
112
  try {
174
- // Get the report.
175
- qwReport = await qualWeb.evaluate(qualWebOptions);
113
+ // Start the QualWeb core engine, which launches a Playwright browser.
114
+ await qualWeb.start(clusterOptions);
176
115
  }
177
- catch(error) {
178
- return {
179
- data: {
180
- prevented: true,
181
- error: `qualWeb evaluation failed (${error.message})`
182
- },
183
- result
184
- };
116
+ // If the start fails:
117
+ catch (error) {
118
+ return {
119
+ data: {
120
+ prevented: true,
121
+ error: `Core engine start failed (${error.message})`
122
+ },
123
+ result
124
+ };
185
125
  }
186
- // Add the report to the result.
187
- result.nativeResult = qwReport.customHtml;
188
- const {nativeResult, standardResult} = result;
189
- // If the report contains, as it should, a copy of the DOM:
190
- if (nativeResult?.system?.page?.dom) {
191
- // Delete the copy for parsimony.
192
- delete nativeResult.system.page.dom;
193
- const {modules} = nativeResult;
194
- // If the report contains, as it should, a modules property:
195
- if (modules) {
196
- // For each test section in it:
197
- for (const section of ['act-rules', 'wcag-techniques', 'best-practices']) {
198
- // If testing in the section was specified:
199
- if (qualWebOptions[section]) {
200
- // If the section exists:
201
- if (modules[section]) {
202
- const {assertions} = modules[section];
203
- // If it contains assertions (test results):
204
- if (assertions) {
205
- const ruleIDs = Object.keys(assertions);
206
- // For each rule:
207
- for (const ruleID of ruleIDs) {
208
- const ruleAssertions = assertions[ruleID];
209
- const {metadata} = ruleAssertions;
210
- // If there were any warnings or failures:
211
- if (metadata?.warning || metadata?.failed) {
212
- // Delete nonviolations from the results.
213
- ruleAssertions.results = ruleAssertions.results.filter(
214
- raResult => raResult.verdict !== 'passed'
215
- );
216
- // For each test result:
217
- for (const raResult of ruleAssertions.results) {
218
- const {elements, verdict} = raResult;
219
- // If any violations are reported:
220
- if (elements?.length) {
221
- // For each violating element:
222
- for (const element of elements) {
223
- // Limit the size of its reported excerpt.
224
- if (element.htmlCode?.length > 2000) {
225
- element.htmlCode = `${element.htmlCode.slice(0, 2000)} …`;
226
- }
227
- // If standard results are to be reported:
228
- if (standard) {
229
- const ordinalSeverity = ordinalSeverities[section][verdict];
230
- // Increment the applicable total.
231
- standardResult.totals[ordinalSeverity]++;
232
- // Initialize a standard instance.
233
- const what = `[${verdict}] ${raResult.description}`;
234
- const xPath = getAttributeXPath(element.htmlCode);
235
- const instance = {
236
- ruleID,
237
- what,
238
- ordinalSeverity: ordinalSeverities[section][verdict],
239
- count: 1,
240
- catalogIndex: getXPathCatalogIndex(report, xPath)
241
- };
242
- // Add the instance to the standard result.
243
- standardResult.instances.push(instance);
244
- }
245
- };
246
- }
247
- };
248
- }
249
- // Otherwise, i.e. if there were no warnings or failures:
250
- else {
251
- // Delete the rule.
252
- delete assertions[ruleID];
253
- }
254
- };
255
- }
256
- // Otherwise, i.e. if it contains no assertions:
257
- else {
258
- // Report this.
259
- data.prevented = true;
260
- data.error = 'No assertions';
261
- }
126
+ // Otherwise, i.e. if the start succeeds, specify the invariant test options.
127
+ const qualWebOptions = {
128
+ log: {
129
+ console: false,
130
+ file: false
131
+ },
132
+ crawlOptions: {
133
+ maxDepth: 0,
134
+ maxUrls: 1,
135
+ timeout: timeLimit * 1000,
136
+ maxParallelCrawls: 1,
137
+ logging: true
138
+ },
139
+ execute: {
140
+ counter: true
141
+ },
142
+ modules: []
143
+ };
144
+ try {
145
+ // Provide the page content, including the data-xpath attributes.
146
+ qualWebOptions.html = await page.content();
147
+ // Specify which rules to test for, adding a custom execute property for report processing.
148
+ const actSpec = rules ? rules.find(typeRules => typeRules.startsWith('act:')) : null;
149
+ const wcagSpec = rules ? rules.find(typeRules => typeRules.startsWith('wcag:')) : null;
150
+ const bestSpec = rules ? rules.find(typeRules => typeRules.startsWith('best:')) : null;
151
+ if (actSpec) {
152
+ if (actSpec === 'act:') {
153
+ qualWebOptions.execute.act = false;
262
154
  }
263
- // Otherwise, i.e. if the section is missing:
264
155
  else {
265
- // Report this.
266
- data.prevented = true;
267
- data.error = `No ${section} section`;
156
+ const actRules = actSpec.slice(4).split(',').map(num => `QW-ACT-R${num}`);
157
+ qualWebOptions['act-rules'] = { rules: actRules };
158
+ qualWebOptions.modules.push(actRulesModule);
159
+ qualWebOptions.execute.act = true;
268
160
  }
269
- }
270
161
  }
271
- }
272
- // Otherwise, i.e. if the report does not contain a modules property:
273
- else {
274
- // Report this.
275
- data.prevented = true;
276
- data.error = 'No modules';
277
- }
278
- }
279
- // Otherwise, i.e. if the report does not contain a copy of the DOM:
280
- else {
281
- // Report this.
282
- data.prevented = true;
283
- data.error = 'No DOM';
284
- }
285
- // Stop the QualWeb core engine.
286
- await qualWeb.stop();
287
- // Test whether the result is an object.
288
- try {
289
- JSON.stringify(result);
162
+ else {
163
+ qualWebOptions['act-rules'] = {
164
+ levels: ['A', 'AA', 'AAA'],
165
+ principles: ['Perceivable', 'Operable', 'Understandable', 'Robust']
166
+ };
167
+ qualWebOptions.modules.push(actRulesModule);
168
+ qualWebOptions.execute.act = true;
169
+ }
170
+ if (wcagSpec) {
171
+ if (wcagSpec === 'wcag:') {
172
+ qualWebOptions.execute.wcag = false;
173
+ }
174
+ else {
175
+ const wcagTechniques = wcagSpec.slice(5).split(',').map(num => `QW-WCAG-T${num}`);
176
+ qualWebOptions['wcag-techniques'] = { techniques: wcagTechniques };
177
+ qualWebOptions.modules.push(wcagModule);
178
+ qualWebOptions.execute.wcag = true;
179
+ }
180
+ }
181
+ else {
182
+ qualWebOptions['wcag-techniques'] = {
183
+ levels: ['A', 'AA', 'AAA'],
184
+ principles: ['Perceivable', 'Operable', 'Understandable', 'Robust']
185
+ };
186
+ qualWebOptions.modules.push(wcagModule);
187
+ qualWebOptions.execute.wcag = true;
188
+ }
189
+ if (bestSpec) {
190
+ if (bestSpec === 'best:') {
191
+ qualWebOptions.execute.bp = false;
192
+ }
193
+ else {
194
+ const bestPractices = bestSpec.slice(5).split(',').map(num => `QW-BP${num}`);
195
+ qualWebOptions['best-practices'] = { bestPractices };
196
+ qualWebOptions.modules.push(bpModule);
197
+ qualWebOptions.execute.bp = true;
198
+ }
199
+ }
200
+ else {
201
+ qualWebOptions['best-practices'] = {};
202
+ qualWebOptions.modules.push(bpModule);
203
+ qualWebOptions.execute.bp = true;
204
+ }
205
+ let qwReport;
206
+ try {
207
+ // Get the report.
208
+ qwReport = await qualWeb.evaluate(qualWebOptions);
209
+ }
210
+ catch (error) {
211
+ return {
212
+ data: {
213
+ prevented: true,
214
+ error: `qualWeb evaluation failed (${error.message})`
215
+ },
216
+ result
217
+ };
218
+ }
219
+ // Add the report to the result.
220
+ result.nativeResult = qwReport.customHtml;
221
+ const { nativeResult, standardResult } = result;
222
+ // If the report contains, as it should, a copy of the DOM:
223
+ if (nativeResult?.system?.page?.dom) {
224
+ // Delete the copy for parsimony.
225
+ delete nativeResult.system.page.dom;
226
+ const { modules } = nativeResult;
227
+ // If the report contains, as it should, a modules property:
228
+ if (modules) {
229
+ // For each test section in it:
230
+ for (const section of ['act-rules', 'wcag-techniques', 'best-practices']) {
231
+ // If testing in the section was specified:
232
+ if (qualWebOptions[section]) {
233
+ // If the section exists:
234
+ if (modules[section]) {
235
+ const { assertions } = modules[section];
236
+ // If it contains assertions (test results):
237
+ if (assertions) {
238
+ const ruleIDs = Object.keys(assertions);
239
+ // For each rule:
240
+ for (const ruleID of ruleIDs) {
241
+ const ruleAssertions = assertions[ruleID];
242
+ const { metadata } = ruleAssertions;
243
+ // If there were any warnings or failures:
244
+ if (metadata?.warning || metadata?.failed) {
245
+ // Delete nonviolations from the results.
246
+ ruleAssertions.results = ruleAssertions.results.filter(raResult => raResult.verdict !== 'passed');
247
+ // For each test result:
248
+ for (const raResult of ruleAssertions.results) {
249
+ const { elements, verdict } = raResult;
250
+ // If any violations are reported:
251
+ if (elements?.length) {
252
+ // For each violating element:
253
+ for (const element of elements) {
254
+ // Limit the size of its reported excerpt.
255
+ if (element.htmlCode?.length > 2000) {
256
+ element.htmlCode = `${element.htmlCode.slice(0, 2000)} …`;
257
+ }
258
+ // If standard results are to be reported:
259
+ if (standard) {
260
+ const what = `[${verdict}] ${raResult.description}`;
261
+ const xPath = (0, xPath_1.getAttributeXPath)(element.htmlCode);
262
+ // Add an instance to the standard result.
263
+ (0, standard_1.addInstance)(standardResult, {
264
+ ruleID,
265
+ what,
266
+ ordinalSeverity: ordinalSeverities[section][verdict],
267
+ outcome: verdict === 'warning' ? 'cantTell' : 'failed',
268
+ catalogIndex: (0, xPath_1.getXPathCatalogIndex)(report, xPath)
269
+ });
270
+ }
271
+ }
272
+ ;
273
+ }
274
+ }
275
+ ;
276
+ }
277
+ // Otherwise, i.e. if there were no warnings or failures:
278
+ else {
279
+ // Delete the rule.
280
+ delete assertions[ruleID];
281
+ }
282
+ }
283
+ ;
284
+ }
285
+ // Otherwise, i.e. if it contains no assertions:
286
+ else {
287
+ // Report this.
288
+ data.prevented = true;
289
+ data.error = 'No assertions';
290
+ }
291
+ }
292
+ // Otherwise, i.e. if the section is missing:
293
+ else {
294
+ // Report this.
295
+ data.prevented = true;
296
+ data.error = `No ${section} section`;
297
+ }
298
+ }
299
+ }
300
+ }
301
+ // Otherwise, i.e. if the report does not contain a modules property:
302
+ else {
303
+ // Report this.
304
+ data.prevented = true;
305
+ data.error = 'No modules';
306
+ }
307
+ }
308
+ // Otherwise, i.e. if the report does not contain a copy of the DOM:
309
+ else {
310
+ // Report this.
311
+ data.prevented = true;
312
+ data.error = 'No DOM';
313
+ }
314
+ // Stop the QualWeb core engine.
315
+ await qualWeb.stop();
316
+ // Test whether the result is an object.
317
+ try {
318
+ JSON.stringify(result);
319
+ }
320
+ catch (error) {
321
+ data.prevented = true;
322
+ data.error = `QualWeb result cannot be made JSON (${error.message})`;
323
+ }
290
324
  }
291
- catch(error) {
292
- data.prevented = true;
293
- data.error = `QualWeb result cannot be made JSON (${error.message})`;
325
+ catch (error) {
326
+ data.prevented = true;
327
+ data.error = `QualWeb failed (${error.message})`;
294
328
  }
295
- }
296
- catch(error) {
297
- data.prevented = true;
298
- data.error = `QualWeb failed (${error.message})`;
299
- }
300
- return {
301
- data,
302
- result
303
- };
329
+ return {
330
+ data,
331
+ result
332
+ };
304
333
  };
334
+ exports.reporter = reporter;