testaro 78.0.6 → 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 (361) 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 +25 -19
  7. package/CONTAINERS.md +10 -6
  8. package/CONTRIBUTING.md +29 -3
  9. package/Dockerfile +1 -1
  10. package/README.md +75 -20
  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 +373 -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 +313 -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 +63 -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/getSource.js +1 -0
  38. package/procs/job.js +116 -1
  39. package/procs/launch.d.ts +40 -0
  40. package/procs/launch.js +239 -108
  41. package/procs/nu.d.ts +48 -0
  42. package/procs/nu.js +1 -0
  43. package/procs/scope.js +196 -0
  44. package/procs/shoot.d.ts +33 -0
  45. package/procs/shoot.js +3 -1
  46. package/procs/standard.d.ts +18 -0
  47. package/procs/standard.js +83 -0
  48. package/procs/standard.ts +126 -0
  49. package/procs/testAct.js +145 -0
  50. package/procs/testaro.d.ts +20 -0
  51. package/procs/testaro.js +237 -189
  52. package/procs/testaro.ts +321 -0
  53. package/procs/userPath.js +126 -0
  54. package/procs/xPath.d.ts +4 -0
  55. package/procs/xPath.js +82 -64
  56. package/procs/xPath.ts +106 -0
  57. package/procs/xPathScript.d.ts +6 -0
  58. package/procs/xPathScript.js +70 -0
  59. package/run.js +3 -2
  60. package/surea11y/README.md +44 -0
  61. package/surea11y/surea11y.browser.js +14 -0
  62. package/testaro/adbID.d.ts +3 -0
  63. package/testaro/adbID.js +39 -41
  64. package/testaro/adbID.ts +66 -0
  65. package/testaro/allCapStyle.d.ts +3 -0
  66. package/testaro/allCapStyle.js +32 -34
  67. package/testaro/allCapStyle.ts +55 -0
  68. package/testaro/allCaps.d.ts +16 -0
  69. package/testaro/allCaps.js +179 -151
  70. package/testaro/allCaps.ts +228 -0
  71. package/testaro/allHidden.d.ts +13 -0
  72. package/testaro/allHidden.js +30 -30
  73. package/testaro/allHidden.ts +50 -0
  74. package/testaro/allSlanted.d.ts +3 -0
  75. package/testaro/allSlanted.js +31 -33
  76. package/testaro/allSlanted.ts +54 -0
  77. package/testaro/altScheme.d.ts +3 -0
  78. package/testaro/altScheme.js +28 -30
  79. package/testaro/altScheme.ts +50 -0
  80. package/testaro/attVal.d.ts +3 -0
  81. package/testaro/attVal.js +21 -21
  82. package/testaro/attVal.ts +52 -0
  83. package/testaro/autocomplete.d.ts +3 -0
  84. package/testaro/autocomplete.js +60 -75
  85. package/testaro/autocomplete.ts +101 -0
  86. package/testaro/bulk.d.ts +13 -0
  87. package/testaro/bulk.js +33 -33
  88. package/testaro/bulk.ts +55 -0
  89. package/testaro/buttonMenu.d.ts +9 -0
  90. package/testaro/buttonMenu.js +318 -319
  91. package/testaro/buttonMenu.ts +391 -0
  92. package/testaro/captionLoc.d.ts +3 -0
  93. package/testaro/captionLoc.js +18 -20
  94. package/testaro/captionLoc.ts +40 -0
  95. package/testaro/datalistRef.d.ts +3 -0
  96. package/testaro/datalistRef.js +34 -36
  97. package/testaro/datalistRef.ts +55 -0
  98. package/testaro/distortion.d.ts +3 -0
  99. package/testaro/distortion.js +58 -26
  100. package/testaro/distortion.ts +81 -0
  101. package/testaro/docType.d.ts +15 -0
  102. package/testaro/docType.js +26 -25
  103. package/testaro/docType.ts +45 -0
  104. package/testaro/dupAtt.d.ts +16 -0
  105. package/testaro/dupAtt.js +114 -104
  106. package/testaro/dupAtt.ts +144 -0
  107. package/testaro/elements.d.ts +6 -0
  108. package/testaro/elements.js +153 -153
  109. package/testaro/elements.ts +215 -0
  110. package/testaro/embAc.d.ts +3 -0
  111. package/testaro/embAc.js +20 -20
  112. package/testaro/embAc.ts +40 -0
  113. package/testaro/focAll.d.ts +13 -0
  114. package/testaro/focAll.js +186 -191
  115. package/testaro/focAll.ts +217 -0
  116. package/testaro/focAndOp.d.ts +3 -0
  117. package/testaro/focAndOp.js +101 -104
  118. package/testaro/focAndOp.ts +128 -0
  119. package/testaro/focInd.d.ts +3 -0
  120. package/testaro/focInd.js +65 -66
  121. package/testaro/focInd.ts +96 -0
  122. package/testaro/focVis.d.ts +3 -0
  123. package/testaro/focVis.js +29 -30
  124. package/testaro/focVis.ts +52 -0
  125. package/testaro/headEl.d.ts +10 -0
  126. package/testaro/headEl.js +62 -62
  127. package/testaro/headEl.ts +82 -0
  128. package/testaro/headingAmb.d.ts +3 -0
  129. package/testaro/headingAmb.js +55 -63
  130. package/testaro/headingAmb.ts +72 -0
  131. package/testaro/hovInd.d.ts +12 -0
  132. package/testaro/hovInd.js +164 -130
  133. package/testaro/hovInd.ts +199 -0
  134. package/testaro/hover.d.ts +3 -0
  135. package/testaro/hover.js +156 -126
  136. package/testaro/hover.ts +154 -0
  137. package/testaro/hr.d.ts +3 -0
  138. package/testaro/hr.js +15 -17
  139. package/testaro/hr.ts +36 -0
  140. package/testaro/imageLink.d.ts +3 -0
  141. package/testaro/imageLink.js +18 -20
  142. package/testaro/imageLink.ts +42 -0
  143. package/testaro/labClash.d.ts +3 -0
  144. package/testaro/labClash.js +32 -33
  145. package/testaro/labClash.ts +54 -0
  146. package/testaro/legendLoc.d.ts +3 -0
  147. package/testaro/legendLoc.js +18 -20
  148. package/testaro/legendLoc.ts +42 -0
  149. package/testaro/lineHeight.d.ts +3 -0
  150. package/testaro/lineHeight.js +44 -48
  151. package/testaro/lineHeight.ts +70 -0
  152. package/testaro/linkAmb.d.ts +7 -0
  153. package/testaro/linkAmb.js +80 -80
  154. package/testaro/linkAmb.ts +105 -0
  155. package/testaro/linkExt.d.ts +3 -0
  156. package/testaro/linkExt.js +14 -16
  157. package/testaro/linkExt.ts +35 -0
  158. package/testaro/linkOldAtt.d.ts +3 -0
  159. package/testaro/linkOldAtt.js +26 -28
  160. package/testaro/linkOldAtt.ts +48 -0
  161. package/testaro/linkTo.d.ts +3 -0
  162. package/testaro/linkTo.js +23 -22
  163. package/testaro/linkTo.ts +43 -0
  164. package/testaro/linkUl.d.ts +3 -0
  165. package/testaro/linkUl.js +31 -34
  166. package/testaro/linkUl.ts +54 -0
  167. package/testaro/miniText.d.ts +3 -0
  168. package/testaro/miniText.js +42 -44
  169. package/testaro/miniText.ts +68 -0
  170. package/testaro/motion.d.ts +10 -0
  171. package/testaro/motion.js +93 -96
  172. package/testaro/motion.ts +125 -0
  173. package/testaro/nonTable.d.ts +3 -0
  174. package/testaro/nonTable.js +40 -45
  175. package/testaro/nonTable.ts +66 -0
  176. package/testaro/optRoleSel.d.ts +3 -0
  177. package/testaro/optRoleSel.js +17 -19
  178. package/testaro/optRoleSel.ts +41 -0
  179. package/testaro/phOnly.d.ts +3 -0
  180. package/testaro/phOnly.js +19 -21
  181. package/testaro/phOnly.ts +43 -0
  182. package/testaro/pseudoP.d.ts +3 -0
  183. package/testaro/pseudoP.js +37 -38
  184. package/testaro/pseudoP.ts +59 -0
  185. package/testaro/radioSet.d.ts +3 -0
  186. package/testaro/radioSet.js +58 -59
  187. package/testaro/radioSet.ts +79 -0
  188. package/testaro/registry.d.ts +63 -0
  189. package/testaro/registry.js +67 -0
  190. package/testaro/registry.ts +141 -0
  191. package/testaro/role.d.ts +3 -0
  192. package/testaro/role.js +28 -29
  193. package/testaro/role.ts +53 -0
  194. package/testaro/secHeading.d.ts +3 -0
  195. package/testaro/secHeading.js +31 -33
  196. package/testaro/secHeading.ts +53 -0
  197. package/testaro/styleDiff.d.ts +25 -0
  198. package/testaro/styleDiff.js +249 -252
  199. package/testaro/styleDiff.ts +303 -0
  200. package/testaro/tabNav.d.ts +33 -0
  201. package/testaro/tabNav.js +273 -342
  202. package/testaro/tabNav.ts +454 -0
  203. package/testaro/targetsNear.d.ts +9 -0
  204. package/testaro/targetsNear.js +131 -132
  205. package/testaro/targetsNear.ts +160 -0
  206. package/testaro/textNodes.d.ts +6 -0
  207. package/testaro/textNodes.js +139 -135
  208. package/testaro/textNodes.ts +185 -0
  209. package/testaro/textSem.d.ts +3 -0
  210. package/testaro/textSem.js +26 -28
  211. package/testaro/textSem.ts +47 -0
  212. package/testaro/title.d.ts +9 -0
  213. package/testaro/title.js +16 -13
  214. package/testaro/title.ts +31 -0
  215. package/testaro/titledEl.d.ts +3 -0
  216. package/testaro/titledEl.js +16 -18
  217. package/testaro/titledEl.ts +38 -0
  218. package/testaro/zIndex.d.ts +3 -0
  219. package/testaro/zIndex.js +20 -22
  220. package/testaro/zIndex.ts +42 -0
  221. package/tests/alfa.d.ts +45 -0
  222. package/tests/alfa.js +139 -141
  223. package/tests/alfa.ts +214 -0
  224. package/tests/aslint.d.ts +33 -0
  225. package/tests/aslint.js +273 -249
  226. package/tests/aslint.ts +301 -0
  227. package/tests/axe.d.ts +27 -0
  228. package/tests/axe.js +200 -200
  229. package/tests/axe.ts +277 -0
  230. package/tests/ed11y.d.ts +28 -0
  231. package/tests/ed11y.js +142 -99
  232. package/tests/ed11y.ts +178 -0
  233. package/tests/htmlcs.d.ts +21 -0
  234. package/tests/htmlcs.js +175 -140
  235. package/tests/htmlcs.ts +181 -0
  236. package/tests/ibm.d.ts +52 -0
  237. package/tests/ibm.js +165 -166
  238. package/tests/ibm.ts +251 -0
  239. package/tests/nuVal.d.ts +13 -0
  240. package/tests/nuVal.js +107 -112
  241. package/tests/nuVal.ts +145 -0
  242. package/tests/nuVnu.d.ts +15 -0
  243. package/tests/nuVnu.js +142 -111
  244. package/tests/nuVnu.ts +144 -0
  245. package/tests/pour.d.ts +31 -0
  246. package/tests/pour.js +242 -0
  247. package/tests/pour.ts +273 -0
  248. package/tests/qualWeb.d.ts +39 -0
  249. package/tests/qualWeb.js +303 -272
  250. package/tests/qualWeb.ts +415 -0
  251. package/tests/surea11y.d.ts +33 -0
  252. package/tests/surea11y.js +288 -0
  253. package/tests/surea11y.ts +334 -0
  254. package/tests/testaro.d.ts +25 -0
  255. package/tests/testaro.js +746 -652
  256. package/tests/testaro.ts +862 -0
  257. package/tests/wave.d.ts +46 -0
  258. package/tests/wave.js +167 -177
  259. package/tests/wave.ts +252 -0
  260. package/tsconfig.json +17 -0
  261. package/types.d.ts +243 -0
  262. package/types.js +10 -0
  263. package/types.ts +376 -0
  264. package/validation/act/README.md +46 -0
  265. package/validation/act/capture.js +424 -0
  266. package/validation/act/chromium-issue-draft.md +66 -0
  267. package/validation/act/fp-triage-2026-08-22.md +86 -0
  268. package/validation/act/isolation-notes.md +159 -0
  269. package/validation/act/playwright-issue-draft.md +73 -0
  270. package/validation/act/propose-mappings.js +0 -0
  271. package/validation/act/repro-cdp-raw.js +105 -0
  272. package/validation/act/repro-metarefresh.js +65 -0
  273. package/validation/act/score.js +184 -0
  274. package/validation/act/stage3a-stress-report.md +69 -0
  275. package/validation/act/stage3b-mapping-proposals.md +94 -0
  276. package/validation/act/stage3b-triage-draft.md +138 -0
  277. package/validation/act/surea11y-track-a-2026-09-01.md +50 -0
  278. package/validation/executors/netWatch.js +180 -90
  279. package/validation/executors/test.js +17 -2
  280. package/validation/executors/tests.js +118 -10
  281. package/validation/jobs/reports/raw/260901T1000-surea11y-validation.json +964 -0
  282. package/validation/jobs/todo/240101T1200-simple-example.json +14 -6
  283. package/validation/jobs/todo/240101T1300-shoot-example.json +2 -1
  284. package/validation/jobs/todo/260821T1900-pour-validation.json +45 -0
  285. package/validation/jobs/todo/260901T1000-surea11y-validation.json +45 -0
  286. package/validation/knownFailures.json +1 -0
  287. package/validation/tests/jobProperties/adbID.json +27 -2
  288. package/validation/tests/jobProperties/{focOp.json → allCapStyle.json} +56 -53
  289. package/validation/tests/jobProperties/allCaps.json +25 -0
  290. package/validation/tests/jobProperties/allHidden.json +133 -13
  291. package/validation/tests/jobProperties/allSlanted.json +3 -3
  292. package/validation/tests/jobProperties/altScheme.json +23 -8
  293. package/validation/tests/jobProperties/attVal.json +57 -57
  294. package/validation/tests/jobProperties/autocomplete.json +11 -1
  295. package/validation/tests/jobProperties/bulk.json +6 -1
  296. package/validation/tests/jobProperties/buttonMenu.json +63 -42
  297. package/validation/tests/jobProperties/captionLoc.json +1 -6
  298. package/validation/tests/jobProperties/checkpoint-browser.json +401 -0
  299. package/validation/tests/jobProperties/checkpoint-page.json +397 -0
  300. package/validation/tests/jobProperties/checkpoint.json +395 -0
  301. package/validation/tests/jobProperties/datalistRef.json +20 -5
  302. package/validation/tests/jobProperties/distortion.json +28 -3
  303. package/validation/tests/jobProperties/docType.json +2 -2
  304. package/validation/tests/jobProperties/dupAtt.json +48 -33
  305. package/validation/tests/jobProperties/elements.json +28 -28
  306. package/validation/tests/jobProperties/embAc.json +36 -31
  307. package/validation/tests/jobProperties/focAndOp.json +284 -0
  308. package/validation/tests/jobProperties/focInd.json +34 -34
  309. package/validation/tests/jobProperties/focVis.json +1 -1
  310. package/validation/tests/jobProperties/hover.json +39 -37
  311. package/validation/tests/jobProperties/hr.json +13 -3
  312. package/validation/tests/jobProperties/imageLink.json +0 -5
  313. package/validation/tests/jobProperties/labClash.json +68 -33
  314. package/validation/tests/jobProperties/legendLoc.json +1 -6
  315. package/validation/tests/jobProperties/lineHeight.json +2 -2
  316. package/validation/tests/jobProperties/linkAmb.json +13 -18
  317. package/validation/tests/jobProperties/linkExt.json +1 -1
  318. package/validation/tests/jobProperties/linkOldAtt.json +12 -2
  319. package/validation/tests/jobProperties/linkTo.json +1 -1
  320. package/validation/tests/jobProperties/linkUl.json +65 -65
  321. package/validation/tests/jobProperties/miniText.json +7 -2
  322. package/validation/tests/jobProperties/motion.json +4 -50
  323. package/validation/tests/jobProperties/nonTable.json +48 -3
  324. package/validation/tests/jobProperties/optRoleSel.json +12 -2
  325. package/validation/tests/jobProperties/phOnly.json +6 -16
  326. package/validation/tests/jobProperties/pseudoP.json +17 -2
  327. package/validation/tests/jobProperties/radioSet.json +30 -30
  328. package/validation/tests/jobProperties/role.json +25 -5
  329. package/validation/tests/jobProperties/secHeading.json +26 -21
  330. package/validation/tests/jobProperties/styleDiff.json +35 -5
  331. package/validation/tests/jobProperties/tabNav.json +3 -1
  332. package/validation/tests/jobProperties/targetsNear.json +237 -0
  333. package/validation/tests/jobProperties/textNodes.json +29 -29
  334. package/validation/tests/jobProperties/textSem.json +26 -1
  335. package/validation/tests/jobProperties/title.json +12 -2
  336. package/validation/tests/jobProperties/titledEl.json +39 -9
  337. package/validation/tests/jobProperties/userPath.json +317 -0
  338. package/validation/tests/jobProperties/zIndex.json +40 -35
  339. package/validation/tests/targets/allCapStyle/index.html +26 -0
  340. package/validation/tests/targets/checkpoint/index.html +38 -0
  341. package/validation/tests/targets/datalistRef/index.html +1 -1
  342. package/validation/tests/targets/focAndOp/bad.html +29 -0
  343. package/validation/tests/targets/{focOp → focAndOp}/good.html +3 -1
  344. package/validation/tests/targets/focInd/bad.html +2 -1
  345. package/validation/tests/targets/headEl/index.html +10 -1
  346. package/validation/tests/targets/{targetSmall → targetsNear}/index.html +15 -1
  347. package/validation/tests/targets/userPath/index.html +42 -0
  348. package/validation/validateTest.js +62 -10
  349. package/.claude/settings.local.json +0 -11
  350. package/.eslintrc.json +0 -41
  351. package/htmlcs/.eslintrc.json +0 -67
  352. package/memory/MEMORY.md +0 -3
  353. package/memory/project_validation_pause.md +0 -10
  354. package/validation/tests/jobProperties/linkTitle.json +0 -127
  355. package/validation/tests/jobProperties/opFoc.json +0 -164
  356. package/validation/tests/jobProperties/targetSmall.json +0 -152
  357. package/validation/tests/jobProperties/targetTiny.json +0 -142
  358. package/validation/tests/targets/focOp/bad.html +0 -25
  359. package/validation/tests/targets/linkTitle/index.html +0 -24
  360. package/validation/tests/targets/opFoc/bad.html +0 -26
  361. package/validation/tests/targets/opFoc/good.html +0 -23
