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
package/tests/ed11y.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2023–2024 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
|
|
7
|
+
https://opensource.org/license/mit/ for details.
|
|
8
|
+
|
|
9
|
+
SPDX-License-Identifier: MIT
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// IMPORTS
|
|
13
|
+
|
|
14
|
+
import * as fs from 'fs/promises';
|
|
15
|
+
import type {Page} from 'playwright';
|
|
16
|
+
import {getXPathCatalogIndex} from '../procs/xPath';
|
|
17
|
+
import {getStandardResult, pushInstance} from '../procs/standard';
|
|
18
|
+
import type {Act, Report, SeverityTotals, StandardInstance, StandardResult} from '../types';
|
|
19
|
+
|
|
20
|
+
// TYPES
|
|
21
|
+
|
|
22
|
+
// The ed11y-act properties this reporter consumes.
|
|
23
|
+
interface Ed11yAct extends Act {
|
|
24
|
+
rules?: string[];
|
|
25
|
+
}
|
|
26
|
+
// One test result exposed by the Ed11y global.
|
|
27
|
+
interface Ed11yToolResult {
|
|
28
|
+
test: string;
|
|
29
|
+
content: string;
|
|
30
|
+
dismissalKey: string;
|
|
31
|
+
element: Element;
|
|
32
|
+
}
|
|
33
|
+
// One instance of the native result.
|
|
34
|
+
interface Ed11yNativeInstance {
|
|
35
|
+
test: string;
|
|
36
|
+
content: string;
|
|
37
|
+
dismissalKey: string;
|
|
38
|
+
html: string;
|
|
39
|
+
xPath: string | null | undefined;
|
|
40
|
+
}
|
|
41
|
+
// The native result: totals and instances, or a prevention report.
|
|
42
|
+
interface Ed11yNativeResult {
|
|
43
|
+
resultCount?: number;
|
|
44
|
+
errorCount?: number;
|
|
45
|
+
warningCount?: number;
|
|
46
|
+
results?: Ed11yNativeInstance[];
|
|
47
|
+
prevented?: boolean;
|
|
48
|
+
error?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
The Ed11y global that the tool script defines in the page: a constructor whose
|
|
53
|
+
test results are exposed as static properties. Declared without a value, so
|
|
54
|
+
this declaration is erased at emit and the references inside the page.evaluate
|
|
55
|
+
callback remain bare page-global references.
|
|
56
|
+
*/
|
|
57
|
+
declare const Ed11y: {
|
|
58
|
+
new (options: {alertMode: string}): unknown;
|
|
59
|
+
results: Ed11yToolResult[];
|
|
60
|
+
errorCount: number;
|
|
61
|
+
warningCount: number;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/*
|
|
65
|
+
ed11y
|
|
66
|
+
Implements the Editoria11y ruleset for accessibility.
|
|
67
|
+
Compiled to ed11y.js by tsc (issue #73); edit this file, not the emitted one.
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
// FUNCTIONS
|
|
71
|
+
|
|
72
|
+
// Performs and reports the Editoria11y tests.
|
|
73
|
+
export const reporter = async (page: Page, report: Report, actIndex: number) => {
|
|
74
|
+
// Get the nonce, if any.
|
|
75
|
+
const act = report.acts[actIndex] as Ed11yAct;
|
|
76
|
+
const {jobData} = report;
|
|
77
|
+
const scriptNonce = (jobData && jobData.lastScriptNonce) as string | undefined;
|
|
78
|
+
// Initialize the act report.
|
|
79
|
+
let data: {prevented?: boolean; error?: string} = {};
|
|
80
|
+
const result: {nativeResult: Ed11yNativeResult; standardResult: StandardResult} = {
|
|
81
|
+
nativeResult: {},
|
|
82
|
+
standardResult: {}
|
|
83
|
+
};
|
|
84
|
+
const standard = report.standard !== 'no';
|
|
85
|
+
// If standard results are to be reported:
|
|
86
|
+
if (standard) {
|
|
87
|
+
// Initialize the standard result.
|
|
88
|
+
result.standardResult = getStandardResult();
|
|
89
|
+
}
|
|
90
|
+
// Get the tool script.
|
|
91
|
+
const script = await fs.readFile(`${__dirname}/../ed11y/editoria11y.min.js`, 'utf8');
|
|
92
|
+
// Perform the specified tests and populate the native result.
|
|
93
|
+
result.nativeResult = await page.evaluate(args => new Promise<Ed11yNativeResult>(
|
|
94
|
+
async resolve => {
|
|
95
|
+
const {scriptNonce, script, rulesToTest} = args;
|
|
96
|
+
// When the script has been executed, creating data in an Ed11y object:
|
|
97
|
+
document.addEventListener('ed11yResults', async () => {
|
|
98
|
+
let {results} = Ed11y;
|
|
99
|
+
// If rules were selected:
|
|
100
|
+
if (rulesToTest) {
|
|
101
|
+
// Remove results of other rules.
|
|
102
|
+
results = results.filter(result => rulesToTest.includes(result.test));
|
|
103
|
+
}
|
|
104
|
+
// Return the native result.
|
|
105
|
+
resolve({
|
|
106
|
+
resultCount: results.length,
|
|
107
|
+
errorCount: Ed11y.errorCount,
|
|
108
|
+
warningCount: Ed11y.warningCount,
|
|
109
|
+
results: results.map(result => ({
|
|
110
|
+
test: result.test,
|
|
111
|
+
content: result.content.replace(/\s+/g, ' ').trim(),
|
|
112
|
+
dismissalKey: result.dismissalKey,
|
|
113
|
+
html: result.element.outerHTML.slice(0, 500),
|
|
114
|
+
xPath: window.getXPath(result.element)
|
|
115
|
+
}))
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
// Add the tool script to the page.
|
|
119
|
+
const toolScript = document.createElement('script');
|
|
120
|
+
if (scriptNonce) {
|
|
121
|
+
toolScript.nonce = scriptNonce;
|
|
122
|
+
console.log(`Added nonce ${scriptNonce} to tool script`);
|
|
123
|
+
}
|
|
124
|
+
toolScript.textContent = script;
|
|
125
|
+
document.body.insertAdjacentElement('beforeend', toolScript);
|
|
126
|
+
// Execute the tool script, creating Ed11y and triggering the event listener.
|
|
127
|
+
try {
|
|
128
|
+
await new Ed11y({
|
|
129
|
+
alertMode: 'headless'
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch(error) {
|
|
133
|
+
resolve({
|
|
134
|
+
prevented: true,
|
|
135
|
+
error: (error as Error).message
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
), {
|
|
140
|
+
scriptNonce,
|
|
141
|
+
script,
|
|
142
|
+
rulesToTest: act.rules
|
|
143
|
+
});
|
|
144
|
+
// If the tool script failed to run:
|
|
145
|
+
if (result.nativeResult.prevented) {
|
|
146
|
+
// Report the prevention.
|
|
147
|
+
data.prevented = true;
|
|
148
|
+
data.error = result.nativeResult.error as string;
|
|
149
|
+
if (standard) {
|
|
150
|
+
result.standardResult.prevented = true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Otherwise, i.e. if it ran, and if a standard result is to be reported:
|
|
154
|
+
else if (standard) {
|
|
155
|
+
const {standardResult} = result;
|
|
156
|
+
const {warningCount, errorCount, results} = result.nativeResult as Required<Ed11yNativeResult>;
|
|
157
|
+
// Populate the standard-result totals.
|
|
158
|
+
standardResult.totals = [warningCount, 0, errorCount, 0] as SeverityTotals;
|
|
159
|
+
// For each native-result instance:
|
|
160
|
+
results.forEach(nativeInstance => {
|
|
161
|
+
// Create a standard-result instance.
|
|
162
|
+
const {test, content, dismissalKey, xPath} = nativeInstance;
|
|
163
|
+
// A dismissable warning is a manual check.
|
|
164
|
+
pushInstance(standardResult, {
|
|
165
|
+
ruleID: test,
|
|
166
|
+
what: content,
|
|
167
|
+
ordinalSeverity: dismissalKey ? 0 : 2,
|
|
168
|
+
outcome: dismissalKey ? 'cantTell' : 'failed',
|
|
169
|
+
uncertainty: dismissalKey ? 'judgement-required' : undefined,
|
|
170
|
+
catalogIndex: getXPathCatalogIndex(report, xPath as string)
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
data,
|
|
176
|
+
result
|
|
177
|
+
};
|
|
178
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { Report, StandardResult } from '../types';
|
|
3
|
+
interface HtmlcsNativeResult {
|
|
4
|
+
totals: {
|
|
5
|
+
failed: number;
|
|
6
|
+
cantTell: number;
|
|
7
|
+
};
|
|
8
|
+
error: string[][];
|
|
9
|
+
warning: string[][];
|
|
10
|
+
}
|
|
11
|
+
export declare const reporter: (page: Page, report: Report, actIndex: number) => Promise<{
|
|
12
|
+
data: {
|
|
13
|
+
prevented?: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
};
|
|
16
|
+
result: {
|
|
17
|
+
nativeResult: HtmlcsNativeResult;
|
|
18
|
+
standardResult: StandardResult;
|
|
19
|
+
};
|
|
20
|
+
}>;
|
|
21
|
+
export {};
|
package/tests/htmlcs.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2022–2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
4
|
© 2026 Jeff Witt.
|
|
@@ -8,154 +9,187 @@
|
|
|
8
9
|
|
|
9
10
|
SPDX-License-Identifier: MIT
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.reporter = void 0;
|
|
47
|
+
// IMPORTS
|
|
48
|
+
const fs = __importStar(require("fs/promises"));
|
|
49
|
+
const xPath_1 = require("../procs/xPath");
|
|
50
|
+
const standard_1 = require("../procs/standard");
|
|
12
51
|
/*
|
|
13
52
|
htmlcs
|
|
14
53
|
Implements the HTML CodeSniffer ruleset.
|
|
54
|
+
Compiled to htmlcs.js by tsc (issue #73); edit this file, not the emitted one.
|
|
15
55
|
*/
|
|
16
|
-
|
|
17
|
-
// IMPORTS
|
|
18
|
-
|
|
19
|
-
const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
|
|
20
|
-
const fs = require('fs/promises');
|
|
21
|
-
|
|
22
56
|
// FUNCTIONS
|
|
23
|
-
|
|
24
57
|
// Conducts and reports the HTML CodeSniffer tests.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
const standard = report.standard !== 'no';
|
|
42
|
-
// If standard results are to be reported:
|
|
43
|
-
if (standard) {
|
|
44
|
-
// Initialize the standard result.
|
|
45
|
-
result.standardResult = {
|
|
46
|
-
prevented: false,
|
|
47
|
-
totals: [0, 0, 0, 0],
|
|
48
|
-
instances: []
|
|
58
|
+
const reporter = async (page, report, actIndex) => {
|
|
59
|
+
const act = report.acts[actIndex];
|
|
60
|
+
const { rules } = act;
|
|
61
|
+
// Initialize the act report.
|
|
62
|
+
const data = {};
|
|
63
|
+
const result = {
|
|
64
|
+
nativeResult: {
|
|
65
|
+
totals: {
|
|
66
|
+
failed: 0,
|
|
67
|
+
cantTell: 0
|
|
68
|
+
},
|
|
69
|
+
error: [],
|
|
70
|
+
warning: []
|
|
71
|
+
},
|
|
72
|
+
standardResult: {}
|
|
49
73
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let messageStrings = [];
|
|
56
|
-
// For each class of standards to be tested for:
|
|
57
|
-
for (const actStandard of ['WCAG2AAA']) {
|
|
58
|
-
const nextViolations = await page.evaluate(args => {
|
|
59
|
-
const actStandard = args[0];
|
|
60
|
-
const rules = args[1];
|
|
61
|
-
const scriptText = args[2];
|
|
62
|
-
const scriptNonce = args[3];
|
|
63
|
-
const script = document.createElement('script');
|
|
64
|
-
script.nonce = scriptNonce;
|
|
65
|
-
script.textContent = scriptText;
|
|
66
|
-
// HTMLCS.js is a UMD bundle. If the page exposes an AMD loader (define.amd, e.g. Wix or RequireJS) or leaked CommonJS globals (exports, module), the UMD wrapper registers HTMLCS as a module and never attaches HTMLCS_RUNNER to window, so the run() call below throws and the tool is reported prevented. Hide those loader globals for the duration of the synchronous script execution, so the wrapper falls through to its browser-global branch.
|
|
67
|
-
const umdDefine = window.define;
|
|
68
|
-
const umdExports = window.exports;
|
|
69
|
-
const umdModule = window.module;
|
|
70
|
-
window.define = undefined;
|
|
71
|
-
window.exports = undefined;
|
|
72
|
-
window.module = undefined;
|
|
73
|
-
// Add the HTMLCS script to the page.
|
|
74
|
-
document.head.insertAdjacentElement('beforeend', script);
|
|
75
|
-
// Restore the loader globals.
|
|
76
|
-
window.define = umdDefine;
|
|
77
|
-
window.exports = umdExports;
|
|
78
|
-
window.module = umdModule;
|
|
79
|
-
// If only some rules are to be employed:
|
|
80
|
-
if (rules && Array.isArray(rules) && rules.length) {
|
|
81
|
-
// Redefine WCAG 2 AAA as including only them.
|
|
82
|
-
if (! window.HTMLCS_WCAG2AAA) {
|
|
83
|
-
window.HTMLCS_WCAG2AAA = {};
|
|
84
|
-
}
|
|
85
|
-
window.HTMLCS_WCAG2AAA.sniffs = rules;
|
|
86
|
-
}
|
|
87
|
-
let violations = null;
|
|
88
|
-
// Run the tests.
|
|
89
|
-
try {
|
|
90
|
-
violations = window.HTMLCS_RUNNER.run(actStandard);
|
|
91
|
-
}
|
|
92
|
-
catch(error) {
|
|
93
|
-
console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
|
|
94
|
-
}
|
|
95
|
-
// Return the reported violations of that standard.
|
|
96
|
-
return violations;
|
|
97
|
-
}, [actStandard, rules, scriptText, scriptNonce]);
|
|
98
|
-
// If all reported violations of the standard are validly described:
|
|
99
|
-
if (nextViolations?.every(violation => typeof violation === 'string')) {
|
|
100
|
-
// Add their descriptions to the violation descriptions.
|
|
101
|
-
messageStrings.push(... nextViolations);
|
|
74
|
+
const standard = report.standard !== 'no';
|
|
75
|
+
// If standard results are to be reported:
|
|
76
|
+
if (standard) {
|
|
77
|
+
// Initialize the standard result.
|
|
78
|
+
result.standardResult = (0, standard_1.getStandardResult)();
|
|
102
79
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
80
|
+
const { nativeResult, standardResult } = result;
|
|
81
|
+
// Get the HTMLCS script.
|
|
82
|
+
const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
|
|
83
|
+
const scriptNonce = (report.jobData && report.jobData.lastScriptNonce);
|
|
84
|
+
let messageStrings = [];
|
|
85
|
+
// For each class of standards to be tested for:
|
|
86
|
+
for (const actStandard of ['WCAG2AAA']) {
|
|
87
|
+
const nextViolations = await page.evaluate(args => {
|
|
88
|
+
const actStandard = args[0];
|
|
89
|
+
const rules = args[1];
|
|
90
|
+
const scriptText = args[2];
|
|
91
|
+
const scriptNonce = args[3];
|
|
92
|
+
const script = document.createElement('script');
|
|
93
|
+
script.nonce = scriptNonce;
|
|
94
|
+
script.textContent = scriptText;
|
|
95
|
+
// HTMLCS.js is a UMD bundle. If the page exposes an AMD loader (define.amd, e.g. Wix or RequireJS) or leaked CommonJS globals (exports, module), the UMD wrapper registers HTMLCS as a module and never attaches HTMLCS_RUNNER to window, so the run() call below throws and the tool is reported prevented. Hide those loader globals for the duration of the synchronous script execution, so the wrapper falls through to its browser-global branch.
|
|
96
|
+
const umdDefine = window.define;
|
|
97
|
+
const umdExports = window.exports;
|
|
98
|
+
const umdModule = window.module;
|
|
99
|
+
window.define = undefined;
|
|
100
|
+
window.exports = undefined;
|
|
101
|
+
// The cast erases; window.module otherwise types as Node's module global.
|
|
102
|
+
window.module = undefined;
|
|
103
|
+
// Add the HTMLCS script to the page.
|
|
104
|
+
document.head.insertAdjacentElement('beforeend', script);
|
|
105
|
+
// Restore the loader globals.
|
|
106
|
+
window.define = umdDefine;
|
|
107
|
+
window.exports = umdExports;
|
|
108
|
+
window.module = umdModule;
|
|
109
|
+
// If only some rules are to be employed:
|
|
110
|
+
if (rules && Array.isArray(rules) && rules.length) {
|
|
111
|
+
// Redefine WCAG 2 AAA as including only them.
|
|
112
|
+
if (!window.HTMLCS_WCAG2AAA) {
|
|
113
|
+
window.HTMLCS_WCAG2AAA = {};
|
|
114
|
+
}
|
|
115
|
+
window.HTMLCS_WCAG2AAA.sniffs = rules;
|
|
116
|
+
}
|
|
117
|
+
let violations = null;
|
|
118
|
+
// Run the tests.
|
|
119
|
+
try {
|
|
120
|
+
violations = window.HTMLCS_RUNNER.run(actStandard);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
|
|
124
|
+
}
|
|
125
|
+
// Return the reported violations of that standard.
|
|
126
|
+
return violations;
|
|
127
|
+
}, [actStandard, rules, scriptText, scriptNonce]);
|
|
128
|
+
// If all reported violations of the standard are validly described:
|
|
129
|
+
if (nextViolations?.every(violation => typeof violation === 'string')) {
|
|
130
|
+
// Add their descriptions to the violation descriptions.
|
|
131
|
+
messageStrings.push(...nextViolations);
|
|
132
|
+
}
|
|
133
|
+
// Otherwise, i.e. if any reported violations are invalidly described:
|
|
134
|
+
else {
|
|
135
|
+
// Report this.
|
|
136
|
+
data.prevented = true;
|
|
137
|
+
data.error = 'ERROR executing HTMLCS_RUNNER in the page';
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
109
140
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
141
|
+
// If no error was thrown:
|
|
142
|
+
if (!data.prevented) {
|
|
143
|
+
// Sort the violations by class and standard.
|
|
144
|
+
messageStrings.sort();
|
|
145
|
+
// Remove any duplicate violations.
|
|
146
|
+
messageStrings = [...new Set(messageStrings)];
|
|
147
|
+
// For each violation:
|
|
148
|
+
for (const string of messageStrings) {
|
|
149
|
+
// Split its message into severity class, rule ID, tagname, ID, rule description, and excerpt.
|
|
150
|
+
const parts = string.split(/\|/, 6);
|
|
151
|
+
const partCount = parts.length;
|
|
152
|
+
// If the message partitions are too few:
|
|
153
|
+
if (partCount < 6) {
|
|
154
|
+
// Report this.
|
|
155
|
+
console.log(`ERROR: Violation string ${string} has too few parts`);
|
|
156
|
+
}
|
|
157
|
+
// Otherwise, if the message reports an error:
|
|
158
|
+
else if (parts[0] === 'Error') {
|
|
159
|
+
// Add the rest of its message to the native-result errors.
|
|
160
|
+
nativeResult.error.push(parts.slice(1));
|
|
161
|
+
// Increment the error total.
|
|
162
|
+
nativeResult.totals.failed++;
|
|
163
|
+
}
|
|
164
|
+
// Otherwise, if the message reports a warning:
|
|
165
|
+
else if (parts[0] === 'Warning') {
|
|
166
|
+
// Add the rest of its message to the native-result warnings.
|
|
167
|
+
nativeResult.warning.push(parts.slice(1));
|
|
168
|
+
// Increment the warning total.
|
|
169
|
+
nativeResult.totals.cantTell++;
|
|
170
|
+
}
|
|
171
|
+
// If standard results are to be reported and the message reports an error or warning:
|
|
172
|
+
if (standard && ['Error', 'Warning'].includes(parts[0])) {
|
|
173
|
+
const xPath = (0, xPath_1.getAttributeXPath)(parts[5]);
|
|
174
|
+
(0, standard_1.pushInstance)(standardResult, {
|
|
175
|
+
ruleID: `${parts[0][0]}-${parts[1]}`,
|
|
176
|
+
what: parts[4],
|
|
177
|
+
ordinalSeverity: parts[0] === 'Warning' ? 0 : 2,
|
|
178
|
+
outcome: parts[0] === 'Warning' ? 'cantTell' : 'failed',
|
|
179
|
+
catalogIndex: (0, xPath_1.getXPathCatalogIndex)(report, xPath)
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// If standard results are to be reported:
|
|
184
|
+
if (standard) {
|
|
185
|
+
// Populate the standard-result totals.
|
|
186
|
+
standardResult.totals[0] = nativeResult.totals.cantTell;
|
|
187
|
+
standardResult.totals[2] = nativeResult.totals.failed;
|
|
188
|
+
}
|
|
153
189
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
data,
|
|
159
|
-
result
|
|
160
|
-
};
|
|
190
|
+
return {
|
|
191
|
+
data,
|
|
192
|
+
result
|
|
193
|
+
};
|
|
161
194
|
};
|
|
195
|
+
exports.reporter = reporter;
|