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
package/tests/htmlcs.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2022–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 {getAttributeXPath, getXPathCatalogIndex} from '../procs/xPath';
|
|
17
|
+
import {getStandardResult, pushInstance} from '../procs/standard';
|
|
18
|
+
import type {Act, Report, StandardInstance, StandardResult} from '../types';
|
|
19
|
+
|
|
20
|
+
// TYPES
|
|
21
|
+
|
|
22
|
+
// The htmlcs-act properties this reporter consumes.
|
|
23
|
+
interface HtmlcsAct extends Act {
|
|
24
|
+
rules?: string[];
|
|
25
|
+
}
|
|
26
|
+
// The native result: violation totals and the parts of error and warning messages.
|
|
27
|
+
interface HtmlcsNativeResult {
|
|
28
|
+
totals: {
|
|
29
|
+
failed: number;
|
|
30
|
+
cantTell: number;
|
|
31
|
+
};
|
|
32
|
+
error: string[][];
|
|
33
|
+
warning: string[][];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
htmlcs
|
|
38
|
+
Implements the HTML CodeSniffer ruleset.
|
|
39
|
+
Compiled to htmlcs.js by tsc (issue #73); edit this file, not the emitted one.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
// FUNCTIONS
|
|
43
|
+
|
|
44
|
+
// Conducts and reports the HTML CodeSniffer tests.
|
|
45
|
+
export const reporter = async (page: Page, report: Report, actIndex: number) => {
|
|
46
|
+
const act = report.acts[actIndex] as HtmlcsAct;
|
|
47
|
+
const {rules} = act;
|
|
48
|
+
// Initialize the act report.
|
|
49
|
+
const data: {prevented?: boolean; error?: string} = {};
|
|
50
|
+
const result: {nativeResult: HtmlcsNativeResult; standardResult: StandardResult} = {
|
|
51
|
+
nativeResult: {
|
|
52
|
+
totals: {
|
|
53
|
+
failed: 0,
|
|
54
|
+
cantTell: 0
|
|
55
|
+
},
|
|
56
|
+
error: [],
|
|
57
|
+
warning: []
|
|
58
|
+
},
|
|
59
|
+
standardResult: {}
|
|
60
|
+
};
|
|
61
|
+
const standard = report.standard !== 'no';
|
|
62
|
+
// If standard results are to be reported:
|
|
63
|
+
if (standard) {
|
|
64
|
+
// Initialize the standard result.
|
|
65
|
+
result.standardResult = getStandardResult();
|
|
66
|
+
}
|
|
67
|
+
const {nativeResult, standardResult} = result;
|
|
68
|
+
// Get the HTMLCS script.
|
|
69
|
+
const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
|
|
70
|
+
const scriptNonce = (report.jobData && report.jobData.lastScriptNonce) as string | undefined;
|
|
71
|
+
let messageStrings: string[] = [];
|
|
72
|
+
// For each class of standards to be tested for:
|
|
73
|
+
for (const actStandard of ['WCAG2AAA']) {
|
|
74
|
+
const nextViolations = await page.evaluate(args => {
|
|
75
|
+
const actStandard = args[0] as string;
|
|
76
|
+
const rules = args[1] as string[] | undefined;
|
|
77
|
+
const scriptText = args[2] as string;
|
|
78
|
+
const scriptNonce = args[3] as string;
|
|
79
|
+
const script = document.createElement('script');
|
|
80
|
+
script.nonce = scriptNonce;
|
|
81
|
+
script.textContent = scriptText;
|
|
82
|
+
// 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.
|
|
83
|
+
const umdDefine = window.define;
|
|
84
|
+
const umdExports = window.exports;
|
|
85
|
+
const umdModule = window.module;
|
|
86
|
+
window.define = undefined;
|
|
87
|
+
window.exports = undefined;
|
|
88
|
+
// The cast erases; window.module otherwise types as Node's module global.
|
|
89
|
+
window.module = undefined as unknown as typeof window.module;
|
|
90
|
+
// Add the HTMLCS script to the page.
|
|
91
|
+
document.head.insertAdjacentElement('beforeend', script);
|
|
92
|
+
// Restore the loader globals.
|
|
93
|
+
window.define = umdDefine;
|
|
94
|
+
window.exports = umdExports;
|
|
95
|
+
window.module = umdModule;
|
|
96
|
+
// If only some rules are to be employed:
|
|
97
|
+
if (rules && Array.isArray(rules) && rules.length) {
|
|
98
|
+
// Redefine WCAG 2 AAA as including only them.
|
|
99
|
+
if (! window.HTMLCS_WCAG2AAA) {
|
|
100
|
+
window.HTMLCS_WCAG2AAA = {};
|
|
101
|
+
}
|
|
102
|
+
window.HTMLCS_WCAG2AAA.sniffs = rules;
|
|
103
|
+
}
|
|
104
|
+
let violations: string[] | null = null;
|
|
105
|
+
// Run the tests.
|
|
106
|
+
try {
|
|
107
|
+
violations = window.HTMLCS_RUNNER!.run(actStandard);
|
|
108
|
+
}
|
|
109
|
+
catch(error) {
|
|
110
|
+
console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${(error as Error).message})`);
|
|
111
|
+
}
|
|
112
|
+
// Return the reported violations of that standard.
|
|
113
|
+
return violations;
|
|
114
|
+
}, [actStandard, rules, scriptText, scriptNonce]);
|
|
115
|
+
// If all reported violations of the standard are validly described:
|
|
116
|
+
if (nextViolations?.every(violation => typeof violation === 'string')) {
|
|
117
|
+
// Add their descriptions to the violation descriptions.
|
|
118
|
+
messageStrings.push(... nextViolations);
|
|
119
|
+
}
|
|
120
|
+
// Otherwise, i.e. if any reported violations are invalidly described:
|
|
121
|
+
else {
|
|
122
|
+
// Report this.
|
|
123
|
+
data.prevented = true;
|
|
124
|
+
data.error = 'ERROR executing HTMLCS_RUNNER in the page';
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// If no error was thrown:
|
|
129
|
+
if (! data.prevented) {
|
|
130
|
+
// Sort the violations by class and standard.
|
|
131
|
+
messageStrings.sort();
|
|
132
|
+
// Remove any duplicate violations.
|
|
133
|
+
messageStrings = [... new Set(messageStrings)];
|
|
134
|
+
// For each violation:
|
|
135
|
+
for (const string of messageStrings) {
|
|
136
|
+
// Split its message into severity class, rule ID, tagname, ID, rule description, and excerpt.
|
|
137
|
+
const parts = string.split(/\|/, 6);
|
|
138
|
+
const partCount = parts.length;
|
|
139
|
+
// If the message partitions are too few:
|
|
140
|
+
if (partCount < 6) {
|
|
141
|
+
// Report this.
|
|
142
|
+
console.log(`ERROR: Violation string ${string} has too few parts`);
|
|
143
|
+
}
|
|
144
|
+
// Otherwise, if the message reports an error:
|
|
145
|
+
else if (parts[0] === 'Error') {
|
|
146
|
+
// Add the rest of its message to the native-result errors.
|
|
147
|
+
nativeResult.error.push(parts.slice(1));
|
|
148
|
+
// Increment the error total.
|
|
149
|
+
nativeResult.totals.failed++;
|
|
150
|
+
}
|
|
151
|
+
// Otherwise, if the message reports a warning:
|
|
152
|
+
else if (parts[0] === 'Warning') {
|
|
153
|
+
// Add the rest of its message to the native-result warnings.
|
|
154
|
+
nativeResult.warning.push(parts.slice(1));
|
|
155
|
+
// Increment the warning total.
|
|
156
|
+
nativeResult.totals.cantTell++;
|
|
157
|
+
}
|
|
158
|
+
// If standard results are to be reported and the message reports an error or warning:
|
|
159
|
+
if (standard && ['Error', 'Warning'].includes(parts[0])) {
|
|
160
|
+
const xPath = getAttributeXPath(parts[5]);
|
|
161
|
+
pushInstance(standardResult, {
|
|
162
|
+
ruleID: `${parts[0][0]}-${parts[1]}`,
|
|
163
|
+
what: parts[4],
|
|
164
|
+
ordinalSeverity: parts[0] === 'Warning' ? 0 : 2,
|
|
165
|
+
outcome: parts[0] === 'Warning' ? 'cantTell' : 'failed',
|
|
166
|
+
catalogIndex: getXPathCatalogIndex(report, xPath)
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// If standard results are to be reported:
|
|
171
|
+
if (standard) {
|
|
172
|
+
// Populate the standard-result totals.
|
|
173
|
+
standardResult.totals![0] = nativeResult.totals.cantTell;
|
|
174
|
+
standardResult.totals![2] = nativeResult.totals.failed;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
data,
|
|
179
|
+
result
|
|
180
|
+
};
|
|
181
|
+
};
|
package/tests/ibm.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Page } from 'playwright';
|
|
2
|
+
import type { Report, StandardResult } from '../types';
|
|
3
|
+
interface IbmItem {
|
|
4
|
+
ruleId: string;
|
|
5
|
+
level: string;
|
|
6
|
+
message: string;
|
|
7
|
+
snippet: string;
|
|
8
|
+
apiArgs?: unknown;
|
|
9
|
+
category?: unknown;
|
|
10
|
+
ignored?: unknown;
|
|
11
|
+
messageArgs?: unknown;
|
|
12
|
+
reasonId?: unknown;
|
|
13
|
+
ruleTime?: unknown;
|
|
14
|
+
value?: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface IbmCounts {
|
|
17
|
+
violation: number;
|
|
18
|
+
recommendation: number;
|
|
19
|
+
[key: string]: number;
|
|
20
|
+
}
|
|
21
|
+
interface IbmActReport {
|
|
22
|
+
summary?: {
|
|
23
|
+
counts?: IbmCounts;
|
|
24
|
+
};
|
|
25
|
+
results: IbmItem[];
|
|
26
|
+
items?: IbmItem[];
|
|
27
|
+
}
|
|
28
|
+
type IbmTrimmedReport = {
|
|
29
|
+
totals: IbmCounts;
|
|
30
|
+
items: IbmItem[] | undefined;
|
|
31
|
+
error?: undefined;
|
|
32
|
+
} | {
|
|
33
|
+
totals: null;
|
|
34
|
+
items: IbmItem[];
|
|
35
|
+
error: string;
|
|
36
|
+
};
|
|
37
|
+
export declare const reporter: (page: Page, report: Report, actIndex: number) => Promise<{
|
|
38
|
+
data: {};
|
|
39
|
+
result: {
|
|
40
|
+
nativeResult: IbmTrimmedReport | Record<string, never>;
|
|
41
|
+
standardResult: StandardResult;
|
|
42
|
+
};
|
|
43
|
+
} | {
|
|
44
|
+
data: {
|
|
45
|
+
report: IbmActReport;
|
|
46
|
+
} | {
|
|
47
|
+
prevented: boolean;
|
|
48
|
+
error: string;
|
|
49
|
+
};
|
|
50
|
+
result: {};
|
|
51
|
+
}>;
|
|
52
|
+
export {};
|
package/tests/ibm.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/*
|
|
2
3
|
© 2021–2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
4
|
+
© 2026 Jeff Witt.
|
|
3
5
|
© 2025–2026 Jonathan Robert Pool.
|
|
4
6
|
|
|
5
7
|
Licensed under the MIT License. See LICENSE file at the project root or
|
|
@@ -7,7 +9,12 @@
|
|
|
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 xPath_1 = require("../procs/xPath");
|
|
15
|
+
const standard_1 = require("../procs/standard");
|
|
16
|
+
const accessibilityChecker = require('accessibility-checker');
|
|
17
|
+
const { getCompliance } = accessibilityChecker;
|
|
11
18
|
/*
|
|
12
19
|
ibm
|
|
13
20
|
Implements the IBM Equal Access ruleset for accessibility.
|
|
@@ -16,192 +23,184 @@
|
|
|
16
23
|
|
|
17
24
|
This rule engine is compatible with Windows only if the accessibility-checker package
|
|
18
25
|
is revised. See README.md for details.
|
|
26
|
+
Compiled to ibm.js by tsc (issue #73); edit this file, not the emitted one.
|
|
19
27
|
*/
|
|
20
|
-
|
|
21
|
-
// IMPORTS
|
|
22
|
-
|
|
23
|
-
const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
|
|
24
|
-
const accessibilityChecker = require('accessibility-checker');
|
|
25
|
-
const {getCompliance} = accessibilityChecker;
|
|
26
|
-
|
|
27
28
|
// FUNCTIONS
|
|
28
|
-
|
|
29
29
|
// Runs the IBM test and returns the result.
|
|
30
|
-
const run = async content => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
const run = async (content) => {
|
|
31
|
+
const nowLabel = (new Date()).toISOString().slice(0, 19);
|
|
32
|
+
try {
|
|
33
|
+
const ibmReport = await getCompliance(content, nowLabel);
|
|
34
|
+
if (typeof ibmReport === 'object' && ibmReport.report) {
|
|
35
|
+
return ibmReport;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return {
|
|
39
|
+
prevented: true,
|
|
40
|
+
error: 'ibm getCompliance produced no report'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.log('ibm getCompliance failed');
|
|
46
|
+
return {
|
|
47
|
+
prevented: true,
|
|
48
|
+
error: error.message.slice(0, 200)
|
|
49
|
+
};
|
|
42
50
|
}
|
|
43
|
-
}
|
|
44
|
-
catch(error) {
|
|
45
|
-
console.log('ibm getCompliance failed');
|
|
46
|
-
return {
|
|
47
|
-
prevented: true,
|
|
48
|
-
error: error.message.slice(0, 200)
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
51
|
};
|
|
52
52
|
// Revises act-report totals for any rule limitation.
|
|
53
53
|
const limitRuleTotals = (actReport, rules) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
if (rules && Array.isArray(rules) && rules.length) {
|
|
55
|
+
const totals = actReport.summary.counts;
|
|
56
|
+
const items = actReport.results;
|
|
57
|
+
totals.violation = totals.recommendation = 0;
|
|
58
|
+
items.forEach(item => {
|
|
59
|
+
if (rules.includes(item.ruleId)) {
|
|
60
|
+
totals[item.level]++;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
64
|
};
|
|
65
65
|
// Trims an IBM report.
|
|
66
66
|
const trimActReport = (actReport, withItems, rules) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
// If the act report includes a summary:
|
|
68
|
+
if (actReport && actReport.summary) {
|
|
69
|
+
// Remove excluded rules from the act report.
|
|
70
|
+
limitRuleTotals(actReport, rules);
|
|
71
|
+
const totals = actReport.summary.counts;
|
|
72
|
+
// If the act report includes totals:
|
|
73
|
+
if (totals) {
|
|
74
|
+
// If itemization is required:
|
|
75
|
+
if (withItems) {
|
|
76
|
+
// Trim the items.
|
|
77
|
+
if (rules && Array.isArray(rules) && rules.length) {
|
|
78
|
+
actReport.items = actReport.results.filter(item => rules.includes(item.ruleId));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
actReport.items = actReport.results;
|
|
82
|
+
}
|
|
83
|
+
actReport.items.forEach(item => {
|
|
84
|
+
delete item.apiArgs;
|
|
85
|
+
delete item.category;
|
|
86
|
+
delete item.ignored;
|
|
87
|
+
delete item.messageArgs;
|
|
88
|
+
delete item.reasonId;
|
|
89
|
+
delete item.ruleTime;
|
|
90
|
+
delete item.value;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Return the act report, trimmed.
|
|
94
|
+
return {
|
|
95
|
+
totals,
|
|
96
|
+
items: actReport.items
|
|
97
|
+
};
|
|
79
98
|
}
|
|
99
|
+
// Otherwise, i.e. if it excludes totals:
|
|
80
100
|
else {
|
|
81
|
-
|
|
101
|
+
// Return an act report with this error.
|
|
102
|
+
return {
|
|
103
|
+
totals: null,
|
|
104
|
+
items: [],
|
|
105
|
+
error: 'No totals reported'
|
|
106
|
+
};
|
|
82
107
|
}
|
|
83
|
-
actReport.items.forEach(item => {
|
|
84
|
-
delete item.apiArgs;
|
|
85
|
-
delete item.category;
|
|
86
|
-
delete item.ignored;
|
|
87
|
-
delete item.messageArgs;
|
|
88
|
-
delete item.reasonId;
|
|
89
|
-
delete item.ruleTime;
|
|
90
|
-
delete item.value;
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
// Return the act report, trimmed.
|
|
94
|
-
return {
|
|
95
|
-
totals,
|
|
96
|
-
items: actReport.items
|
|
97
|
-
};
|
|
98
108
|
}
|
|
99
|
-
// Otherwise, i.e. if it excludes
|
|
109
|
+
// Otherwise, i.e. if it excludes a summary:
|
|
100
110
|
else {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
111
|
+
// Return an act report with this error.
|
|
112
|
+
return {
|
|
113
|
+
totals: null,
|
|
114
|
+
items: [],
|
|
115
|
+
error: 'No summary reported'
|
|
116
|
+
};
|
|
107
117
|
}
|
|
108
|
-
}
|
|
109
|
-
// Otherwise, i.e. if it excludes a summary:
|
|
110
|
-
else {
|
|
111
|
-
// Return an act report with this error.
|
|
112
|
-
return {
|
|
113
|
-
totals: null,
|
|
114
|
-
items: [],
|
|
115
|
-
error: 'No summary reported'
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
118
|
};
|
|
119
119
|
// Conducts and reports the IBM Equal Access tests.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
};
|
|
128
|
-
const standard = report.standard !== 'no';
|
|
129
|
-
// If standard results are to be reported:
|
|
130
|
-
if (standard) {
|
|
131
|
-
// Initialize the standard result.
|
|
132
|
-
result.standardResult = {
|
|
133
|
-
prevented: false,
|
|
134
|
-
totals: [0, 0, 0, 0],
|
|
135
|
-
instances: []
|
|
120
|
+
const reporter = async (page, report, actIndex) => {
|
|
121
|
+
const act = report.acts[actIndex];
|
|
122
|
+
const { withItems, rules } = act;
|
|
123
|
+
// Initialize the act report.
|
|
124
|
+
const result = {
|
|
125
|
+
nativeResult: {},
|
|
126
|
+
standardResult: {}
|
|
136
127
|
};
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
error
|
|
155
|
-
|
|
156
|
-
|
|
128
|
+
const standard = report.standard !== 'no';
|
|
129
|
+
// If standard results are to be reported:
|
|
130
|
+
if (standard) {
|
|
131
|
+
// Initialize the standard result.
|
|
132
|
+
result.standardResult = (0, standard_1.getStandardResult)();
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
// Conduct the tests.
|
|
136
|
+
const runReport = await run(page);
|
|
137
|
+
const actReport = runReport.report;
|
|
138
|
+
// If there were results:
|
|
139
|
+
if (actReport) {
|
|
140
|
+
// Trim them.
|
|
141
|
+
result.nativeResult = trimActReport(actReport, withItems, rules);
|
|
142
|
+
const { nativeResult, standardResult } = result;
|
|
143
|
+
const { error, totals } = nativeResult;
|
|
144
|
+
// If they were not trimmable:
|
|
145
|
+
if (error) {
|
|
146
|
+
// Return an act report with this error.
|
|
147
|
+
return {
|
|
148
|
+
data: {
|
|
149
|
+
prevented: true,
|
|
150
|
+
error
|
|
151
|
+
},
|
|
152
|
+
result: {}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Otherwise, i.e. if they were trimmable, and if standard results are to be reported:
|
|
156
|
+
if (standard) {
|
|
157
|
+
// Populate the totals of the standard result.
|
|
158
|
+
standardResult.totals = [totals.recommendation, 0, totals.violation, 0];
|
|
159
|
+
// For each item of the native result (without itemization, items is
|
|
160
|
+
// undefined and this throws, caught below; verbatim from the original):
|
|
161
|
+
nativeResult.items.forEach(item => {
|
|
162
|
+
// Populate a standard instance. Potential violations, potential recommendations, and
|
|
163
|
+
// manual checks are engine-flagged uncertainty.
|
|
164
|
+
const standardItem = {
|
|
165
|
+
ruleID: item.ruleId,
|
|
166
|
+
what: item.message,
|
|
167
|
+
ordinalSeverity: item.level === 'recommendation' ? 0 : 2,
|
|
168
|
+
outcome: ['violation', 'recommendation'].includes(item.level) ? 'failed' : 'cantTell'
|
|
169
|
+
};
|
|
170
|
+
// Get the XPath from the added attribute, because path.dom is wrong.
|
|
171
|
+
const xPath = (0, xPath_1.getAttributeXPath)(item.snippet);
|
|
172
|
+
// If the XPath was obtained:
|
|
173
|
+
if (xPath) {
|
|
174
|
+
// Add the catalog index to the standard instance.
|
|
175
|
+
standardItem.catalogIndex = (0, xPath_1.getXPathCatalogIndex)(report, xPath);
|
|
176
|
+
}
|
|
177
|
+
// Add the standard instance to the standard result.
|
|
178
|
+
(0, standard_1.pushInstance)(standardResult, standardItem);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
data: {},
|
|
183
|
+
result
|
|
184
|
+
};
|
|
157
185
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// For each item of the native result:
|
|
164
|
-
nativeResult.items.forEach(item => {
|
|
165
|
-
// Populate a standard instance.
|
|
166
|
-
const standardItem = {
|
|
167
|
-
ruleID: item.ruleId,
|
|
168
|
-
what: item.message,
|
|
169
|
-
ordinalSeverity: item.level === 'recommendation' ? 0 : 2,
|
|
170
|
-
count: 1
|
|
171
|
-
};
|
|
172
|
-
// Get the XPath from the added attribute, because path.dom is wrong.
|
|
173
|
-
const xPath = getAttributeXPath(item.snippet);
|
|
174
|
-
// If the XPath was obtained:
|
|
175
|
-
if (xPath) {
|
|
176
|
-
// Add the catalog index to the standard instance.
|
|
177
|
-
standardItem.catalogIndex = getXPathCatalogIndex(report, xPath);
|
|
178
|
-
}
|
|
179
|
-
// Add the standard instance to the standard result.
|
|
180
|
-
standardResult.instances.push(standardItem);
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
return {
|
|
184
|
-
data: {},
|
|
185
|
-
result
|
|
186
|
-
};
|
|
186
|
+
// Otherwise, i.e. if there was only an error, return it in an act report.
|
|
187
|
+
return {
|
|
188
|
+
data: runReport,
|
|
189
|
+
result: {}
|
|
190
|
+
};
|
|
187
191
|
}
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
+
// If an error occurred:
|
|
193
|
+
catch (error) {
|
|
194
|
+
const message = `Act failed (${error.message.slice(0, 200)})`;
|
|
195
|
+
console.log(message);
|
|
196
|
+
// Return it in an act report.
|
|
197
|
+
return {
|
|
198
|
+
data: {
|
|
199
|
+
prevented: true,
|
|
200
|
+
error: message
|
|
201
|
+
},
|
|
202
|
+
result: {}
|
|
203
|
+
};
|
|
192
204
|
}
|
|
193
|
-
}
|
|
194
|
-
// If an error occurred:
|
|
195
|
-
catch(error) {
|
|
196
|
-
const message = `Act failed (${error.message.slice(0, 200)})`;
|
|
197
|
-
console.log(message);
|
|
198
|
-
// Return it in an act report.
|
|
199
|
-
return {
|
|
200
|
-
data: {
|
|
201
|
-
prevented: true,
|
|
202
|
-
error: message
|
|
203
|
-
},
|
|
204
|
-
result: {}
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
205
|
};
|
|
206
|
+
exports.reporter = reporter;
|