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.
- package/.gitattributes +94 -0
- package/.github/workflows/ci.yml +58 -0
- package/.github/workflows/publish.yml +49 -0
- package/.github/workflows/typescript.yml +35 -0
- package/AGENTS.md +2 -2
- package/CLAUDE.md +25 -19
- package/CONTAINERS.md +10 -6
- package/CONTRIBUTING.md +29 -3
- package/Dockerfile +1 -1
- package/README.md +75 -20
- package/UPGRADES.md +4 -0
- package/actSpecs-doc.md +13 -1
- package/actSpecs.js +29 -5
- package/call.js +6 -5
- package/docker-compose.yml +8 -2
- package/docs/checkpoint-scanning.md +199 -0
- package/docs/standard-result-outcome.md +165 -0
- package/env.example +44 -10
- package/eslint.config.mjs +101 -0
- package/netWatch.js +373 -222
- package/package.json +46 -31
- package/pour/README.md +47 -0
- package/pour/pour.min.js +8 -0
- package/procs/actDo.js +808 -0
- package/procs/catalog.d.ts +17 -0
- package/procs/catalog.js +313 -221
- package/procs/catalog.ts +398 -0
- package/procs/checkpoint.js +110 -0
- package/procs/config.d.ts +35 -0
- package/procs/config.js +63 -0
- package/procs/dateTime.js +2 -1
- package/procs/doActs.js +442 -849
- package/procs/doTestAct.js +27 -121
- package/procs/flow.js +221 -0
- package/procs/generateRuleRegistry.js +94 -0
- package/procs/getSource.d.ts +26 -0
- package/procs/getSource.js +1 -0
- package/procs/job.js +116 -1
- package/procs/launch.d.ts +40 -0
- package/procs/launch.js +239 -108
- package/procs/nu.d.ts +48 -0
- package/procs/nu.js +1 -0
- package/procs/scope.js +196 -0
- package/procs/shoot.d.ts +33 -0
- package/procs/shoot.js +3 -1
- package/procs/standard.d.ts +18 -0
- package/procs/standard.js +83 -0
- package/procs/standard.ts +126 -0
- package/procs/testAct.js +145 -0
- package/procs/testaro.d.ts +20 -0
- package/procs/testaro.js +237 -189
- package/procs/testaro.ts +321 -0
- package/procs/userPath.js +126 -0
- package/procs/xPath.d.ts +4 -0
- package/procs/xPath.js +82 -64
- package/procs/xPath.ts +106 -0
- package/procs/xPathScript.d.ts +6 -0
- package/procs/xPathScript.js +70 -0
- package/run.js +3 -2
- package/surea11y/README.md +44 -0
- package/surea11y/surea11y.browser.js +14 -0
- package/testaro/adbID.d.ts +3 -0
- package/testaro/adbID.js +39 -41
- package/testaro/adbID.ts +66 -0
- package/testaro/allCapStyle.d.ts +3 -0
- package/testaro/allCapStyle.js +32 -34
- package/testaro/allCapStyle.ts +55 -0
- package/testaro/allCaps.d.ts +16 -0
- package/testaro/allCaps.js +179 -151
- package/testaro/allCaps.ts +228 -0
- package/testaro/allHidden.d.ts +13 -0
- package/testaro/allHidden.js +30 -30
- package/testaro/allHidden.ts +50 -0
- package/testaro/allSlanted.d.ts +3 -0
- package/testaro/allSlanted.js +31 -33
- package/testaro/allSlanted.ts +54 -0
- package/testaro/altScheme.d.ts +3 -0
- package/testaro/altScheme.js +28 -30
- package/testaro/altScheme.ts +50 -0
- package/testaro/attVal.d.ts +3 -0
- package/testaro/attVal.js +21 -21
- package/testaro/attVal.ts +52 -0
- package/testaro/autocomplete.d.ts +3 -0
- package/testaro/autocomplete.js +60 -75
- package/testaro/autocomplete.ts +101 -0
- package/testaro/bulk.d.ts +13 -0
- package/testaro/bulk.js +33 -33
- package/testaro/bulk.ts +55 -0
- package/testaro/buttonMenu.d.ts +9 -0
- package/testaro/buttonMenu.js +318 -319
- package/testaro/buttonMenu.ts +391 -0
- package/testaro/captionLoc.d.ts +3 -0
- package/testaro/captionLoc.js +18 -20
- package/testaro/captionLoc.ts +40 -0
- package/testaro/datalistRef.d.ts +3 -0
- package/testaro/datalistRef.js +34 -36
- package/testaro/datalistRef.ts +55 -0
- package/testaro/distortion.d.ts +3 -0
- package/testaro/distortion.js +58 -26
- package/testaro/distortion.ts +81 -0
- package/testaro/docType.d.ts +15 -0
- package/testaro/docType.js +26 -25
- package/testaro/docType.ts +45 -0
- package/testaro/dupAtt.d.ts +16 -0
- package/testaro/dupAtt.js +114 -104
- package/testaro/dupAtt.ts +144 -0
- package/testaro/elements.d.ts +6 -0
- package/testaro/elements.js +153 -153
- package/testaro/elements.ts +215 -0
- package/testaro/embAc.d.ts +3 -0
- package/testaro/embAc.js +20 -20
- package/testaro/embAc.ts +40 -0
- package/testaro/focAll.d.ts +13 -0
- package/testaro/focAll.js +186 -191
- package/testaro/focAll.ts +217 -0
- package/testaro/focAndOp.d.ts +3 -0
- package/testaro/focAndOp.js +101 -104
- package/testaro/focAndOp.ts +128 -0
- package/testaro/focInd.d.ts +3 -0
- package/testaro/focInd.js +65 -66
- package/testaro/focInd.ts +96 -0
- package/testaro/focVis.d.ts +3 -0
- package/testaro/focVis.js +29 -30
- package/testaro/focVis.ts +52 -0
- package/testaro/headEl.d.ts +10 -0
- package/testaro/headEl.js +62 -62
- package/testaro/headEl.ts +82 -0
- package/testaro/headingAmb.d.ts +3 -0
- package/testaro/headingAmb.js +55 -63
- package/testaro/headingAmb.ts +72 -0
- package/testaro/hovInd.d.ts +12 -0
- package/testaro/hovInd.js +164 -130
- package/testaro/hovInd.ts +199 -0
- package/testaro/hover.d.ts +3 -0
- package/testaro/hover.js +156 -126
- package/testaro/hover.ts +154 -0
- package/testaro/hr.d.ts +3 -0
- package/testaro/hr.js +15 -17
- package/testaro/hr.ts +36 -0
- package/testaro/imageLink.d.ts +3 -0
- package/testaro/imageLink.js +18 -20
- package/testaro/imageLink.ts +42 -0
- package/testaro/labClash.d.ts +3 -0
- package/testaro/labClash.js +32 -33
- package/testaro/labClash.ts +54 -0
- package/testaro/legendLoc.d.ts +3 -0
- package/testaro/legendLoc.js +18 -20
- package/testaro/legendLoc.ts +42 -0
- package/testaro/lineHeight.d.ts +3 -0
- package/testaro/lineHeight.js +44 -48
- package/testaro/lineHeight.ts +70 -0
- package/testaro/linkAmb.d.ts +7 -0
- package/testaro/linkAmb.js +80 -80
- package/testaro/linkAmb.ts +105 -0
- package/testaro/linkExt.d.ts +3 -0
- package/testaro/linkExt.js +14 -16
- package/testaro/linkExt.ts +35 -0
- package/testaro/linkOldAtt.d.ts +3 -0
- package/testaro/linkOldAtt.js +26 -28
- package/testaro/linkOldAtt.ts +48 -0
- package/testaro/linkTo.d.ts +3 -0
- package/testaro/linkTo.js +23 -22
- package/testaro/linkTo.ts +43 -0
- package/testaro/linkUl.d.ts +3 -0
- package/testaro/linkUl.js +31 -34
- package/testaro/linkUl.ts +54 -0
- package/testaro/miniText.d.ts +3 -0
- package/testaro/miniText.js +42 -44
- package/testaro/miniText.ts +68 -0
- package/testaro/motion.d.ts +10 -0
- package/testaro/motion.js +93 -96
- package/testaro/motion.ts +125 -0
- package/testaro/nonTable.d.ts +3 -0
- package/testaro/nonTable.js +40 -45
- package/testaro/nonTable.ts +66 -0
- package/testaro/optRoleSel.d.ts +3 -0
- package/testaro/optRoleSel.js +17 -19
- package/testaro/optRoleSel.ts +41 -0
- package/testaro/phOnly.d.ts +3 -0
- package/testaro/phOnly.js +19 -21
- package/testaro/phOnly.ts +43 -0
- package/testaro/pseudoP.d.ts +3 -0
- package/testaro/pseudoP.js +37 -38
- package/testaro/pseudoP.ts +59 -0
- package/testaro/radioSet.d.ts +3 -0
- package/testaro/radioSet.js +58 -59
- package/testaro/radioSet.ts +79 -0
- package/testaro/registry.d.ts +63 -0
- package/testaro/registry.js +67 -0
- package/testaro/registry.ts +141 -0
- package/testaro/role.d.ts +3 -0
- package/testaro/role.js +28 -29
- package/testaro/role.ts +53 -0
- package/testaro/secHeading.d.ts +3 -0
- package/testaro/secHeading.js +31 -33
- package/testaro/secHeading.ts +53 -0
- package/testaro/styleDiff.d.ts +25 -0
- package/testaro/styleDiff.js +249 -252
- package/testaro/styleDiff.ts +303 -0
- package/testaro/tabNav.d.ts +33 -0
- package/testaro/tabNav.js +273 -342
- package/testaro/tabNav.ts +454 -0
- package/testaro/targetsNear.d.ts +9 -0
- package/testaro/targetsNear.js +131 -132
- package/testaro/targetsNear.ts +160 -0
- package/testaro/textNodes.d.ts +6 -0
- package/testaro/textNodes.js +139 -135
- package/testaro/textNodes.ts +185 -0
- package/testaro/textSem.d.ts +3 -0
- package/testaro/textSem.js +26 -28
- package/testaro/textSem.ts +47 -0
- package/testaro/title.d.ts +9 -0
- package/testaro/title.js +16 -13
- package/testaro/title.ts +31 -0
- package/testaro/titledEl.d.ts +3 -0
- package/testaro/titledEl.js +16 -18
- package/testaro/titledEl.ts +38 -0
- package/testaro/zIndex.d.ts +3 -0
- package/testaro/zIndex.js +20 -22
- package/testaro/zIndex.ts +42 -0
- package/tests/alfa.d.ts +45 -0
- package/tests/alfa.js +139 -141
- package/tests/alfa.ts +214 -0
- package/tests/aslint.d.ts +33 -0
- package/tests/aslint.js +273 -249
- package/tests/aslint.ts +301 -0
- package/tests/axe.d.ts +27 -0
- package/tests/axe.js +200 -200
- package/tests/axe.ts +277 -0
- package/tests/ed11y.d.ts +28 -0
- package/tests/ed11y.js +142 -99
- package/tests/ed11y.ts +178 -0
- package/tests/htmlcs.d.ts +21 -0
- package/tests/htmlcs.js +175 -140
- package/tests/htmlcs.ts +181 -0
- package/tests/ibm.d.ts +52 -0
- package/tests/ibm.js +165 -166
- package/tests/ibm.ts +251 -0
- package/tests/nuVal.d.ts +13 -0
- package/tests/nuVal.js +107 -112
- package/tests/nuVal.ts +145 -0
- package/tests/nuVnu.d.ts +15 -0
- package/tests/nuVnu.js +142 -111
- package/tests/nuVnu.ts +144 -0
- package/tests/pour.d.ts +31 -0
- package/tests/pour.js +242 -0
- package/tests/pour.ts +273 -0
- package/tests/qualWeb.d.ts +39 -0
- package/tests/qualWeb.js +303 -272
- package/tests/qualWeb.ts +415 -0
- package/tests/surea11y.d.ts +33 -0
- package/tests/surea11y.js +288 -0
- package/tests/surea11y.ts +334 -0
- package/tests/testaro.d.ts +25 -0
- package/tests/testaro.js +746 -652
- package/tests/testaro.ts +862 -0
- package/tests/wave.d.ts +46 -0
- package/tests/wave.js +167 -177
- package/tests/wave.ts +252 -0
- package/tsconfig.json +17 -0
- package/types.d.ts +243 -0
- package/types.js +10 -0
- package/types.ts +376 -0
- package/validation/act/README.md +46 -0
- package/validation/act/capture.js +424 -0
- package/validation/act/chromium-issue-draft.md +66 -0
- package/validation/act/fp-triage-2026-08-22.md +86 -0
- package/validation/act/isolation-notes.md +159 -0
- package/validation/act/playwright-issue-draft.md +73 -0
- package/validation/act/propose-mappings.js +0 -0
- package/validation/act/repro-cdp-raw.js +105 -0
- package/validation/act/repro-metarefresh.js +65 -0
- package/validation/act/score.js +184 -0
- package/validation/act/stage3a-stress-report.md +69 -0
- package/validation/act/stage3b-mapping-proposals.md +94 -0
- package/validation/act/stage3b-triage-draft.md +138 -0
- package/validation/act/surea11y-track-a-2026-09-01.md +50 -0
- package/validation/executors/netWatch.js +180 -90
- package/validation/executors/test.js +17 -2
- package/validation/executors/tests.js +118 -10
- package/validation/jobs/reports/raw/260901T1000-surea11y-validation.json +964 -0
- package/validation/jobs/todo/240101T1200-simple-example.json +14 -6
- package/validation/jobs/todo/240101T1300-shoot-example.json +2 -1
- package/validation/jobs/todo/260821T1900-pour-validation.json +45 -0
- package/validation/jobs/todo/260901T1000-surea11y-validation.json +45 -0
- package/validation/knownFailures.json +1 -0
- package/validation/tests/jobProperties/adbID.json +27 -2
- package/validation/tests/jobProperties/{focOp.json → allCapStyle.json} +56 -53
- package/validation/tests/jobProperties/allCaps.json +25 -0
- package/validation/tests/jobProperties/allHidden.json +133 -13
- package/validation/tests/jobProperties/allSlanted.json +3 -3
- package/validation/tests/jobProperties/altScheme.json +23 -8
- package/validation/tests/jobProperties/attVal.json +57 -57
- package/validation/tests/jobProperties/autocomplete.json +11 -1
- package/validation/tests/jobProperties/bulk.json +6 -1
- package/validation/tests/jobProperties/buttonMenu.json +63 -42
- package/validation/tests/jobProperties/captionLoc.json +1 -6
- package/validation/tests/jobProperties/checkpoint-browser.json +401 -0
- package/validation/tests/jobProperties/checkpoint-page.json +397 -0
- package/validation/tests/jobProperties/checkpoint.json +395 -0
- package/validation/tests/jobProperties/datalistRef.json +20 -5
- package/validation/tests/jobProperties/distortion.json +28 -3
- package/validation/tests/jobProperties/docType.json +2 -2
- package/validation/tests/jobProperties/dupAtt.json +48 -33
- package/validation/tests/jobProperties/elements.json +28 -28
- package/validation/tests/jobProperties/embAc.json +36 -31
- package/validation/tests/jobProperties/focAndOp.json +284 -0
- package/validation/tests/jobProperties/focInd.json +34 -34
- package/validation/tests/jobProperties/focVis.json +1 -1
- package/validation/tests/jobProperties/hover.json +39 -37
- package/validation/tests/jobProperties/hr.json +13 -3
- package/validation/tests/jobProperties/imageLink.json +0 -5
- package/validation/tests/jobProperties/labClash.json +68 -33
- package/validation/tests/jobProperties/legendLoc.json +1 -6
- package/validation/tests/jobProperties/lineHeight.json +2 -2
- package/validation/tests/jobProperties/linkAmb.json +13 -18
- package/validation/tests/jobProperties/linkExt.json +1 -1
- package/validation/tests/jobProperties/linkOldAtt.json +12 -2
- package/validation/tests/jobProperties/linkTo.json +1 -1
- package/validation/tests/jobProperties/linkUl.json +65 -65
- package/validation/tests/jobProperties/miniText.json +7 -2
- package/validation/tests/jobProperties/motion.json +4 -50
- package/validation/tests/jobProperties/nonTable.json +48 -3
- package/validation/tests/jobProperties/optRoleSel.json +12 -2
- package/validation/tests/jobProperties/phOnly.json +6 -16
- package/validation/tests/jobProperties/pseudoP.json +17 -2
- package/validation/tests/jobProperties/radioSet.json +30 -30
- package/validation/tests/jobProperties/role.json +25 -5
- package/validation/tests/jobProperties/secHeading.json +26 -21
- package/validation/tests/jobProperties/styleDiff.json +35 -5
- package/validation/tests/jobProperties/tabNav.json +3 -1
- package/validation/tests/jobProperties/targetsNear.json +237 -0
- package/validation/tests/jobProperties/textNodes.json +29 -29
- package/validation/tests/jobProperties/textSem.json +26 -1
- package/validation/tests/jobProperties/title.json +12 -2
- package/validation/tests/jobProperties/titledEl.json +39 -9
- package/validation/tests/jobProperties/userPath.json +317 -0
- package/validation/tests/jobProperties/zIndex.json +40 -35
- package/validation/tests/targets/allCapStyle/index.html +26 -0
- package/validation/tests/targets/checkpoint/index.html +38 -0
- package/validation/tests/targets/datalistRef/index.html +1 -1
- package/validation/tests/targets/focAndOp/bad.html +29 -0
- package/validation/tests/targets/{focOp → focAndOp}/good.html +3 -1
- package/validation/tests/targets/focInd/bad.html +2 -1
- package/validation/tests/targets/headEl/index.html +10 -1
- package/validation/tests/targets/{targetSmall → targetsNear}/index.html +15 -1
- package/validation/tests/targets/userPath/index.html +42 -0
- package/validation/validateTest.js +62 -10
- package/.claude/settings.local.json +0 -11
- package/.eslintrc.json +0 -41
- package/htmlcs/.eslintrc.json +0 -67
- package/memory/MEMORY.md +0 -3
- package/memory/project_validation_pause.md +0 -10
- package/validation/tests/jobProperties/linkTitle.json +0 -127
- package/validation/tests/jobProperties/opFoc.json +0 -164
- package/validation/tests/jobProperties/targetSmall.json +0 -152
- package/validation/tests/jobProperties/targetTiny.json +0 -142
- package/validation/tests/targets/focOp/bad.html +0 -25
- package/validation/tests/targets/linkTitle/index.html +0 -24
- package/validation/tests/targets/opFoc/bad.html +0 -26
- package/validation/tests/targets/opFoc/good.html +0 -23
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2026 Jonathan Robert Pool.
|
|
4
|
+
|
|
5
|
+
Licensed under the MIT License. See LICENSE file at the project root or https://opensource.org/license/mit/ for details.
|
|
6
|
+
|
|
7
|
+
SPDX-License-Identifier: MIT
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// IMPORTS
|
|
11
|
+
|
|
12
|
+
import type {Page} from 'playwright';
|
|
13
|
+
|
|
14
|
+
// TYPES
|
|
15
|
+
|
|
16
|
+
// Data on one attribute of an element.
|
|
17
|
+
interface AttributeDatum {
|
|
18
|
+
name: string;
|
|
19
|
+
value: string;
|
|
20
|
+
}
|
|
21
|
+
// Data on one sibling node of an element.
|
|
22
|
+
interface SibInfo {
|
|
23
|
+
type: number;
|
|
24
|
+
tagName?: string;
|
|
25
|
+
attributes?: AttributeDatum[];
|
|
26
|
+
text?: string;
|
|
27
|
+
}
|
|
28
|
+
// Data on one specified element.
|
|
29
|
+
interface ElementDatum {
|
|
30
|
+
tagName: string;
|
|
31
|
+
parentTagName: string;
|
|
32
|
+
code: string;
|
|
33
|
+
attributes: AttributeDatum[];
|
|
34
|
+
textContent: string;
|
|
35
|
+
labelers?: string[];
|
|
36
|
+
labels?: string[];
|
|
37
|
+
parentTextContent?: string;
|
|
38
|
+
siblings?: {before: SibInfo[]; after: SibInfo[]};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
elements
|
|
43
|
+
This test reports data about specified elements within the document body. Meanings of detailLevel values:
|
|
44
|
+
0. Only total element count; no detail.
|
|
45
|
+
1. Also data on each specified element.
|
|
46
|
+
2. Data on each specified element also include the text content of the parent element.
|
|
47
|
+
3. Data on each specified element also include data on its sibling nodes.
|
|
48
|
+
Compiled to elements.js by tsc (issue #73); edit this file, not the emitted one.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
// FUNCTIONS
|
|
52
|
+
|
|
53
|
+
export const reporter = async (
|
|
54
|
+
page: Page,
|
|
55
|
+
_0: unknown,
|
|
56
|
+
_1: unknown,
|
|
57
|
+
_2: unknown,
|
|
58
|
+
detailLevel = 0,
|
|
59
|
+
tagName: string | null = null,
|
|
60
|
+
onlyVisible = false,
|
|
61
|
+
attribute?: string
|
|
62
|
+
) => {
|
|
63
|
+
// Determine a selector of the specified elements, including any descendants of open shadow roots.
|
|
64
|
+
let selector = `body ${tagName ? tagName.toLowerCase() : '*'}`;
|
|
65
|
+
if (attribute) {
|
|
66
|
+
selector += `[${attribute}]`;
|
|
67
|
+
}
|
|
68
|
+
if (onlyVisible) {
|
|
69
|
+
selector += ':visible';
|
|
70
|
+
}
|
|
71
|
+
let data: Record<string, unknown> = {};
|
|
72
|
+
// Get the data on the elements.
|
|
73
|
+
try {
|
|
74
|
+
const locator = page.locator(selector);
|
|
75
|
+
data = await locator.evaluateAll((elements, detailLevel) => {
|
|
76
|
+
// FUNCTION DEFINITIONS START
|
|
77
|
+
// Compacts a string.
|
|
78
|
+
const compact = (string: string) => string.replace(/\s+/g, ' ').trim();
|
|
79
|
+
// Gets data on a sibling node of an element.
|
|
80
|
+
const getSibInfo = (node: Node, nodeType: number, text: string | null) => {
|
|
81
|
+
const sibInfo: SibInfo = {
|
|
82
|
+
type: nodeType
|
|
83
|
+
};
|
|
84
|
+
// If the sibling node is an element:
|
|
85
|
+
if (nodeType === 1) {
|
|
86
|
+
sibInfo.tagName = (node as Element).tagName;
|
|
87
|
+
sibInfo.attributes = [];
|
|
88
|
+
Array.from((node as Element).attributes).forEach(attribute => {
|
|
89
|
+
sibInfo.attributes!.push({
|
|
90
|
+
name: attribute.name,
|
|
91
|
+
value: attribute.value
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else if (nodeType === 3) {
|
|
96
|
+
sibInfo.text = compact(text!);
|
|
97
|
+
}
|
|
98
|
+
return sibInfo;
|
|
99
|
+
};
|
|
100
|
+
// FUNCTION DEFINITIONS END
|
|
101
|
+
// Initialize the data with the count of the specified elements.
|
|
102
|
+
const data: {total: number; items?: ElementDatum[]} = {
|
|
103
|
+
total: elements.length
|
|
104
|
+
};
|
|
105
|
+
// If no itemization is required:
|
|
106
|
+
if (detailLevel === 0) {
|
|
107
|
+
// Return the element count.
|
|
108
|
+
return data;
|
|
109
|
+
}
|
|
110
|
+
// Otherwise, i.e. if itemization is required:
|
|
111
|
+
else {
|
|
112
|
+
// Initialize the item data.
|
|
113
|
+
data.items = [];
|
|
114
|
+
// For each specified element:
|
|
115
|
+
elements.forEach(element => {
|
|
116
|
+
// Initialize data on it.
|
|
117
|
+
const parent = element.parentElement;
|
|
118
|
+
const datum: ElementDatum = {
|
|
119
|
+
tagName: element.tagName,
|
|
120
|
+
parentTagName: parent ? parent.tagName : '',
|
|
121
|
+
code: compact(element.outerHTML),
|
|
122
|
+
attributes: [],
|
|
123
|
+
textContent: compact(element.textContent!)
|
|
124
|
+
};
|
|
125
|
+
// For each of its attributes:
|
|
126
|
+
for (const attribute of element.attributes) {
|
|
127
|
+
// Add data on the attribute to the element data.
|
|
128
|
+
const {name, value} = attribute;
|
|
129
|
+
datum.attributes.push({
|
|
130
|
+
name,
|
|
131
|
+
value
|
|
132
|
+
});
|
|
133
|
+
// If the element has reference labels:
|
|
134
|
+
if (name === 'aria-labelledby') {
|
|
135
|
+
// Add their texts to the element data.
|
|
136
|
+
const labelerIDs = value.split(/\s+/);
|
|
137
|
+
const labelers: string[] = [];
|
|
138
|
+
labelerIDs.forEach(id => {
|
|
139
|
+
const labeler = document.getElementById(id);
|
|
140
|
+
if (labeler) {
|
|
141
|
+
labelers.push(compact(labeler.textContent!));
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
if (labelers.length) {
|
|
145
|
+
datum.labelers = labelers;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// If the element has text content:
|
|
150
|
+
const {labels, textContent} = element as HTMLInputElement;
|
|
151
|
+
const compactContent = compact(textContent!);
|
|
152
|
+
if (compactContent) {
|
|
153
|
+
// Add it to the element data.
|
|
154
|
+
datum.textContent = compactContent;
|
|
155
|
+
}
|
|
156
|
+
// If the element has labels:
|
|
157
|
+
if (labels && labels.length) {
|
|
158
|
+
// Add their texts to the element data.
|
|
159
|
+
datum.labels = Array.from(labels).map(label => compact(label.textContent!));
|
|
160
|
+
}
|
|
161
|
+
// If the parental text content is required:
|
|
162
|
+
if (detailLevel > 1) {
|
|
163
|
+
// Add it (excluding any shadow-root descendants) to the element data.
|
|
164
|
+
datum.parentTextContent = parent ? compact(parent.textContent!) : '';
|
|
165
|
+
}
|
|
166
|
+
// If sibling itemization is required:
|
|
167
|
+
if (detailLevel === 3) {
|
|
168
|
+
// Add data on the siblings, excluding any descendants of shadow roots, to the data.
|
|
169
|
+
datum.siblings = {
|
|
170
|
+
before: [],
|
|
171
|
+
after: []
|
|
172
|
+
};
|
|
173
|
+
let more: Node | null = element;
|
|
174
|
+
while (more) {
|
|
175
|
+
more = more.previousSibling;
|
|
176
|
+
if (more) {
|
|
177
|
+
const {nodeType, nodeValue} = more;
|
|
178
|
+
if (! (nodeType === 3 && nodeValue === '')) {
|
|
179
|
+
const sibInfo = getSibInfo(more, nodeType, nodeValue);
|
|
180
|
+
datum.siblings!.before.unshift(sibInfo);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
more = element;
|
|
185
|
+
while (more) {
|
|
186
|
+
more = more.nextSibling;
|
|
187
|
+
if (more) {
|
|
188
|
+
const {nodeType, textContent} = more;
|
|
189
|
+
if (! (nodeType === 3 && textContent === '')) {
|
|
190
|
+
const sibInfo = getSibInfo(more, nodeType, compact(textContent!));
|
|
191
|
+
datum.siblings!.after.push(sibInfo);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
data.items!.push(datum);
|
|
197
|
+
});
|
|
198
|
+
return data;
|
|
199
|
+
}
|
|
200
|
+
}, detailLevel);
|
|
201
|
+
}
|
|
202
|
+
catch(error) {
|
|
203
|
+
console.log(`ERROR performing test (${(error as Error).message})`);
|
|
204
|
+
data = {
|
|
205
|
+
prevented: true,
|
|
206
|
+
error: 'ERROR performing test'
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
// Return the result.
|
|
210
|
+
return {
|
|
211
|
+
data,
|
|
212
|
+
totals: [],
|
|
213
|
+
standardInstances: []
|
|
214
|
+
};
|
|
215
|
+
};
|
package/testaro/embAc.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2021–2023 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
|
|
@@ -7,30 +9,28 @@
|
|
|
7
9
|
|
|
8
10
|
SPDX-License-Identifier: MIT
|
|
9
11
|
*/
|
|
10
|
-
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.reporter = void 0;
|
|
14
|
+
const testaro_1 = require("../procs/testaro");
|
|
11
15
|
/*
|
|
12
16
|
embAc
|
|
13
17
|
This test reports interactive elements (links, buttons, inputs, and select lists) contained by links or buttons. Such embedding not only violates the HTML standard, but also complicates user interaction and creates risks of error. It becomes non-obvious what a user will activate with a click.
|
|
18
|
+
Compiled to embAc.js by tsc (issue #73); edit this file, not the emitted one.
|
|
14
19
|
*/
|
|
15
|
-
|
|
16
|
-
// IMPORTS
|
|
17
|
-
|
|
18
|
-
const {doTest} = require('../procs/testaro');
|
|
19
|
-
|
|
20
20
|
// FUNCTIONS
|
|
21
|
-
|
|
22
21
|
// Runs the test and returns the result.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
const reporter = async (page, report, _, withItems) => {
|
|
23
|
+
const getBadWhat = element => {
|
|
24
|
+
// Get whether the embedding element is a link or a button.
|
|
25
|
+
const embedder = element.parentElement.closest('a, button');
|
|
26
|
+
const embedderWhat = embedder.tagName.toLowerCase() === 'a' ? 'a link' : 'a button';
|
|
27
|
+
// Return a violation description.
|
|
28
|
+
return `interactive element is embedded in ${embedderWhat}`;
|
|
29
|
+
};
|
|
30
|
+
const selector = ['a', 'button', 'input', 'select']
|
|
31
|
+
.map(tag => `a ${tag}, button ${tag}`)
|
|
32
|
+
.join(', ');
|
|
33
|
+
const whats = 'interactive elements are embedded in links or buttons';
|
|
34
|
+
return await (0, testaro_1.doTest)(page, report, withItems, 'embAc', selector, whats, 2, getBadWhat.toString());
|
|
36
35
|
};
|
|
36
|
+
exports.reporter = reporter;
|
package/testaro/embAc.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2026 Jeff Witt.
|
|
4
|
+
© 2026 Jonathan Robert Pool.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License. See LICENSE file at the project root or
|
|
7
|
+
https://opensource.org/license/mit/ for details.
|
|
8
|
+
|
|
9
|
+
SPDX-License-Identifier: MIT
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// IMPORTS
|
|
13
|
+
|
|
14
|
+
import type {Page} from 'playwright';
|
|
15
|
+
import {doTest} from '../procs/testaro';
|
|
16
|
+
import type {GetBadWhat, Report} from '../types';
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
embAc
|
|
20
|
+
This test reports interactive elements (links, buttons, inputs, and select lists) contained by links or buttons. Such embedding not only violates the HTML standard, but also complicates user interaction and creates risks of error. It becomes non-obvious what a user will activate with a click.
|
|
21
|
+
Compiled to embAc.js by tsc (issue #73); edit this file, not the emitted one.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// FUNCTIONS
|
|
25
|
+
|
|
26
|
+
// Runs the test and returns the result.
|
|
27
|
+
export const reporter = async (page: Page, report: Report, _: unknown, withItems: boolean) => {
|
|
28
|
+
const getBadWhat: GetBadWhat = element => {
|
|
29
|
+
// Get whether the embedding element is a link or a button.
|
|
30
|
+
const embedder = element.parentElement!.closest('a, button');
|
|
31
|
+
const embedderWhat = embedder!.tagName.toLowerCase() === 'a' ? 'a link' : 'a button';
|
|
32
|
+
// Return a violation description.
|
|
33
|
+
return `interactive element is embedded in ${embedderWhat}`;
|
|
34
|
+
};
|
|
35
|
+
const selector = ['a', 'button', 'input', 'select']
|
|
36
|
+
.map(tag => `a ${tag}, button ${tag}`)
|
|
37
|
+
.join(', ');
|
|
38
|
+
const whats = 'interactive elements are embedded in links or buttons';
|
|
39
|
+
return await doTest(page, report, withItems, 'embAc', selector, whats, 2, getBadWhat.toString());
|
|
40
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { Report, StandardInstance } from '../types';
|
|
3
|
+
export declare const reporter: (page: Page, report: Report, _: unknown, withItems: boolean) => Promise<{
|
|
4
|
+
data: {
|
|
5
|
+
focusableCount: number;
|
|
6
|
+
tabFocused: number;
|
|
7
|
+
discrepancy: number;
|
|
8
|
+
unreachedCount: number;
|
|
9
|
+
unexpectedCount: number;
|
|
10
|
+
};
|
|
11
|
+
totals: number[];
|
|
12
|
+
standardInstances: StandardInstance[];
|
|
13
|
+
}>;
|