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/procs/xPath.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2026 Jeff Witt.
|
|
4
|
+
© 2026 Jonathan Robert Pool.
|
|
5
|
+
|
|
6
|
+
Licensed under the MIT License. See LICENSE file at the project root or
|
|
7
|
+
https://opensource.org/license/mit/ for details.
|
|
8
|
+
|
|
9
|
+
SPDX-License-Identifier: MIT
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// IMPORTS
|
|
13
|
+
|
|
14
|
+
import type {Catalog, Report} from '../types';
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
xPath
|
|
18
|
+
Processes element XPaths. Compiled to xPath.js by tsc (issue #73); edit this
|
|
19
|
+
file, not the emitted one.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// FUNCTIONS
|
|
23
|
+
|
|
24
|
+
// Normalizes an XPath.
|
|
25
|
+
export const getNormalizedXPath = (xPath: string | null | undefined): string => {
|
|
26
|
+
if (xPath) {
|
|
27
|
+
if (xPath === '/') {
|
|
28
|
+
xPath = '/html';
|
|
29
|
+
}
|
|
30
|
+
xPath = xPath.replace(/^\.\/\//, '/');
|
|
31
|
+
const segments = xPath.split('/');
|
|
32
|
+
// Initialize an array of normalized segments.
|
|
33
|
+
const normalizedSegments: string[] = [];
|
|
34
|
+
// For each segment of the XPath:
|
|
35
|
+
segments.forEach(segment => {
|
|
36
|
+
// If the segment is html[1] or body[1]:
|
|
37
|
+
if (/html\[1\]|body\[1\]/.test(segment)) {
|
|
38
|
+
// Add it without its subscript to the array.
|
|
39
|
+
normalizedSegments.push(segment.replace(/\[1\]/, ''));
|
|
40
|
+
}
|
|
41
|
+
// Otherwise, if the segment is empty or html or body or ends with a subscript:
|
|
42
|
+
else if (segment === '' || ['html', 'body'].includes(segment) || segment.endsWith(']')) {
|
|
43
|
+
// Add it to the array.
|
|
44
|
+
normalizedSegments.push(segment);
|
|
45
|
+
}
|
|
46
|
+
// Otherwise, i.e. if the segment is a tag name with no subscript:
|
|
47
|
+
else {
|
|
48
|
+
// Add it with a subscript 1 to the array.
|
|
49
|
+
normalizedSegments.push(`${segment}[1]`);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
// If the final segment contains any nonstandard character:
|
|
53
|
+
if (/[[^\]A-Za-z0-9]/.test(segments[segments.length - 1])) {
|
|
54
|
+
// Remove it.
|
|
55
|
+
normalizedSegments.pop();
|
|
56
|
+
}
|
|
57
|
+
// Return the concatenated segments as the normalized XPath.
|
|
58
|
+
return normalizedSegments.join('/');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
return '/html';
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
// Gets an XPath from a data-xpath attribute in an HTML excerpt.
|
|
65
|
+
export const getAttributeXPath = (html: string | null | undefined): string => {
|
|
66
|
+
// If there is no excerpt (e.g. a Nu Html Checker message without an extract):
|
|
67
|
+
if (! html) {
|
|
68
|
+
// Return the fallback XPath, as for an excerpt without a data-xpath attribute.
|
|
69
|
+
return '/html';
|
|
70
|
+
}
|
|
71
|
+
const match = html.match(/ data-xpath="([^" ]+)"/);
|
|
72
|
+
return match ? match[1] : '/html';
|
|
73
|
+
};
|
|
74
|
+
// Gets a tag name from an XPath.
|
|
75
|
+
const getXPathTagName = (xPath: string): string => {
|
|
76
|
+
return (xPath.split('/').pop() as string).replace(/\[.+/, '').toUpperCase();
|
|
77
|
+
};
|
|
78
|
+
// Gets a catalog index as a string from an XPath, within a checkpoint (the active one by
|
|
79
|
+
// default). An XPath the checkpoint's catalog lacks gets a stub entry, keyed from the report's
|
|
80
|
+
// monotonic counter so that entries of different checkpoints never collide.
|
|
81
|
+
export const getXPathCatalogIndex = (
|
|
82
|
+
report: Report, xPath: string, checkpoint: number = report.activeCheckpoint ?? 0
|
|
83
|
+
): string => {
|
|
84
|
+
// The catalog always exists by the time tests cite elements (getCatalog ran first).
|
|
85
|
+
const {catalog} = report as Report & {catalog: Catalog};
|
|
86
|
+
report.pathIDs ??= {};
|
|
87
|
+
const pathIDs = (report.pathIDs[checkpoint] ??= {});
|
|
88
|
+
// Get the index of the catalog item with the XPath.
|
|
89
|
+
const index = pathIDs[xPath];
|
|
90
|
+
// If no such item exists (an index of '0' is a match, so test for absence, not falsity):
|
|
91
|
+
if (index === undefined) {
|
|
92
|
+
// Add an item to the catalog, keyed by the counter (or, in a report without one, by the
|
|
93
|
+
// count of items already in it).
|
|
94
|
+
const newIndex = report.catalogNextIndex === undefined
|
|
95
|
+
? `${Object.keys(catalog).length}`
|
|
96
|
+
: `${report.catalogNextIndex++}`;
|
|
97
|
+
catalog[newIndex] = {
|
|
98
|
+
pathID: xPath,
|
|
99
|
+
tagName: getXPathTagName(xPath),
|
|
100
|
+
checkpoint
|
|
101
|
+
};
|
|
102
|
+
pathIDs[xPath] = newIndex;
|
|
103
|
+
return newIndex;
|
|
104
|
+
}
|
|
105
|
+
return index;
|
|
106
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type {Page} from 'playwright';
|
|
2
|
+
|
|
3
|
+
// The in-page script defining window.getXPath, as source text.
|
|
4
|
+
export const getXPathSource: string;
|
|
5
|
+
// Defines window.getXPath on a live page if it is not already defined.
|
|
6
|
+
export function defineGetXPath(page: Page): Promise<void>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2026 Jeff Witt.
|
|
3
|
+
|
|
4
|
+
Licensed under the MIT License. See LICENSE file at the project root or
|
|
5
|
+
https://opensource.org/license/mit/ for details.
|
|
6
|
+
|
|
7
|
+
SPDX-License-Identifier: MIT
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
xPathScript
|
|
12
|
+
The in-page script that defines window.getXPath, shared by the launcher (which adds it as an
|
|
13
|
+
init script to every page it creates) and the checkpoint cataloguer (which defines it on a live
|
|
14
|
+
page that was launched without it).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// FUNCTIONS
|
|
18
|
+
|
|
19
|
+
// Defines window.getXPath in the page. Runs inside the page, so it must be closure-free.
|
|
20
|
+
const installGetXPath = () => {
|
|
21
|
+
window.getXPath = element => {
|
|
22
|
+
if (! element || element.nodeType !== Node.ELEMENT_NODE) {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
const segments = [];
|
|
26
|
+
// As long as the current node is an element:
|
|
27
|
+
while (element && element.nodeType === Node.ELEMENT_NODE) {
|
|
28
|
+
const tag = element.tagName.toLowerCase();
|
|
29
|
+
// If it is the html element:
|
|
30
|
+
if (element === document.documentElement) {
|
|
31
|
+
// Prepend it to the segment array
|
|
32
|
+
segments.unshift('html');
|
|
33
|
+
// Stop traversing.
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
// Otherwise, get its parent node.
|
|
37
|
+
const parent = element.parentNode;
|
|
38
|
+
// If (abnormally) the parent node is not an element:
|
|
39
|
+
if (! parent || parent.nodeType !== Node.ELEMENT_NODE) {
|
|
40
|
+
// Prepend the element (not the parent) to the segment array.
|
|
41
|
+
segments.unshift(tag);
|
|
42
|
+
// Stop traversing, leaving the segment array partial.
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
// Get the subscript of the element if it is not the body element.
|
|
46
|
+
const cohort = Array
|
|
47
|
+
.from(parent.childNodes)
|
|
48
|
+
.filter(
|
|
49
|
+
childNode => childNode.nodeType === Node.ELEMENT_NODE
|
|
50
|
+
&& childNode.tagName === element.tagName
|
|
51
|
+
);
|
|
52
|
+
const subscript = tag === 'body' ? '' : `[${cohort.indexOf(element) + 1}]`;
|
|
53
|
+
// Prepend the element identifier to the segment array.
|
|
54
|
+
segments.unshift(`${tag}${subscript}`);
|
|
55
|
+
// Continue the traversal with the parent of the current element.
|
|
56
|
+
element = parent;
|
|
57
|
+
}
|
|
58
|
+
// Return the XPath.
|
|
59
|
+
return `/${segments.join('/')}`;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
// The script as source text, for addInitScript and evaluate.
|
|
63
|
+
const getXPathSource = exports.getXPathSource = `(${installGetXPath.toString()})();`;
|
|
64
|
+
// Defines window.getXPath on a live page if it is not already defined.
|
|
65
|
+
exports.defineGetXPath = async page => {
|
|
66
|
+
const isDefined = await page.evaluate(() => typeof window.getXPath === 'function');
|
|
67
|
+
if (! isDefined) {
|
|
68
|
+
await page.evaluate(getXPathSource);
|
|
69
|
+
}
|
|
70
|
+
};
|
package/run.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
const {doActs} = require('./procs/doActs');
|
|
20
20
|
require('dotenv').config({quiet: true});
|
|
21
|
-
const {isValidJob} = require('./procs/job');
|
|
21
|
+
const {getIsolation, isValidJob} = require('./procs/job');
|
|
22
22
|
const {getCatalog} = require('./procs/catalog');
|
|
23
23
|
const {nowString} = require('./procs/dateTime');
|
|
24
24
|
const {chromium} = require('playwright-extra');
|
|
@@ -131,7 +131,8 @@ exports.doJob = async (job, opts = {}) => {
|
|
|
131
131
|
presses: 0,
|
|
132
132
|
amountRead: 0,
|
|
133
133
|
toolTimes: {},
|
|
134
|
-
preventions: {}
|
|
134
|
+
preventions: {},
|
|
135
|
+
isolation: getIsolation(job)
|
|
135
136
|
};
|
|
136
137
|
process.on('message', message => {
|
|
137
138
|
if (message === 'interrupt') {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Vendored SureA11y core bundle
|
|
2
|
+
|
|
3
|
+
Upstream: [SureA11y/core](https://github.com/SureA11y/core) (`@surea11y/core` on npm,
|
|
4
|
+
**MPL-2.0** — file-level copyleft: modifications to the vendored file itself must remain
|
|
5
|
+
MPL-2.0; the rest of this repo is unaffected. The bundle is vendored verbatim, unmodified).
|
|
6
|
+
|
|
7
|
+
## Vendoring
|
|
8
|
+
|
|
9
|
+
No build step: upstream publishes a self-contained standalone browser bundle. To vendor or
|
|
10
|
+
update:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm pack @surea11y/core@<version>
|
|
14
|
+
tar xzf surea11y-core-<version>.tgz
|
|
15
|
+
cp package/surea11y.browser.js surea11y/surea11y.browser.js
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The bundle defines one global, `a11ycore`, exposing `runa11yCoreInPage(pageUrl,
|
|
19
|
+
contextSelector, engineOptions, runOnly)`; `tests/surea11y.js` reports the act as `prevented`
|
|
20
|
+
if the file is missing or the global is absent. English-only by design (locale side files
|
|
21
|
+
exist upstream; not vendored).
|
|
22
|
+
|
|
23
|
+
## Result shape (verified against 1.7.0, schemaVersion 1.0.0)
|
|
24
|
+
|
|
25
|
+
`runa11yCoreInPage()` returns `{engine: {tag: 'a11ycore', schemaVersion, wcagVersion},
|
|
26
|
+
checksResults, rulesResults, ...}`. Each `checksResults` entry:
|
|
27
|
+
`{ruleId, outcome: pass|fail|cantTell|notApplicable, severity: minor|moderate|serious|critical,
|
|
28
|
+
confidence, type: automatic|manual, occurrences, title, meta: {normativeMappings:
|
|
29
|
+
[{standard, version, requirement, ...}], ...}}`. Occurrences carry `{selector, html, summary,
|
|
30
|
+
occurrenceOutcome?: fail|cantTell, uncertainty?}` — a `fail`-outcome rule may grade individual
|
|
31
|
+
occurrences into `cantTell` tier via `occurrenceOutcome`, which the adapter honors
|
|
32
|
+
per-occurrence, and the adapter forwards the occurrence's (else the check's) `uncertainty.code`
|
|
33
|
+
and `uncertainty.needed` as the standard instance's `uncertainty` and `needed`. `pass` results serialize no occurrences; `notApplicable` may carry one
|
|
34
|
+
scan-describing occurrence (empty selector) which the adapter must not count. Full contract:
|
|
35
|
+
upstream `docs/OUTPUT_SCHEMA.md` (pinned to `schemaVersion` — the adapter reports `prevented`
|
|
36
|
+
on a major schema change is NOT automatic; re-verify at each vendor bump).
|
|
37
|
+
|
|
38
|
+
## Pinned version
|
|
39
|
+
|
|
40
|
+
- **Vendored:** 2026-09-01
|
|
41
|
+
- **Upstream:** `@surea11y/core` 1.7.0 (npm tarball, published bundle used verbatim)
|
|
42
|
+
- **Bundle:** 749 KB standalone browser IIFE, global `a11ycore`
|
|
43
|
+
- **Smoke-tested:** see yra-monitor `docs/plans/engine-candidacy-pipeline.md` candidate
|
|
44
|
+
register for Stage-1 results.
|