@@ -1,275 +1,272 @@
1
+ "use strict";
1
2
  /*
2
3
  © 2021–2024 CVS Health and/or one of its affiliates. All rights reserved.
4
+ © 2026 Jeff Witt.
3
5
  © 2026 Jonathan Robert Pool.
4
6
 
5
7
  Licensed under the MIT License. See LICENSE file at the project root or https://opensource.org/license/mit/ for details.
6
8
 
7
9
  SPDX-License-Identifier: MIT
8
10
  */
9
-
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.reporter = void 0;
13
+ const xPath_1 = require("../procs/xPath");
10
14
  /*
11
15
  styleDiff
12
16
  This test reports style differences among links, buttons, and headings. It assumes that an accessible page employs few or only one style for adjacent links, and likewise for list links, buttons, and headings at each level. The test considers only particular style properties, listed in the 'mainStyles' and 'headingStyles' arrays.
17
+ Compiled to styleDiff.js by tsc (issue #73); edit this file, not the emitted one.
13
18
  */
14
-
15
- // IMPORTS
16
-
17
- const {getXPathCatalogIndex} = require('../procs/xPath');
18
-
19
19
  // FUNCTIONS
20
-
21
20
  // Returns an object classifying the links in a page by layout.
22
- const linksByType = async page => await page.evaluateHandle(() => {
23
- // FUNCTION DEFINITIONS START
24
- // Removes spacing characters from a text.
25
- const despace = text => text.replace(/\s/g, '');
26
- // Returns whether a list is a list entirely of links.
27
- const isLinkList = list => {
28
- const listItems = Array.from(list.children);
29
- if (listItems.length > 1) {
30
- return listItems.length > 1 && listItems.every(item => {
31
- if (item.tagName === 'LI') {
32
- const {children} = item;
33
- if (children.length === 1) {
34
- const link = children[0];
35
- if (link.tagName === 'A') {
36
- const itemText = despace(item.textContent);
37
- const linkText = despace(link.textContent);
38
- return itemText.length === linkText.length;
39
- }
40
- else {
41
- return false;
42
- }
43
- }
44
- else {
45
- return false;
46
- }
21
+ const linksByType = async (page) => await page.evaluateHandle(() => {
22
+ // FUNCTION DEFINITIONS START
23
+ // Removes spacing characters from a text.
24
+ const despace = (text) => text.replace(/\s/g, '');
25
+ // Returns whether a list is a list entirely of links.
26
+ const isLinkList = (list) => {
27
+ const listItems = Array.from(list.children);
28
+ if (listItems.length > 1) {
29
+ return listItems.length > 1 && listItems.every(item => {
30
+ if (item.tagName === 'LI') {
31
+ const { children } = item;
32
+ if (children.length === 1) {
33
+ const link = children[0];
34
+ if (link.tagName === 'A') {
35
+ const itemText = despace(item.textContent);
36
+ const linkText = despace(link.textContent);
37
+ return itemText.length === linkText.length;
38
+ }
39
+ else {
40
+ return false;
41
+ }
42
+ }
43
+ else {
44
+ return false;
45
+ }
46
+ }
47
+ else {
48
+ return false;
49
+ }
50
+ });
47
51
  }
48
52
  else {
49
- return false;
53
+ return false;
50
54
  }
51
- });
52
- }
53
- else {
54
- return false;
55
- }
56
- };
57
- // FUNCTION DEFINITIONS END
58
- // Identify the lists in the page.
59
- const lists = Array.from(document.body.querySelectorAll('ul, ol'));
60
- // Initialize an array of list links.
61
- const listLinks = [];
62
- // For each one:
63
- lists.forEach(list => {
64
- // If it is a list of links:
65
- if (isLinkList(list)) {
66
- // Choose one of the links randomly, assuming they have uniform styles.
67
- const links = Array.from(list.querySelectorAll('a'));
68
- const randomIndex = Math.floor(Math.random() * links.length);
69
- const randomLink = links[randomIndex];
70
- // Add it to the array.
71
- listLinks.push(randomLink);
72
- }
73
- });
74
- // Identify the inline links in the page.
75
- const allLinks = Array.from(document.body.querySelectorAll('a'));
76
- const inlineLinks = allLinks.filter(link => ! listLinks.includes(link));
77
- // Return the data.
78
- return {
79
- adjacent: inlineLinks,
80
- list: listLinks
81
- };
82
- });
83
- // Runs the test and returns the result.
84
- exports.reporter = async (page, report, _, withItems) => {
85
- // Get an object with arrays of list links and adjacent links as properties.
86
- const linkTypes = await linksByType(page);
87
- const catalogIndex = getXPathCatalogIndex(report, '/html/body');
88
- return await page.evaluate(args => {
89
- const [linkTypes, withItems, catalogIndex] = args;
90
- const {body} = document;
91
- // Identify the settable style properties to be compared for all tag names.
92
- const mainStyles = [
93
- 'fontStyle',
94
- 'fontWeight',
95
- 'opacity',
96
- 'textDecorationLine',
97
- 'textDecorationStyle',
98
- 'textDecorationThickness'
99
- ];
100
- // Identify those only for buttons.
101
- const buttonStyles = [
102
- 'borderStyle',
103
- 'borderWidth',
104
- 'height',
105
- 'lineHeight',
106
- 'maxHeight',
107
- 'maxWidth',
108
- 'minHeight',
109
- 'minWidth',
110
- 'outlineOffset',
111
- 'outlineStyle',
112
- 'outlineWidth'
113
- ];
114
- // Identify those for headings.
115
- const headingStyles = [
116
- 'color',
117
- 'fontSize'
118
- ];
119
- // Identify those for list links.
120
- const listLinkStyles = [
121
- 'color',
122
- 'fontSize',
123
- 'lineHeight'
124
- ];
125
- // Initialize the data to be returned.
126
- const data = {
127
- mainStyles,
128
- buttonStyles,
129
- headingStyles,
130
- listLinkStyles,
131
- totals: {}
132
55
  };
133
- if (withItems) {
134
- data.items = {};
135
- }
136
- // Initialize an object of elements to be analyzed, including links.
137
- const elements = {
138
- buttons: [],
139
- headings: {
140
- h1: [],
141
- h2: [],
142
- h3: [],
143
- h4: [],
144
- h5: [],
145
- h6: []
146
- },
147
- links: {
148
- adjacent: linkTypes.adjacent,
149
- list: linkTypes.list
150
- }
151
- };
152
- // Identify the heading tag names to be analyzed.
153
- const headingNames = Object.keys(elements.headings);
154
- // Add the buttons to the object.
155
- elements.buttons = Array.from(body.querySelectorAll('button, input[type=button]'));
156
- // For each heading tag name:
157
- headingNames.forEach(tagName => {
158
- // Add its elements to the object.
159
- elements.headings[tagName] = Array.from(body.getElementsByTagName(tagName));
160
- });
161
- // FUNCTION DEFINITION START
162
- // Tabulates the distribution of style properties for elements of a type.
163
- const tallyStyles = (typeName, elements, typeStyles, withItems) => {
164
- // If there are any elements:
165
- const elementCount = elements.length;
166
- if (elementCount) {
167
- const styleProps = {};
168
- const styleTexts = {};
169
- // For each element:
170
- elements.forEach(element => {
171
- // Get its values on the style properties to be compared.
172
- const styleDec = window.getComputedStyle(element);
173
- const style = {};
174
- const styles = mainStyles.concat(typeStyles);
175
- styles.forEach(styleName => {
176
- style[styleName] = styleDec[styleName];
177
- });
178
- // Get a text representation of the style, limited to those properties.
179
- const styleText = JSON.stringify(style);
180
- // Increment the total of elements with that style.
181
- styleTexts[styleText] = ++styleTexts[styleText] || 1;
182
- // If details are to be reported:
183
- if (withItems) {
184
- // Add the element’s values and text to the style details.
185
- if (! styleProps[typeName]) {
186
- styleProps[typeName] = {};
187
- }
188
- const elementText = (element.textContent.trim() || element.outerHTML.trim())
189
- .replace(/\s+/g, ' ')
190
- .slice(0, 100);
191
- // For each style property being compared:
192
- styles.forEach(styleName => {
193
- if (! styleProps[typeName][styleName]) {
194
- styleProps[typeName][styleName] = {};
195
- }
196
- if (! styleProps[typeName][styleName][style[styleName]]) {
197
- styleProps[typeName][styleName][style[styleName]] = [];
198
- }
199
- // Add the element text to the style details.
200
- styleProps[typeName][styleName][style[styleName]].push(elementText);
201
- });
202
- }
203
- });
204
- // Add the total to the result.
205
- data.totals[typeName] = {total: elementCount};
206
- const styleCounts = Object.values(styleTexts);
207
- // If the elements of the type differ in style:
208
- if (styleCounts.length > 1) {
209
- // Add the distribution of its style counts to the result.
210
- data.totals[typeName].subtotals = styleCounts.sort((a, b) => b - a);
211
- // If details are to be reported:
212
- if (withItems) {
213
- // Delete the data on uniform style properties.
214
- Object.keys(styleProps[typeName]).forEach(styleName => {
215
- if (Object.keys(styleProps[typeName][styleName]).length === 1) {
216
- delete styleProps[typeName][styleName];
217
- }
218
- });
219
- // Add the element values and texts to the result.
220
- data.items[typeName] = styleProps[typeName];
221
- }
56
+ // FUNCTION DEFINITIONS END
57
+ // Identify the lists in the page.
58
+ const lists = Array.from(document.body.querySelectorAll('ul, ol'));
59
+ // Initialize an array of list links.
60
+ const listLinks = [];
61
+ // For each one:
62
+ lists.forEach(list => {
63
+ // If it is a list of links:
64
+ if (isLinkList(list)) {
65
+ // Add all its links to the array. Formerly one link per list was sampled as a representative, which made totals vary run to run (issue #113) and let the unsampled list links be counted as inline links, so a uniformly styled link list was reported as an inline-link style difference. Using every list link is deterministic and also detects style differences within a list.
66
+ const links = Array.from(list.querySelectorAll(':scope > li > a'));
67
+ listLinks.push(...links);
222
68
  }
223
- }
224
- };
225
- // FUNCTION DEFINITION END
226
- // Report the style-property distributions for the element types.
227
- tallyStyles('button', elements.buttons, buttonStyles, withItems);
228
- tallyStyles('adjacentLink', elements.links.adjacent, [], withItems);
229
- tallyStyles('listLink', elements.links.list, listLinkStyles, withItems);
230
- headingNames.forEach(headingName => {
231
- tallyStyles(headingName, elements.headings[headingName], headingStyles, withItems);
232
- });
233
- // Report the standandardized data.
234
- const totals = [0, 0, 0, 0];
235
- const standardInstances = [];
236
- const elementData = {
237
- adjacentLink: [0, 'In-line links', 'A'],
238
- listLink: [1, 'Links in columns', 'A'],
239
- button: [2, 'Buttons', 'BUTTON'],
240
- h1: [3, 'Level-1 headings', 'H1'],
241
- h2: [3, 'Level-2 headings', 'H2'],
242
- h3: [3, 'Level-3 headings', 'H3'],
243
- h4: [3, 'Level-4 headings', 'H4'],
244
- h5: [3, 'Level-5 headings', 'H5'],
245
- h6: [3, 'Level-6 headings', 'H6'],
246
- };
247
- // For each eligible element type:
248
- Object.keys(elementData).forEach(elementName => {
249
- // If it has more than 1 style:
250
- const elementTotal = data.totals[elementName];
251
- if (elementTotal && elementTotal.subtotals) {
252
- const currentData = elementData[elementName];
253
- const severity = currentData[0];
254
- const elementSubtotals = elementTotal.subtotals;
255
- // Treat the count of its styles in excess of 1 as the instance count for that element type.
256
- const extraCount = elementSubtotals.length - 1;
257
- totals[severity] += extraCount;
258
- // Add a summary standard instance for that element type.
259
- standardInstances.push({
260
- ruleID: 'styleDiff',
261
- what: `${currentData[1]} have ${elementSubtotals.length} different styles`,
262
- ordinalSeverity: severity,
263
- count: extraCount,
264
- catalogIndex
265
- });
266
- }
267
69
  });
268
- // Return the result.
70
+ // Identify the inline links in the page, i.e. the links that are not list links.
71
+ const allLinks = Array.from(document.body.querySelectorAll('a'));
72
+ const inlineLinks = allLinks.filter(link => !listLinks.includes(link));
73
+ // Return the data.
269
74
  return {
270
- data,
271
- totals,
272
- standardInstances
75
+ adjacent: inlineLinks,
76
+ list: listLinks
273
77
  };
274
- }, [linkTypes, withItems, catalogIndex]);
78
+ });
79
+ // Runs the test and returns the result.
80
+ const reporter = async (page, report, _, withItems) => {
81
+ // Get an object with arrays of list links and adjacent links as properties.
82
+ const linkTypes = await linksByType(page);
83
+ const catalogIndex = (0, xPath_1.getXPathCatalogIndex)(report, '/html/body');
84
+ return await page.evaluate(args => {
85
+ const [linkTypes, withItems, catalogIndex] = args;
86
+ const { body } = document;
87
+ // Identify the settable style properties to be compared for all tag names.
88
+ const mainStyles = [
89
+ 'fontStyle',
90
+ 'fontWeight',
91
+ 'opacity',
92
+ 'textDecorationLine',
93
+ 'textDecorationStyle',
94
+ 'textDecorationThickness'
95
+ ];
96
+ // Identify those only for buttons.
97
+ const buttonStyles = [
98
+ 'borderStyle',
99
+ 'borderWidth',
100
+ 'height',
101
+ 'lineHeight',
102
+ 'maxHeight',
103
+ 'maxWidth',
104
+ 'minHeight',
105
+ 'minWidth',
106
+ 'outlineOffset',
107
+ 'outlineStyle',
108
+ 'outlineWidth'
109
+ ];
110
+ // Identify those for headings.
111
+ const headingStyles = [
112
+ 'color',
113
+ 'fontSize'
114
+ ];
115
+ // Identify those for list links.
116
+ const listLinkStyles = [
117
+ 'color',
118
+ 'fontSize',
119
+ 'lineHeight'
120
+ ];
121
+ // Initialize the data to be returned.
122
+ const data = {
123
+ mainStyles,
124
+ buttonStyles,
125
+ headingStyles,
126
+ listLinkStyles,
127
+ totals: {}
128
+ };
129
+ if (withItems) {
130
+ data.items = {};
131
+ }
132
+ // Initialize an object of elements to be analyzed, including links.
133
+ const elements = {
134
+ buttons: [],
135
+ headings: {
136
+ h1: [],
137
+ h2: [],
138
+ h3: [],
139
+ h4: [],
140
+ h5: [],
141
+ h6: []
142
+ },
143
+ links: {
144
+ adjacent: linkTypes.adjacent,
145
+ list: linkTypes.list
146
+ }
147
+ };
148
+ // Identify the heading tag names to be analyzed.
149
+ const headingNames = Object.keys(elements.headings);
150
+ // Add the buttons to the object.
151
+ elements.buttons = Array.from(body.querySelectorAll('button, input[type=button]'));
152
+ // For each heading tag name:
153
+ headingNames.forEach(tagName => {
154
+ // Add its elements to the object.
155
+ elements.headings[tagName] = Array.from(body.getElementsByTagName(tagName));
156
+ });
157
+ // FUNCTION DEFINITION START
158
+ // Tabulates the distribution of style properties for elements of a type.
159
+ const tallyStyles = (typeName, elements, typeStyles, withItems) => {
160
+ // If there are any elements:
161
+ const elementCount = elements.length;
162
+ if (elementCount) {
163
+ const styleProps = {};
164
+ const styleTexts = {};
165
+ // For each element:
166
+ elements.forEach(element => {
167
+ // Get its values on the style properties to be compared.
168
+ const styleDec = window.getComputedStyle(element);
169
+ const style = {};
170
+ const styles = mainStyles.concat(typeStyles);
171
+ styles.forEach(styleName => {
172
+ style[styleName] = styleDec[styleName];
173
+ });
174
+ // Get a text representation of the style, limited to those properties.
175
+ const styleText = JSON.stringify(style);
176
+ // Increment the total of elements with that style.
177
+ styleTexts[styleText] = ++styleTexts[styleText] || 1;
178
+ // If details are to be reported:
179
+ if (withItems) {
180
+ // Add the element’s values and text to the style details.
181
+ if (!styleProps[typeName]) {
182
+ styleProps[typeName] = {};
183
+ }
184
+ const elementText = (element.textContent.trim() || element.outerHTML.trim())
185
+ .replace(/\s+/g, ' ')
186
+ .slice(0, 100);
187
+ // For each style property being compared:
188
+ styles.forEach(styleName => {
189
+ if (!styleProps[typeName][styleName]) {
190
+ styleProps[typeName][styleName] = {};
191
+ }
192
+ if (!styleProps[typeName][styleName][style[styleName]]) {
193
+ styleProps[typeName][styleName][style[styleName]] = [];
194
+ }
195
+ // Add the element text to the style details.
196
+ styleProps[typeName][styleName][style[styleName]].push(elementText);
197
+ });
198
+ }
199
+ });
200
+ // Add the total to the result.
201
+ data.totals[typeName] = { total: elementCount };
202
+ const styleCounts = Object.values(styleTexts);
203
+ // If the elements of the type differ in style:
204
+ if (styleCounts.length > 1) {
205
+ // Add the distribution of its style counts to the result.
206
+ data.totals[typeName].subtotals = styleCounts.sort((a, b) => b - a);
207
+ // If details are to be reported:
208
+ if (withItems) {
209
+ // Delete the data on uniform style properties.
210
+ Object.keys(styleProps[typeName]).forEach(styleName => {
211
+ if (Object.keys(styleProps[typeName][styleName]).length === 1) {
212
+ delete styleProps[typeName][styleName];
213
+ }
214
+ });
215
+ // Add the element values and texts to the result.
216
+ data.items[typeName] = styleProps[typeName];
217
+ }
218
+ }
219
+ }
220
+ };
221
+ // FUNCTION DEFINITION END
222
+ // Report the style-property distributions for the element types.
223
+ tallyStyles('button', elements.buttons, buttonStyles, withItems);
224
+ tallyStyles('adjacentLink', elements.links.adjacent, [], withItems);
225
+ tallyStyles('listLink', elements.links.list, listLinkStyles, withItems);
226
+ headingNames.forEach(headingName => {
227
+ tallyStyles(headingName, elements.headings[headingName], headingStyles, withItems);
228
+ });
229
+ // Report the standandardized data.
230
+ const totals = [0, 0, 0, 0];
231
+ const standardInstances = [];
232
+ const elementData = {
233
+ adjacentLink: [0, 'In-line links', 'A'],
234
+ listLink: [1, 'Links in columns', 'A'],
235
+ button: [2, 'Buttons', 'BUTTON'],
236
+ h1: [3, 'Level-1 headings', 'H1'],
237
+ h2: [3, 'Level-2 headings', 'H2'],
238
+ h3: [3, 'Level-3 headings', 'H3'],
239
+ h4: [3, 'Level-4 headings', 'H4'],
240
+ h5: [3, 'Level-5 headings', 'H5'],
241
+ h6: [3, 'Level-6 headings', 'H6'],
242
+ };
243
+ // For each eligible element type:
244
+ Object.keys(elementData).forEach(elementName => {
245
+ // If it has more than 1 style:
246
+ const elementTotal = data.totals[elementName];
247
+ if (elementTotal && elementTotal.subtotals) {
248
+ const currentData = elementData[elementName];
249
+ const severity = currentData[0];
250
+ const elementSubtotals = elementTotal.subtotals;
251
+ // Treat the count of its styles in excess of 1 as the instance count for that element type.
252
+ const extraCount = elementSubtotals.length - 1;
253
+ totals[severity] += extraCount;
254
+ // Add a summary standard instance for that element type.
255
+ standardInstances.push({
256
+ ruleID: 'styleDiff',
257
+ what: `${currentData[1]} have ${elementSubtotals.length} different styles`,
258
+ ordinalSeverity: severity,
259
+ count: extraCount,
260
+ catalogIndex
261
+ });
262
+ }
263
+ });
264
+ // Return the result.
265
+ return {
266
+ data,
267
+ totals,
268
+ standardInstances
269
+ };
270
+ }, [linkTypes, withItems, catalogIndex]);
275
271
  };
272
+ exports.reporter = reporter;