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
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /*
2
3
  © 2021–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
4
  © 2026 Jeff Witt.
@@ -7,270 +8,265 @@
7
8
 
8
9
  SPDX-License-Identifier: MIT
9
10
  */
10
-
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.reporter = void 0;
13
+ const xPath_1 = require("../procs/xPath");
11
14
  /*
12
15
  styleDiff
13
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.
14
18
  */
15
-
16
- // IMPORTS
17
-
18
- const {getXPathCatalogIndex} = require('../procs/xPath');
19
-
20
19
  // FUNCTIONS
21
-
22
20
  // Returns an object classifying the links in a page by layout.
23
- const linksByType = async page => await page.evaluateHandle(() => {
24
- // FUNCTION DEFINITIONS START
25
- // Removes spacing characters from a text.
26
- const despace = text => text.replace(/\s/g, '');
27
- // Returns whether a list is a list entirely of links.
28
- const isLinkList = list => {
29
- const listItems = Array.from(list.children);
30
- if (listItems.length > 1) {
31
- return listItems.length > 1 && listItems.every(item => {
32
- if (item.tagName === 'LI') {
33
- const {children} = item;
34
- if (children.length === 1) {
35
- const link = children[0];
36
- if (link.tagName === 'A') {
37
- const itemText = despace(item.textContent);
38
- const linkText = despace(link.textContent);
39
- return itemText.length === linkText.length;
40
- }
41
- else {
42
- return false;
43
- }
44
- }
45
- else {
46
- return false;
47
- }
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
+ });
48
51
  }
49
52
  else {
50
- return false;
53
+ return false;
51
54
  }
52
- });
53
- }
54
- else {
55
- return false;
56
- }
57
- };
58
- // FUNCTION DEFINITIONS END
59
- // Identify the lists in the page.
60
- const lists = Array.from(document.body.querySelectorAll('ul, ol'));
61
- // Initialize an array of list links.
62
- const listLinks = [];
63
- // For each one:
64
- lists.forEach(list => {
65
- // If it is a list of links:
66
- if (isLinkList(list)) {
67
- // Choose one of the links randomly, assuming they have uniform styles.
68
- const links = Array.from(list.querySelectorAll('a'));
69
- const randomIndex = Math.floor(Math.random() * links.length);
70
- const randomLink = links[randomIndex];
71
- // Add it to the array.
72
- listLinks.push(randomLink);
73
- }
74
- });
75
- // Identify the inline links in the page.
76
- const allLinks = Array.from(document.body.querySelectorAll('a'));
77
- const inlineLinks = allLinks.filter(link => ! listLinks.includes(link));
78
- // Return the data.
79
- return {
80
- adjacent: inlineLinks,
81
- list: listLinks
82
- };
83
- });
84
- // Runs the test and returns the result.
85
- exports.reporter = async (page, report, _, withItems) => {
86
- // Get an object with arrays of list links and adjacent links as properties.
87
- const linkTypes = await linksByType(page);
88
- const catalogIndex = getXPathCatalogIndex(report, '/html/body');
89
- return await page.evaluate(args => {
90
- const [linkTypes, withItems, catalogIndex] = args;
91
- const {body} = document;
92
- // Identify the settable style properties to be compared for all tag names.
93
- const mainStyles = [
94
- 'fontStyle',
95
- 'fontWeight',
96
- 'opacity',
97
- 'textDecorationLine',
98
- 'textDecorationStyle',
99
- 'textDecorationThickness'
100
- ];
101
- // Identify those only for buttons.
102
- const buttonStyles = [
103
- 'borderStyle',
104
- 'borderWidth',
105
- 'height',
106
- 'lineHeight',
107
- 'maxHeight',
108
- 'maxWidth',
109
- 'minHeight',
110
- 'minWidth',
111
- 'outlineOffset',
112
- 'outlineStyle',
113
- 'outlineWidth'
114
- ];
115
- // Identify those for headings.
116
- const headingStyles = [
117
- 'color',
118
- 'fontSize'
119
- ];
120
- // Identify those for list links.
121
- const listLinkStyles = [
122
- 'color',
123
- 'fontSize',
124
- 'lineHeight'
125
- ];
126
- // Initialize the data to be returned.
127
- const data = {
128
- mainStyles,
129
- buttonStyles,
130
- headingStyles,
131
- listLinkStyles,
132
- totals: {}
133
55
  };
134
- if (withItems) {
135
- data.items = {};
136
- }
137
- // Initialize an object of elements to be analyzed, including links.
138
- const elements = {
139
- buttons: [],
140
- headings: {
141
- h1: [],
142
- h2: [],
143
- h3: [],
144
- h4: [],
145
- h5: [],
146
- h6: []
147
- },
148
- links: {
149
- adjacent: linkTypes.adjacent,
150
- list: linkTypes.list
151
- }
152
- };
153
- // Identify the heading tag names to be analyzed.
154
- const headingNames = Object.keys(elements.headings);
155
- // Add the buttons to the object.
156
- elements.buttons = Array.from(body.querySelectorAll('button, input[type=button]'));
157
- // For each heading tag name:
158
- headingNames.forEach(tagName => {
159
- // Add its elements to the object.
160
- elements.headings[tagName] = Array.from(body.getElementsByTagName(tagName));
161
- });
162
- // FUNCTION DEFINITION START
163
- // Tabulates the distribution of style properties for elements of a type.
164
- const tallyStyles = (typeName, elements, typeStyles, withItems) => {
165
- // If there are any elements:
166
- const elementCount = elements.length;
167
- if (elementCount) {
168
- const styleProps = {};
169
- const styleTexts = {};
170
- // For each element:
171
- elements.forEach(element => {
172
- // Get its values on the style properties to be compared.
173
- const styleDec = window.getComputedStyle(element);
174
- const style = {};
175
- const styles = mainStyles.concat(typeStyles);
176
- styles.forEach(styleName => {
177
- style[styleName] = styleDec[styleName];
178
- });
179
- // Get a text representation of the style, limited to those properties.
180
- const styleText = JSON.stringify(style);
181
- // Increment the total of elements with that style.
182
- styleTexts[styleText] = ++styleTexts[styleText] || 1;
183
- // If details are to be reported:
184
- if (withItems) {
185
- // Add the element’s values and text to the style details.
186
- if (! styleProps[typeName]) {
187
- styleProps[typeName] = {};
188
- }
189
- const elementText = (element.textContent.trim() || element.outerHTML.trim())
190
- .replace(/\s+/g, ' ')
191
- .slice(0, 100);
192
- // For each style property being compared:
193
- styles.forEach(styleName => {
194
- if (! styleProps[typeName][styleName]) {
195
- styleProps[typeName][styleName] = {};
196
- }
197
- if (! styleProps[typeName][styleName][style[styleName]]) {
198
- styleProps[typeName][styleName][style[styleName]] = [];
199
- }
200
- // Add the element text to the style details.
201
- styleProps[typeName][styleName][style[styleName]].push(elementText);
202
- });
203
- }
204
- });
205
- // Add the total to the result.
206
- data.totals[typeName] = {total: elementCount};
207
- const styleCounts = Object.values(styleTexts);
208
- // If the elements of the type differ in style:
209
- if (styleCounts.length > 1) {
210
- // Add the distribution of its style counts to the result.
211
- data.totals[typeName].subtotals = styleCounts.sort((a, b) => b - a);
212
- // If details are to be reported:
213
- if (withItems) {
214
- // Delete the data on uniform style properties.
215
- Object.keys(styleProps[typeName]).forEach(styleName => {
216
- if (Object.keys(styleProps[typeName][styleName]).length === 1) {
217
- delete styleProps[typeName][styleName];
218
- }
219
- });
220
- // Add the element values and texts to the result.
221
- data.items[typeName] = styleProps[typeName];
222
- }
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);
223
68
  }
224
- }
225
- };
226
- // FUNCTION DEFINITION END
227
- // Report the style-property distributions for the element types.
228
- tallyStyles('button', elements.buttons, buttonStyles, withItems);
229
- tallyStyles('adjacentLink', elements.links.adjacent, [], withItems);
230
- tallyStyles('listLink', elements.links.list, listLinkStyles, withItems);
231
- headingNames.forEach(headingName => {
232
- tallyStyles(headingName, elements.headings[headingName], headingStyles, withItems);
233
- });
234
- // Report the standandardized data.
235
- const totals = [0, 0, 0, 0];
236
- const standardInstances = [];
237
- const elementData = {
238
- adjacentLink: [0, 'In-line links', 'A'],
239
- listLink: [1, 'Links in columns', 'A'],
240
- button: [2, 'Buttons', 'BUTTON'],
241
- h1: [3, 'Level-1 headings', 'H1'],
242
- h2: [3, 'Level-2 headings', 'H2'],
243
- h3: [3, 'Level-3 headings', 'H3'],
244
- h4: [3, 'Level-4 headings', 'H4'],
245
- h5: [3, 'Level-5 headings', 'H5'],
246
- h6: [3, 'Level-6 headings', 'H6'],
247
- };
248
- // For each eligible element type:
249
- Object.keys(elementData).forEach(elementName => {
250
- // If it has more than 1 style:
251
- const elementTotal = data.totals[elementName];
252
- if (elementTotal && elementTotal.subtotals) {
253
- const currentData = elementData[elementName];
254
- const severity = currentData[0];
255
- const elementSubtotals = elementTotal.subtotals;
256
- // Treat the count of its styles in excess of 1 as the instance count for that element type.
257
- const extraCount = elementSubtotals.length - 1;
258
- totals[severity] += extraCount;
259
- // Add a summary standard instance for that element type.
260
- standardInstances.push({
261
- ruleID: 'styleDiff',
262
- what: `${currentData[1]} have ${elementSubtotals.length} different styles`,
263
- ordinalSeverity: severity,
264
- count: extraCount,
265
- catalogIndex
266
- });
267
- }
268
69
  });
269
- // 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.
270
74
  return {
271
- data,
272
- totals,
273
- standardInstances
75
+ adjacent: inlineLinks,
76
+ list: listLinks
274
77
  };
275
- }, [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]);
276
271
  };
272
+ exports.reporter = reporter;