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.
- 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 +24 -18
- package/CONTAINERS.md +9 -6
- package/CONTRIBUTING.md +29 -3
- package/Dockerfile +1 -1
- package/README.md +73 -19
- 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 +372 -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 +312 -221
- package/procs/catalog.ts +398 -0
- package/procs/checkpoint.js +110 -0
- package/procs/config.d.ts +35 -0
- package/procs/config.js +62 -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/job.js +115 -1
- package/procs/launch.d.ts +40 -0
- package/procs/launch.js +239 -108
- package/procs/nu.d.ts +48 -0
- package/procs/scope.js +196 -0
- package/procs/shoot.d.ts +33 -0
- 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 +236 -189
- package/procs/testaro.ts +321 -0
- package/procs/userPath.js +126 -0
- package/procs/xPath.d.ts +4 -0
- package/procs/xPath.js +81 -69
- 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 +38 -41
- package/testaro/adbID.ts +66 -0
- package/testaro/allCapStyle.d.ts +3 -0
- package/testaro/allCapStyle.js +31 -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 +29 -30
- package/testaro/allHidden.ts +50 -0
- package/testaro/allSlanted.d.ts +3 -0
- package/testaro/allSlanted.js +30 -33
- package/testaro/allSlanted.ts +54 -0
- package/testaro/altScheme.d.ts +3 -0
- package/testaro/altScheme.js +27 -30
- package/testaro/altScheme.ts +50 -0
- package/testaro/attVal.d.ts +3 -0
- package/testaro/attVal.js +20 -21
- package/testaro/attVal.ts +52 -0
- package/testaro/autocomplete.d.ts +3 -0
- package/testaro/autocomplete.js +59 -75
- package/testaro/autocomplete.ts +101 -0
- package/testaro/bulk.d.ts +13 -0
- package/testaro/bulk.js +32 -33
- package/testaro/bulk.ts +55 -0
- package/testaro/buttonMenu.d.ts +9 -0
- package/testaro/buttonMenu.js +317 -319
- package/testaro/buttonMenu.ts +391 -0
- package/testaro/captionLoc.d.ts +3 -0
- package/testaro/captionLoc.js +17 -20
- package/testaro/captionLoc.ts +40 -0
- package/testaro/datalistRef.d.ts +3 -0
- package/testaro/datalistRef.js +33 -36
- package/testaro/datalistRef.ts +55 -0
- package/testaro/distortion.d.ts +3 -0
- package/testaro/distortion.js +57 -26
- package/testaro/distortion.ts +81 -0
- package/testaro/docType.d.ts +15 -0
- package/testaro/docType.js +25 -25
- package/testaro/docType.ts +45 -0
- package/testaro/dupAtt.d.ts +16 -0
- package/testaro/dupAtt.js +113 -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 +19 -20
- package/testaro/embAc.ts +40 -0
- package/testaro/focAll.d.ts +13 -0
- package/testaro/focAll.js +185 -191
- package/testaro/focAll.ts +217 -0
- package/testaro/focAndOp.d.ts +3 -0
- package/testaro/focAndOp.js +100 -104
- package/testaro/focAndOp.ts +128 -0
- package/testaro/focInd.d.ts +3 -0
- package/testaro/focInd.js +64 -66
- package/testaro/focInd.ts +96 -0
- package/testaro/focVis.d.ts +3 -0
- package/testaro/focVis.js +28 -30
- package/testaro/focVis.ts +52 -0
- package/testaro/headEl.d.ts +10 -0
- package/testaro/headEl.js +61 -62
- package/testaro/headEl.ts +82 -0
- package/testaro/headingAmb.d.ts +3 -0
- package/testaro/headingAmb.js +54 -63
- package/testaro/headingAmb.ts +72 -0
- package/testaro/hovInd.d.ts +12 -0
- package/testaro/hovInd.js +163 -130
- package/testaro/hovInd.ts +199 -0
- package/testaro/hover.d.ts +3 -0
- package/testaro/hover.js +155 -126
- package/testaro/hover.ts +154 -0
- package/testaro/hr.d.ts +3 -0
- package/testaro/hr.js +14 -17
- package/testaro/hr.ts +36 -0
- package/testaro/imageLink.d.ts +3 -0
- package/testaro/imageLink.js +17 -20
- package/testaro/imageLink.ts +42 -0
- package/testaro/labClash.d.ts +3 -0
- package/testaro/labClash.js +31 -33
- package/testaro/labClash.ts +54 -0
- package/testaro/legendLoc.d.ts +3 -0
- package/testaro/legendLoc.js +17 -20
- package/testaro/legendLoc.ts +42 -0
- package/testaro/lineHeight.d.ts +3 -0
- package/testaro/lineHeight.js +43 -48
- package/testaro/lineHeight.ts +70 -0
- package/testaro/linkAmb.d.ts +7 -0
- package/testaro/linkAmb.js +79 -80
- package/testaro/linkAmb.ts +105 -0
- package/testaro/linkExt.d.ts +3 -0
- package/testaro/linkExt.js +13 -16
- package/testaro/linkExt.ts +35 -0
- package/testaro/linkOldAtt.d.ts +3 -0
- package/testaro/linkOldAtt.js +25 -28
- package/testaro/linkOldAtt.ts +48 -0
- package/testaro/linkTo.d.ts +3 -0
- package/testaro/linkTo.js +22 -22
- package/testaro/linkTo.ts +43 -0
- package/testaro/linkUl.d.ts +3 -0
- package/testaro/linkUl.js +30 -34
- package/testaro/linkUl.ts +54 -0
- package/testaro/miniText.d.ts +3 -0
- package/testaro/miniText.js +41 -44
- package/testaro/miniText.ts +68 -0
- package/testaro/motion.d.ts +10 -0
- package/testaro/motion.js +92 -96
- package/testaro/motion.ts +125 -0
- package/testaro/nonTable.d.ts +3 -0
- package/testaro/nonTable.js +39 -45
- package/testaro/nonTable.ts +66 -0
- package/testaro/optRoleSel.d.ts +3 -0
- package/testaro/optRoleSel.js +16 -19
- package/testaro/optRoleSel.ts +41 -0
- package/testaro/phOnly.d.ts +3 -0
- package/testaro/phOnly.js +18 -21
- package/testaro/phOnly.ts +43 -0
- package/testaro/pseudoP.d.ts +3 -0
- package/testaro/pseudoP.js +36 -38
- package/testaro/pseudoP.ts +59 -0
- package/testaro/radioSet.d.ts +3 -0
- package/testaro/radioSet.js +57 -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 +27 -29
- package/testaro/role.ts +53 -0
- package/testaro/secHeading.d.ts +3 -0
- package/testaro/secHeading.js +30 -33
- package/testaro/secHeading.ts +53 -0
- package/testaro/styleDiff.d.ts +25 -0
- package/testaro/styleDiff.js +248 -252
- package/testaro/styleDiff.ts +303 -0
- package/testaro/tabNav.d.ts +33 -0
- package/testaro/tabNav.js +272 -342
- package/testaro/tabNav.ts +454 -0
- package/testaro/targetsNear.d.ts +9 -0
- package/testaro/targetsNear.js +130 -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 +25 -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 +15 -18
- package/testaro/titledEl.ts +38 -0
- package/testaro/zIndex.d.ts +3 -0
- package/testaro/zIndex.js +19 -22
- package/testaro/zIndex.ts +42 -0
- package/tests/alfa.d.ts +45 -0
- package/tests/alfa.js +138 -141
- package/tests/alfa.ts +214 -0
- package/tests/aslint.d.ts +33 -0
- package/tests/aslint.js +272 -249
- package/tests/aslint.ts +301 -0
- package/tests/axe.d.ts +27 -0
- package/tests/axe.js +199 -200
- package/tests/axe.ts +277 -0
- package/tests/ed11y.d.ts +28 -0
- package/tests/ed11y.js +141 -99
- package/tests/ed11y.ts +178 -0
- package/tests/htmlcs.d.ts +21 -0
- package/tests/htmlcs.js +174 -140
- package/tests/htmlcs.ts +181 -0
- package/tests/ibm.d.ts +52 -0
- package/tests/ibm.js +164 -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 +141 -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 +302 -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 +745 -652
- package/tests/testaro.ts +862 -0
- package/tests/wave.d.ts +46 -0
- package/tests/wave.js +166 -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 +61 -9
- package/.claude/settings.local.json +0 -11
- package/.eslintrc.json +0 -41
- package/htmlcs/.eslintrc.json +0 -67
- 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,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2022–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2026 Jeff Witt.
|
|
4
|
+
© 2025–2026 Jonathan Robert Pool.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License. See LICENSE file at the project root or https://opensource.org/license/mit/ for details.
|
|
7
|
+
|
|
8
|
+
SPDX-License-Identifier: MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// IMPORTS
|
|
12
|
+
|
|
13
|
+
import type {Page} from 'playwright';
|
|
14
|
+
import {doTest} from '../procs/testaro';
|
|
15
|
+
import type {BadWhat, Report} from '../types';
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
nonTable
|
|
19
|
+
Derived from the bbc-a11y useTablesForData test. Crude heuristics omitted.
|
|
20
|
+
This test reports tables used for layout.
|
|
21
|
+
Compiled to nonTable.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
|
+
// The candidate selector yields table elements.
|
|
29
|
+
const getBadWhat = (element: HTMLTableElement): BadWhat => {
|
|
30
|
+
// If the element contains another table:
|
|
31
|
+
if (element.querySelector('table')) {
|
|
32
|
+
// Return a violation description.
|
|
33
|
+
return 'Element contains another table';
|
|
34
|
+
}
|
|
35
|
+
const rowCount = element.querySelectorAll('tr').length;
|
|
36
|
+
const columnCount = Math.max(
|
|
37
|
+
... Array
|
|
38
|
+
.from(element.querySelectorAll('tr'))
|
|
39
|
+
.map(row => Array.from(row.querySelectorAll('th, td')).length)
|
|
40
|
+
);
|
|
41
|
+
// Otherwise, if it has only 1 column or 1 row:
|
|
42
|
+
if (rowCount === 1 || columnCount === 1) {
|
|
43
|
+
// Return a violation description.
|
|
44
|
+
return 'Element has only one row or one column';
|
|
45
|
+
}
|
|
46
|
+
// Otherwise, if it contains an object or player:
|
|
47
|
+
if (element.querySelector('object, embed, applet, audio, video')) {
|
|
48
|
+
// Return a violation description.
|
|
49
|
+
return 'Element contains an object or player';
|
|
50
|
+
}
|
|
51
|
+
const role = element.getAttribute('role');
|
|
52
|
+
// Otherwise, if it has no table-compatible explicit role or descendant element:
|
|
53
|
+
if (! (
|
|
54
|
+
['grid', 'treegrid'].includes(role as string)
|
|
55
|
+
|| element.caption
|
|
56
|
+
|| element.querySelector('col, colgroup, tfoot, th, thead')
|
|
57
|
+
)) {
|
|
58
|
+
// Return a violation description.
|
|
59
|
+
return 'Element has no table-compatible explicit role or descendant element';
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const whats = 'table elements are misused for non-table content';
|
|
63
|
+
return await doTest(
|
|
64
|
+
page, report, withItems, 'nonTable', 'body table', whats, 2, getBadWhat.toString()
|
|
65
|
+
);
|
|
66
|
+
};
|
package/testaro/optRoleSel.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2025 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2025 Juan S. Casado.
|
|
@@ -9,30 +10,26 @@
|
|
|
9
10
|
|
|
10
11
|
SPDX-License-Identifier: MIT
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.reporter = void 0;
|
|
15
|
+
const testaro_1 = require("../procs/testaro");
|
|
13
16
|
/*
|
|
14
17
|
optRoleSel
|
|
15
18
|
Clean-room rule.
|
|
16
19
|
This test reports elements with role=option that are missing aria-selected attributes.
|
|
20
|
+
Compiled to optRoleSel.js by tsc (issue #73); edit this file, not the emitted one.
|
|
17
21
|
*/
|
|
18
|
-
|
|
19
|
-
// IMPORTS
|
|
20
|
-
|
|
21
|
-
const {doTest} = require('../procs/testaro');
|
|
22
|
-
|
|
23
22
|
// FUNCTIONS
|
|
24
|
-
|
|
25
23
|
// Runs the test and returns the result.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
page, report, withItems, 'optRoleSel', 'body [role="option"]', whats, 1, getBadWhat.toString()
|
|
37
|
-
);
|
|
24
|
+
const reporter = async (page, report, _, withItems) => {
|
|
25
|
+
const getBadWhat = element => {
|
|
26
|
+
// If the element has no aria-selected attribute:
|
|
27
|
+
if (!element.hasAttribute('aria-selected')) {
|
|
28
|
+
// Return a violation description.
|
|
29
|
+
return 'Element has role=option but no aria-selected attribute';
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const whats = 'Elements with role=option have no aria-selected attributes';
|
|
33
|
+
return await (0, testaro_1.doTest)(page, report, withItems, 'optRoleSel', 'body [role="option"]', whats, 1, getBadWhat.toString());
|
|
38
34
|
};
|
|
35
|
+
exports.reporter = reporter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2025 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2025 Juan S. Casado.
|
|
4
|
+
© 2026 Jeff Witt.
|
|
5
|
+
© 2025–2026 Jonathan Robert Pool.
|
|
6
|
+
|
|
7
|
+
Licensed under the MIT License. See LICENSE file at the project root or
|
|
8
|
+
https://opensource.org/license/mit/ for details.
|
|
9
|
+
|
|
10
|
+
SPDX-License-Identifier: MIT
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// IMPORTS
|
|
14
|
+
|
|
15
|
+
import type {Page} from 'playwright';
|
|
16
|
+
import {doTest} from '../procs/testaro';
|
|
17
|
+
import type {GetBadWhat, Report} from '../types';
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
optRoleSel
|
|
21
|
+
Clean-room rule.
|
|
22
|
+
This test reports elements with role=option that are missing aria-selected attributes.
|
|
23
|
+
Compiled to optRoleSel.js by tsc (issue #73); edit this file, not the emitted one.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// FUNCTIONS
|
|
27
|
+
|
|
28
|
+
// Runs the test and returns the result.
|
|
29
|
+
export const reporter = async (page: Page, report: Report, _: unknown, withItems: boolean) => {
|
|
30
|
+
const getBadWhat: GetBadWhat = element => {
|
|
31
|
+
// If the element has no aria-selected attribute:
|
|
32
|
+
if (! element.hasAttribute('aria-selected')) {
|
|
33
|
+
// Return a violation description.
|
|
34
|
+
return 'Element has role=option but no aria-selected attribute';
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const whats = 'Elements with role=option have no aria-selected attributes';
|
|
38
|
+
return await doTest(
|
|
39
|
+
page, report, withItems, 'optRoleSel', 'body [role="option"]', whats, 1, getBadWhat.toString()
|
|
40
|
+
);
|
|
41
|
+
};
|
package/testaro/phOnly.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2025 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2025 Juan S. Casado.
|
|
@@ -9,32 +10,28 @@
|
|
|
9
10
|
|
|
10
11
|
SPDX-License-Identifier: MIT
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.reporter = void 0;
|
|
15
|
+
const testaro_1 = require("../procs/testaro");
|
|
13
16
|
/*
|
|
14
17
|
phOnly
|
|
15
18
|
Clean-room rule.
|
|
16
19
|
This test reports input elements that have placeholders but no accessible names. The standard for accessible name computation is employed; it accepts title attributes as sources for accessible names. Thus, this test does not report reliance on title attributes for accessible names, although such reliance is generally considered a poor practice.
|
|
20
|
+
Compiled to phOnly.js by tsc (issue #73); edit this file, not the emitted one.
|
|
17
21
|
*/
|
|
18
|
-
|
|
19
|
-
// IMPORTS
|
|
20
|
-
|
|
21
|
-
const {doTest} = require('../procs/testaro');
|
|
22
|
-
|
|
23
22
|
// FUNCTIONS
|
|
24
|
-
|
|
25
23
|
// Runs the test and returns the result.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
page, report, withItems, 'phOnly', 'body input[placeholder]', whats, 2, getBadWhat.toString()
|
|
39
|
-
);
|
|
24
|
+
const reporter = async (page, report, _, withItems) => {
|
|
25
|
+
const getBadWhat = element => {
|
|
26
|
+
// Get the accessible name of the element.
|
|
27
|
+
const accessibleName = window.getAccessibleName(element);
|
|
28
|
+
// If there is none:
|
|
29
|
+
if (!accessibleName) {
|
|
30
|
+
// Return a violation description.
|
|
31
|
+
return 'Element has a placeholder but no accessible name';
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const whats = 'input elements have placeholders but no accessible names';
|
|
35
|
+
return await (0, testaro_1.doTest)(page, report, withItems, 'phOnly', 'body input[placeholder]', whats, 2, getBadWhat.toString());
|
|
40
36
|
};
|
|
37
|
+
exports.reporter = reporter;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2025 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2025 Juan S. Casado.
|
|
4
|
+
© 2026 Jeff Witt.
|
|
5
|
+
© 2025–2026 Jonathan Robert Pool.
|
|
6
|
+
|
|
7
|
+
Licensed under the MIT License. See LICENSE file at the project root or
|
|
8
|
+
https://opensource.org/license/mit/ for details.
|
|
9
|
+
|
|
10
|
+
SPDX-License-Identifier: MIT
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// IMPORTS
|
|
14
|
+
|
|
15
|
+
import type {Page} from 'playwright';
|
|
16
|
+
import {doTest} from '../procs/testaro';
|
|
17
|
+
import type {GetBadWhat, Report} from '../types';
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
phOnly
|
|
21
|
+
Clean-room rule.
|
|
22
|
+
This test reports input elements that have placeholders but no accessible names. The standard for accessible name computation is employed; it accepts title attributes as sources for accessible names. Thus, this test does not report reliance on title attributes for accessible names, although such reliance is generally considered a poor practice.
|
|
23
|
+
Compiled to phOnly.js by tsc (issue #73); edit this file, not the emitted one.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// FUNCTIONS
|
|
27
|
+
|
|
28
|
+
// Runs the test and returns the result.
|
|
29
|
+
export const reporter = async (page: Page, report: Report, _: unknown, withItems: boolean) => {
|
|
30
|
+
const getBadWhat: GetBadWhat = element => {
|
|
31
|
+
// Get the accessible name of the element.
|
|
32
|
+
const accessibleName = window.getAccessibleName(element);
|
|
33
|
+
// If there is none:
|
|
34
|
+
if (! accessibleName) {
|
|
35
|
+
// Return a violation description.
|
|
36
|
+
return 'Element has a placeholder but no accessible name';
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const whats = 'input elements have placeholders but no accessible names';
|
|
40
|
+
return await doTest(
|
|
41
|
+
page, report, withItems, 'phOnly', 'body input[placeholder]', whats, 2, getBadWhat.toString()
|
|
42
|
+
);
|
|
43
|
+
};
|
package/testaro/pseudoP.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2026 Jeff Witt.
|
|
@@ -7,49 +8,46 @@
|
|
|
7
8
|
|
|
8
9
|
SPDX-License-Identifier: MIT
|
|
9
10
|
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.reporter = void 0;
|
|
13
|
+
const testaro_1 = require("../procs/testaro");
|
|
10
14
|
/*
|
|
11
15
|
pseudoP
|
|
12
16
|
This test reports 2 or more sequential br elements without intervening text content. They may be inferior substitutes for p elements.
|
|
17
|
+
Compiled to pseudoP.js by tsc (issue #73); edit this file, not the emitted one.
|
|
13
18
|
*/
|
|
14
|
-
|
|
15
|
-
// IMPORTS
|
|
16
|
-
|
|
17
|
-
const {doTest} = require('../procs/testaro');
|
|
18
|
-
|
|
19
19
|
// FUNCTIONS
|
|
20
|
-
|
|
21
20
|
// Runs the test and returns the result.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
21
|
+
const reporter = async (page, report, _, withItems) => {
|
|
22
|
+
const getBadWhat = element => {
|
|
23
|
+
// Get the node before the element node.
|
|
24
|
+
const previousNode = element.previousSibling;
|
|
25
|
+
let isBad = false;
|
|
26
|
+
// If it is a br element:
|
|
27
|
+
if (previousNode && previousNode.nodeType === Node.ELEMENT_NODE && previousNode.tagName === 'BR') {
|
|
28
|
+
// Classify the element as a violator.
|
|
29
|
+
isBad = true;
|
|
30
|
+
}
|
|
31
|
+
// Otherwise, if it is a text node:
|
|
32
|
+
else if (previousNode && previousNode.nodeType === Node.TEXT_NODE) {
|
|
33
|
+
// If the text node contains only whitespace:
|
|
34
|
+
if (previousNode.textContent.trim() === '') {
|
|
35
|
+
// Get the node before the text node.
|
|
36
|
+
const beforeText = previousNode.previousSibling;
|
|
37
|
+
// If that node is a br element:
|
|
38
|
+
if (beforeText && beforeText.nodeType === Node.ELEMENT_NODE && beforeText.tagName === 'BR') {
|
|
39
|
+
// Classify the element as a violator.
|
|
40
|
+
isBad = true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// If the element is a violator:
|
|
45
|
+
if (isBad) {
|
|
46
|
+
// Return a violation description.
|
|
47
|
+
return `Element follows another br element, possibly constituting a pseudo-paragraph`;
|
|
42
48
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (isBad) {
|
|
47
|
-
// Return a violation description.
|
|
48
|
-
return `Element follows another br element, possibly constituting a pseudo-paragraph`;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
const whats = 'br elements follow other br elements, possibly constituting pseudo-paragraphs';
|
|
52
|
-
return await doTest(
|
|
53
|
-
page, report, withItems, 'pseudoP', 'body br', whats, 0, getBadWhat.toString()
|
|
54
|
-
);
|
|
49
|
+
};
|
|
50
|
+
const whats = 'br elements follow other br elements, possibly constituting pseudo-paragraphs';
|
|
51
|
+
return await (0, testaro_1.doTest)(page, report, withItems, 'pseudoP', 'body br', whats, 0, getBadWhat.toString());
|
|
55
52
|
};
|
|
53
|
+
exports.reporter = reporter;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2026 Jeff Witt.
|
|
4
|
+
© 2025–2026 Jonathan Robert Pool.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License. See LICENSE file at the project root or https://opensource.org/license/mit/ for details.
|
|
7
|
+
|
|
8
|
+
SPDX-License-Identifier: MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// IMPORTS
|
|
12
|
+
|
|
13
|
+
import type {Page} from 'playwright';
|
|
14
|
+
import {doTest} from '../procs/testaro';
|
|
15
|
+
import type {GetBadWhat, Report} from '../types';
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
pseudoP
|
|
19
|
+
This test reports 2 or more sequential br elements without intervening text content. They may be inferior substitutes for p elements.
|
|
20
|
+
Compiled to pseudoP.js by tsc (issue #73); edit this file, not the emitted one.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// FUNCTIONS
|
|
24
|
+
|
|
25
|
+
// Runs the test and returns the result.
|
|
26
|
+
export const reporter = async (page: Page, report: Report, _: unknown, withItems: boolean) => {
|
|
27
|
+
const getBadWhat: GetBadWhat = element => {
|
|
28
|
+
// Get the node before the element node.
|
|
29
|
+
const previousNode = element.previousSibling;
|
|
30
|
+
let isBad = false;
|
|
31
|
+
// If it is a br element:
|
|
32
|
+
if (previousNode && previousNode.nodeType === Node.ELEMENT_NODE && (previousNode as Element).tagName === 'BR') {
|
|
33
|
+
// Classify the element as a violator.
|
|
34
|
+
isBad = true;
|
|
35
|
+
}
|
|
36
|
+
// Otherwise, if it is a text node:
|
|
37
|
+
else if (previousNode && previousNode.nodeType === Node.TEXT_NODE) {
|
|
38
|
+
// If the text node contains only whitespace:
|
|
39
|
+
if (previousNode.textContent!.trim() === '') {
|
|
40
|
+
// Get the node before the text node.
|
|
41
|
+
const beforeText = previousNode.previousSibling;
|
|
42
|
+
// If that node is a br element:
|
|
43
|
+
if (beforeText && beforeText.nodeType === Node.ELEMENT_NODE && (beforeText as Element).tagName === 'BR') {
|
|
44
|
+
// Classify the element as a violator.
|
|
45
|
+
isBad = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// If the element is a violator:
|
|
50
|
+
if (isBad) {
|
|
51
|
+
// Return a violation description.
|
|
52
|
+
return `Element follows another br element, possibly constituting a pseudo-paragraph`;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const whats = 'br elements follow other br elements, possibly constituting pseudo-paragraphs';
|
|
56
|
+
return await doTest(
|
|
57
|
+
page, report, withItems, 'pseudoP', 'body br', whats, 0, getBadWhat.toString()
|
|
58
|
+
);
|
|
59
|
+
};
|
package/testaro/radioSet.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2026 Jeff Witt.
|
|
@@ -7,69 +8,66 @@
|
|
|
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 testaro_1 = require("../procs/testaro");
|
|
11
14
|
/*
|
|
12
15
|
radioSet
|
|
13
16
|
This test reports nonstandard groupings of radio buttons. It defines a standard grouping to require that two or more radio buttons with the same name, and no other radio buttons, be grouped in a fieldset element with a valid legend element.
|
|
17
|
+
Compiled to radioSet.js by tsc (issue #73); edit this file, not the emitted one.
|
|
14
18
|
*/
|
|
15
|
-
|
|
16
|
-
// IMPORTS
|
|
17
|
-
|
|
18
|
-
const {doTest} = require('../procs/testaro');
|
|
19
|
-
|
|
20
19
|
// FUNCTIONS
|
|
21
|
-
|
|
22
20
|
// Runs the test and returns the result.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
page, report, withItems, 'radioSet', 'body input[type=radio]', whats, 2, getBadWhat.toString()
|
|
74
|
-
);
|
|
21
|
+
const reporter = async (page, report, _, withItems) => {
|
|
22
|
+
// The candidate selector guarantees input elements, so the parameter is typed as one.
|
|
23
|
+
const getBadWhat = (element) => {
|
|
24
|
+
// Get the name of the element.
|
|
25
|
+
const elName = element.name;
|
|
26
|
+
// If it has none:
|
|
27
|
+
if (!elName) {
|
|
28
|
+
// Return a violation description.
|
|
29
|
+
return 'radio button has no name attribute';
|
|
30
|
+
}
|
|
31
|
+
// Identify the field set of the element.
|
|
32
|
+
const elFS = element.closest('fieldset');
|
|
33
|
+
// If it has none:
|
|
34
|
+
if (!elFS) {
|
|
35
|
+
// Return a violation description.
|
|
36
|
+
return 'radio button is not in a field set';
|
|
37
|
+
}
|
|
38
|
+
// Get the first child element of the field set.
|
|
39
|
+
const fsChild1 = elFS.firstElementChild;
|
|
40
|
+
// Get whether the child is a legend with text content.
|
|
41
|
+
const legendOK = fsChild1.tagName === 'LEGEND'
|
|
42
|
+
&& fsChild1.textContent.replace(/\s/g, '').length;
|
|
43
|
+
// If it is not:
|
|
44
|
+
if (!legendOK) {
|
|
45
|
+
// Return a violation description.
|
|
46
|
+
return 'radio button is in a field set without a valid legend';
|
|
47
|
+
}
|
|
48
|
+
// Get the count of radio buttons with the same name in the field set.
|
|
49
|
+
const nameGroupSize = elFS.querySelectorAll(`input[type=radio][name=${elName}]`).length;
|
|
50
|
+
// If the count is only 1:
|
|
51
|
+
if (nameGroupSize === 1) {
|
|
52
|
+
// Return a violation description.
|
|
53
|
+
return 'radio button is the only one with its name in its field set';
|
|
54
|
+
}
|
|
55
|
+
// Get the count of radio buttons in the field set.
|
|
56
|
+
const groupSize = elFS.querySelectorAll('input[type=radio]').length;
|
|
57
|
+
// If it is greater than the count of radio buttons with the same name in the field set:
|
|
58
|
+
if (groupSize > nameGroupSize) {
|
|
59
|
+
// Return a violation description.
|
|
60
|
+
return 'radio button shares a field set with differently named others';
|
|
61
|
+
}
|
|
62
|
+
// Get the count of radio buttons with the same name in the document.
|
|
63
|
+
const nameDocSize = document.querySelectorAll(`input[type=radio][name=${elName}]`).length;
|
|
64
|
+
// If it is greater, and thus some such radio button is outside the field set:
|
|
65
|
+
if (nameDocSize > nameGroupSize) {
|
|
66
|
+
// Return a violation description.
|
|
67
|
+
return 'radio button shares a name with others outside its field set';
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const whats = 'Radio buttons are not validly grouped in fieldsets with legends';
|
|
71
|
+
return await (0, testaro_1.doTest)(page, report, withItems, 'radioSet', 'body input[type=radio]', whats, 2, getBadWhat.toString());
|
|
75
72
|
};
|
|
73
|
+
exports.reporter = reporter;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2026 Jeff Witt.
|
|
4
|
+
© 2025–2026 Jonathan Robert Pool.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License. See LICENSE file at the project root or https://opensource.org/license/mit/ for details.
|
|
7
|
+
|
|
8
|
+
SPDX-License-Identifier: MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// IMPORTS
|
|
12
|
+
|
|
13
|
+
import type {Page} from 'playwright';
|
|
14
|
+
import {doTest} from '../procs/testaro';
|
|
15
|
+
import type {BadWhat, Report} from '../types';
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
radioSet
|
|
19
|
+
This test reports nonstandard groupings of radio buttons. It defines a standard grouping to require that two or more radio buttons with the same name, and no other radio buttons, be grouped in a fieldset element with a valid legend element.
|
|
20
|
+
Compiled to radioSet.js by tsc (issue #73); edit this file, not the emitted one.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
// FUNCTIONS
|
|
24
|
+
|
|
25
|
+
// Runs the test and returns the result.
|
|
26
|
+
export const reporter = async (page: Page, report: Report, _: unknown, withItems: boolean) => {
|
|
27
|
+
// The candidate selector guarantees input elements, so the parameter is typed as one.
|
|
28
|
+
const getBadWhat = (element: HTMLInputElement): BadWhat => {
|
|
29
|
+
// Get the name of the element.
|
|
30
|
+
const elName = element.name;
|
|
31
|
+
// If it has none:
|
|
32
|
+
if (! elName) {
|
|
33
|
+
// Return a violation description.
|
|
34
|
+
return 'radio button has no name attribute';
|
|
35
|
+
}
|
|
36
|
+
// Identify the field set of the element.
|
|
37
|
+
const elFS = element.closest('fieldset');
|
|
38
|
+
// If it has none:
|
|
39
|
+
if (! elFS) {
|
|
40
|
+
// Return a violation description.
|
|
41
|
+
return 'radio button is not in a field set';
|
|
42
|
+
}
|
|
43
|
+
// Get the first child element of the field set.
|
|
44
|
+
const fsChild1 = elFS.firstElementChild;
|
|
45
|
+
// Get whether the child is a legend with text content.
|
|
46
|
+
const legendOK = fsChild1!.tagName === 'LEGEND'
|
|
47
|
+
&& fsChild1!.textContent!.replace(/\s/g, '').length;
|
|
48
|
+
// If it is not:
|
|
49
|
+
if (! legendOK) {
|
|
50
|
+
// Return a violation description.
|
|
51
|
+
return 'radio button is in a field set without a valid legend';
|
|
52
|
+
}
|
|
53
|
+
// Get the count of radio buttons with the same name in the field set.
|
|
54
|
+
const nameGroupSize = elFS.querySelectorAll(`input[type=radio][name=${elName}]`).length;
|
|
55
|
+
// If the count is only 1:
|
|
56
|
+
if (nameGroupSize === 1) {
|
|
57
|
+
// Return a violation description.
|
|
58
|
+
return 'radio button is the only one with its name in its field set';
|
|
59
|
+
}
|
|
60
|
+
// Get the count of radio buttons in the field set.
|
|
61
|
+
const groupSize = elFS.querySelectorAll('input[type=radio]').length;
|
|
62
|
+
// If it is greater than the count of radio buttons with the same name in the field set:
|
|
63
|
+
if (groupSize > nameGroupSize) {
|
|
64
|
+
// Return a violation description.
|
|
65
|
+
return 'radio button shares a field set with differently named others';
|
|
66
|
+
}
|
|
67
|
+
// Get the count of radio buttons with the same name in the document.
|
|
68
|
+
const nameDocSize = document.querySelectorAll(`input[type=radio][name=${elName}]`).length;
|
|
69
|
+
// If it is greater, and thus some such radio button is outside the field set:
|
|
70
|
+
if (nameDocSize > nameGroupSize) {
|
|
71
|
+
// Return a violation description.
|
|
72
|
+
return 'radio button shares a name with others outside its field set';
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const whats = 'Radio buttons are not validly grouped in fieldsets with legends';
|
|
76
|
+
return await doTest(
|
|
77
|
+
page, report, withItems, 'radioSet', 'body input[type=radio]', whats, 2, getBadWhat.toString()
|
|
78
|
+
);
|
|
79
|
+
};
|