testaro 30.0.8 → 32.0.1
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/CONTRIBUTING.md +26 -4
- package/LICENSE +1 -1
- package/README.md +24 -2
- package/aceconfig.js +27 -0
- package/actSpecs.js +28 -1
- package/call.js +22 -1
- package/data/template.js +22 -0
- package/dirWatch.js +22 -0
- package/package.json +1 -1
- package/procs/aslint.js +24 -0
- package/procs/getLocatorData.js +29 -1
- package/procs/getSource.js +30 -3
- package/procs/isInlineLink.js +23 -0
- package/procs/operable.js +23 -2
- package/procs/sample.js +22 -0
- package/procs/standardize.js +28 -7
- package/procs/tellServer.js +24 -2
- package/procs/testaro.js +26 -1
- package/procs/visChange.js +22 -0
- package/run.js +373 -83
- package/testaro/allCaps.js +22 -0
- package/testaro/allHidden.js +22 -0
- package/testaro/allSlanted.js +22 -0
- package/testaro/attVal.js +22 -0
- package/testaro/autocomplete.js +22 -0
- package/testaro/bulk.js +22 -0
- package/testaro/buttonMenu.js +22 -0
- package/testaro/distortion.js +22 -0
- package/testaro/docType.js +22 -0
- package/testaro/dupAtt.js +22 -0
- package/testaro/elements.js +22 -0
- package/testaro/embAc.js +22 -0
- package/testaro/filter.js +22 -0
- package/testaro/focAll.js +22 -0
- package/testaro/focInd.js +22 -0
- package/testaro/focOp.js +22 -0
- package/testaro/focVis.js +22 -0
- package/testaro/headEl.js +22 -0
- package/testaro/headingAmb.js +22 -0
- package/testaro/hovInd.js +21 -24
- package/testaro/hover.js +22 -0
- package/testaro/labClash.js +22 -0
- package/testaro/lineHeight.js +22 -0
- package/testaro/linkAmb.js +22 -0
- package/testaro/linkTitle.js +22 -0
- package/testaro/linkUl.js +22 -0
- package/testaro/miniText.js +22 -0
- package/testaro/motion.js +22 -0
- package/testaro/nonTable.js +22 -0
- package/testaro/opFoc.js +22 -0
- package/testaro/pseudoP.js +25 -3
- package/testaro/radioSet.js +22 -0
- package/testaro/role.js +22 -0
- package/testaro/styleDiff.js +80 -1
- package/testaro/tabNav.js +99 -2
- package/testaro/targetSize.js +22 -0
- package/testaro/textNodes.js +25 -3
- package/testaro/title.js +22 -0
- package/testaro/zIndex.js +22 -0
- package/tests/alfa.js +34 -12
- package/tests/aslint.js +55 -17
- package/tests/axe.js +35 -9
- package/tests/htmlcs.js +109 -78
- package/tests/ibm.js +111 -45
- package/tests/nuVal.js +39 -9
- package/tests/qualWeb.js +49 -25
- package/tests/testaro.js +50 -22
- package/tests/wave.js +36 -10
- package/validation/executors/run.js +26 -2
- package/validation/executors/test.js +27 -3
- package/validation/executors/tests.js +26 -2
- package/validation/executors/watchDir.js +26 -2
- package/validation/executors/watchNet.js +26 -2
- package/validation/jobs/todo/README.md +22 -0
- package/validation/tests/targets/adbID/index.html +21 -0
- package/validation/tests/targets/allCaps/index.html +21 -0
- package/validation/tests/targets/allHidden/ariaHiddenBody.html +21 -0
- package/validation/tests/targets/allHidden/good.html +21 -0
- package/validation/tests/targets/allHidden/hiddenMain.html +21 -0
- package/validation/tests/targets/allHidden/mixedHidden.html +22 -1
- package/validation/tests/targets/allHidden/noBody.html +21 -0
- package/validation/tests/targets/allHidden/noMain.html +21 -0
- package/validation/tests/targets/allHidden/noneDoc.html +21 -0
- package/validation/tests/targets/allHidden/visHiddenMain.html +21 -0
- package/validation/tests/targets/allSlanted/index.html +21 -0
- package/validation/tests/targets/altScheme/index.html +21 -0
- package/validation/tests/targets/attVal/bad.html +21 -0
- package/validation/tests/targets/attVal/good.html +21 -0
- package/validation/tests/targets/autocomplete/bad.html +21 -0
- package/validation/tests/targets/autocomplete/good.html +21 -0
- package/validation/tests/targets/bulk/bad.html +21 -0
- package/validation/tests/targets/bulk/good.html +21 -0
- package/validation/tests/targets/buttonMenu/bad.html +21 -0
- package/validation/tests/targets/buttonMenu/bad.js +27 -0
- package/validation/tests/targets/buttonMenu/good.html +21 -0
- package/validation/tests/targets/buttonMenu/good.js +27 -0
- package/validation/tests/targets/buttonMenu/style.css +27 -0
- package/validation/tests/targets/captionLoc/index.html +21 -0
- package/validation/tests/targets/datalistRef/index.html +21 -0
- package/validation/tests/targets/distortion/index.html +21 -0
- package/validation/tests/targets/docType/bad.html +21 -0
- package/validation/tests/targets/docType/good.html +21 -0
- package/validation/tests/targets/dupAtt/bad.html +21 -0
- package/validation/tests/targets/dupAtt/good.html +21 -0
- package/validation/tests/targets/elements/index.html +21 -0
- package/validation/tests/targets/embAc/bad.html +21 -0
- package/validation/tests/targets/embAc/good.html +21 -0
- package/validation/tests/targets/filter/bad.html +21 -0
- package/validation/tests/targets/filter/good.html +21 -0
- package/validation/tests/targets/focAll/good.html +21 -0
- package/validation/tests/targets/focAll/less.html +21 -0
- package/validation/tests/targets/focAll/more.html +21 -0
- package/validation/tests/targets/focInd/bad.html +21 -0
- package/validation/tests/targets/focInd/good.html +21 -0
- package/validation/tests/targets/focOp/bad.html +21 -0
- package/validation/tests/targets/focOp/good.html +21 -0
- package/validation/tests/targets/focVis/index.html +21 -0
- package/validation/tests/targets/headEl/index.html +21 -0
- package/validation/tests/targets/headingAmb/index.html +21 -0
- package/validation/tests/targets/hovInd/index.html +21 -0
- package/validation/tests/targets/hover/bad.html +21 -0
- package/validation/tests/targets/hover/good.html +21 -0
- package/validation/tests/targets/hr/index.html +21 -0
- package/validation/tests/targets/imageLink/index.html +21 -0
- package/validation/tests/targets/labClash/bad.html +21 -0
- package/validation/tests/targets/labClash/good.html +21 -0
- package/validation/tests/targets/legendLoc/index.html +21 -0
- package/validation/tests/targets/lineHeight/index.html +21 -0
- package/validation/tests/targets/linkAmb/index.html +21 -0
- package/validation/tests/targets/linkExt/index.html +21 -0
- package/validation/tests/targets/linkOldAtt/index.html +21 -0
- package/validation/tests/targets/linkTitle/index.html +21 -0
- package/validation/tests/targets/linkTo/index.html +21 -0
- package/validation/tests/targets/linkUl/bad.html +21 -0
- package/validation/tests/targets/linkUl/good.html +21 -0
- package/validation/tests/targets/linkUl/na.html +21 -0
- package/validation/tests/targets/miniText/index.html +21 -0
- package/validation/tests/targets/motion/bad.css +27 -0
- package/validation/tests/targets/motion/bad.html +21 -0
- package/validation/tests/targets/motion/good.html +21 -0
- package/validation/tests/targets/nonTable/index.html +21 -0
- package/validation/tests/targets/opFoc/bad.html +21 -0
- package/validation/tests/targets/opFoc/good.html +21 -0
- package/validation/tests/targets/optRoleSel/index.html +21 -0
- package/validation/tests/targets/phOnly/index.html +21 -0
- package/validation/tests/targets/pseudoP/index.html +21 -0
- package/validation/tests/targets/radioSet/bad.html +21 -0
- package/validation/tests/targets/radioSet/good.html +21 -0
- package/validation/tests/targets/role/bad.html +21 -0
- package/validation/tests/targets/role/good.html +21 -0
- package/validation/tests/targets/secHeading/index.html +21 -0
- package/validation/tests/targets/styleDiff/bad.html +21 -0
- package/validation/tests/targets/styleDiff/good.html +21 -0
- package/validation/tests/targets/tabNav/bad.html +21 -0
- package/validation/tests/targets/tabNav/bad.js +27 -0
- package/validation/tests/targets/tabNav/good.html +21 -0
- package/validation/tests/targets/tabNav/good.js +27 -0
- package/validation/tests/targets/tabNav/style.css +27 -0
- package/validation/tests/targets/targetSize/index.html +21 -0
- package/validation/tests/targets/textNodes/index.html +21 -0
- package/validation/tests/targets/textSem/index.html +21 -0
- package/validation/tests/targets/title/bad.html +21 -0
- package/validation/tests/targets/title/good.html +21 -0
- package/validation/tests/targets/titledEl/index.html +21 -0
- package/validation/tests/targets/zIndex/bad.html +21 -0
- package/validation/tests/targets/zIndex/good.html +21 -0
- package/validation/validateTest.js +39 -3
- package/validation/watch/done/README.md +23 -1
- package/validation/watch/todo/README.md +23 -1
- package/watch.js +32 -7
- package/call-old.js +0 -86
- package/procs/allText.js +0 -76
- package/procs/allVis.js +0 -17
- package/procs/getTextNodes.js +0 -39
- package/procs/linksByType.js +0 -54
- package/procs/nav.js +0 -259
- package/procs/textOf.txt +0 -73
- package/test copy.js +0 -38
- package/validation/tests/old/allCaps.json +0 -102
- package/validation/tests/old/allHidden.json +0 -314
- package/validation/tests/old/attVal.json +0 -60
- package/validation/tests/old/autocomplete.json +0 -51
- package/validation/tests/old/bulk.json +0 -48
- package/validation/tests/old/docType.json +0 -46
- package/validation/tests/old/dupAtt.json +0 -51
- package/validation/tests/old/elements.json +0 -140
- package/validation/tests/old/embAc.json +0 -54
- package/validation/tests/old/filter.json +0 -55
- package/validation/tests/old/focAll.json +0 -68
- package/validation/tests/old/focInd.json +0 -69
- package/validation/tests/old/focOp.json +0 -62
- package/validation/tests/old/focVis.json +0 -35
- package/validation/tests/old/hover.json +0 -118
- package/validation/tests/old/labClash.json +0 -52
- package/validation/tests/old/linkTo.json +0 -35
- package/validation/tests/old/linkUl.json +0 -71
- package/validation/tests/old/menuNav.json +0 -106
- package/validation/tests/old/miniText.json +0 -36
- package/validation/tests/old/motion.json +0 -62
- package/validation/tests/old/nonTable.json +0 -37
- package/validation/tests/old/radioSet.json +0 -52
- package/validation/tests/old/role.json +0 -60
- package/validation/tests/old/styleDiff.json +0 -71
- package/validation/tests/old/tabNav.json +0 -106
- package/validation/tests/old/temp.js +0 -28
- package/validation/tests/old/textNodes.json +0 -98
- package/validation/tests/old/title.json +0 -46
- package/validation/tests/old/titledEl.json +0 -37
- package/validation/tests/old/zIndex.json +0 -49
- package/validation/tests/targets/tabNav/goodMoz.js +0 -206
- package/watch-old.js +0 -275
- package/watch-temp.js +0 -45
package/tests/aslint.js
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
|
|
1
23
|
/*
|
|
2
24
|
aslint
|
|
3
25
|
This test implements the ASLint ruleset for accessibility.
|
|
@@ -12,15 +34,18 @@ const fs = require('fs/promises');
|
|
|
12
34
|
|
|
13
35
|
// Conducts and reports an ASLint test.
|
|
14
36
|
exports.reporter = async (page, options) => {
|
|
15
|
-
// Initialize the report.
|
|
37
|
+
// Initialize the act report.
|
|
16
38
|
let data = {};
|
|
39
|
+
let result = {};
|
|
17
40
|
// Get the ASLint runner and bundle scripts.
|
|
18
41
|
const aslintRunner = await fs.readFile(`${__dirname}/../procs/aslint.js`, 'utf8');
|
|
19
42
|
const aslintBundle = await fs.readFile(
|
|
20
43
|
`${__dirname}/../node_modules/aslint-testaro/aslint.bundle.js`, 'utf8'
|
|
21
44
|
);
|
|
22
45
|
// Get the nonce, if any.
|
|
23
|
-
const {
|
|
46
|
+
const {report} = options;
|
|
47
|
+
const {jobData} = report;
|
|
48
|
+
const scriptNonce = jobData && jobData.lastScriptNonce;
|
|
24
49
|
// Inject the ASLint bundle and runner into the page.
|
|
25
50
|
await page.evaluate(args => {
|
|
26
51
|
const {scriptNonce, aslintBundle, aslintRunner} = args;
|
|
@@ -43,41 +68,54 @@ exports.reporter = async (page, options) => {
|
|
|
43
68
|
document.body.insertAdjacentElement('beforeend', runnerEl);
|
|
44
69
|
}, {scriptNonce, aslintBundle, aslintRunner})
|
|
45
70
|
.catch(error => {
|
|
46
|
-
|
|
71
|
+
const message = `ERROR: ASLint injection failed (${error.message.slice(0, 400)})`;
|
|
72
|
+
console.log(message);
|
|
47
73
|
data.prevented = true;
|
|
48
|
-
data.error =
|
|
74
|
+
data.error = message;
|
|
49
75
|
});
|
|
50
76
|
// If the injection succeeded:
|
|
77
|
+
const reportLoc = page.locator('#aslintResult');
|
|
51
78
|
if (! data.prevented) {
|
|
52
79
|
// Wait for the test results.
|
|
53
|
-
const reportLoc = page.locator('#aslintResult');
|
|
54
80
|
await reportLoc.waitFor({
|
|
55
81
|
state: 'attached',
|
|
56
|
-
timeout:
|
|
82
|
+
timeout: 30000
|
|
83
|
+
})
|
|
84
|
+
.catch(error => {
|
|
85
|
+
const message = `ERROR: Results timed out (${error.message.slice(0, 400)})`;
|
|
86
|
+
console.log(message);
|
|
87
|
+
data.prevented = true;
|
|
88
|
+
data.error = message;
|
|
57
89
|
});
|
|
90
|
+
}
|
|
91
|
+
// If the results arrived in time:
|
|
92
|
+
if (! data.prevented) {
|
|
58
93
|
// Get them.
|
|
59
|
-
const
|
|
60
|
-
// Populate the
|
|
61
|
-
|
|
94
|
+
const actReport = await reportLoc.textContent();
|
|
95
|
+
// Populate the act report.
|
|
96
|
+
result = JSON.parse(actReport);
|
|
62
97
|
// Delete irrelevant properties from the tool report details.
|
|
63
|
-
if (
|
|
64
|
-
Object.keys(
|
|
65
|
-
if (['passed', 'skipped'].includes(
|
|
66
|
-
delete
|
|
98
|
+
if (result.rules) {
|
|
99
|
+
Object.keys(result.rules).forEach(ruleID => {
|
|
100
|
+
if (['passed', 'skipped'].includes(result.rules[ruleID].status.type)) {
|
|
101
|
+
delete result.rules[ruleID];
|
|
67
102
|
}
|
|
68
103
|
});
|
|
69
104
|
}
|
|
70
105
|
}
|
|
71
|
-
// Return the
|
|
106
|
+
// Return the act report.
|
|
72
107
|
try {
|
|
73
108
|
JSON.stringify(data);
|
|
74
109
|
}
|
|
75
110
|
catch(error) {
|
|
76
|
-
|
|
111
|
+
const message = `ERROR: ASLint result cannot be made JSON (${error.message.slice(0, 200)})`;
|
|
77
112
|
data = {
|
|
78
113
|
prevented: true,
|
|
79
|
-
error:
|
|
114
|
+
error: message
|
|
80
115
|
};
|
|
81
116
|
}
|
|
82
|
-
return {
|
|
117
|
+
return {
|
|
118
|
+
data,
|
|
119
|
+
result
|
|
120
|
+
};
|
|
83
121
|
};
|
package/tests/axe.js
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
|
|
1
23
|
/*
|
|
2
24
|
axe
|
|
3
25
|
This test implements the axe-core ruleset for accessibility.
|
|
@@ -28,8 +50,9 @@ const {injectAxe, getAxeResults} = require('axe-playwright');
|
|
|
28
50
|
// Conducts and reports an Axe test.
|
|
29
51
|
exports.reporter = async (page, options) => {
|
|
30
52
|
const {detailLevel, rules} = options;
|
|
31
|
-
// Initialize the report.
|
|
53
|
+
// Initialize the act report.
|
|
32
54
|
let data = {};
|
|
55
|
+
let result = {};
|
|
33
56
|
// Inject axe-core into the page.
|
|
34
57
|
await injectAxe(page)
|
|
35
58
|
.catch(error => {
|
|
@@ -58,7 +81,7 @@ exports.reporter = async (page, options) => {
|
|
|
58
81
|
const {inapplicable, passes, incomplete, violations} = axeReport;
|
|
59
82
|
if (violations) {
|
|
60
83
|
// Initialize the result.
|
|
61
|
-
|
|
84
|
+
result.totals = {
|
|
62
85
|
rulesNA: 0,
|
|
63
86
|
rulesPassed: 0,
|
|
64
87
|
rulesWarned: 0,
|
|
@@ -76,9 +99,9 @@ exports.reporter = async (page, options) => {
|
|
|
76
99
|
critical: 0
|
|
77
100
|
}
|
|
78
101
|
};
|
|
79
|
-
|
|
102
|
+
result.details = axeReport;
|
|
80
103
|
// Populate the totals.
|
|
81
|
-
const {totals} =
|
|
104
|
+
const {totals} = result;
|
|
82
105
|
totals.rulesNA = inapplicable.length;
|
|
83
106
|
totals.rulesPassed = passes.length;
|
|
84
107
|
incomplete.forEach(rule => {
|
|
@@ -104,8 +127,7 @@ exports.reporter = async (page, options) => {
|
|
|
104
127
|
else {
|
|
105
128
|
// Report this.
|
|
106
129
|
data.prevented = true;
|
|
107
|
-
data.error = 'ERROR:
|
|
108
|
-
console.log('ERROR: axe failed');
|
|
130
|
+
data.error = 'ERROR: Act failed';
|
|
109
131
|
}
|
|
110
132
|
}
|
|
111
133
|
// Return the result.
|
|
@@ -113,11 +135,15 @@ exports.reporter = async (page, options) => {
|
|
|
113
135
|
JSON.stringify(data);
|
|
114
136
|
}
|
|
115
137
|
catch(error) {
|
|
116
|
-
|
|
138
|
+
const message = `ERROR: Axe result cannot be made JSON (${error.message})`;
|
|
139
|
+
console.log(message);
|
|
117
140
|
data = {
|
|
118
141
|
prevented: true,
|
|
119
|
-
error:
|
|
142
|
+
error: message
|
|
120
143
|
};
|
|
121
144
|
}
|
|
122
|
-
return {
|
|
145
|
+
return {
|
|
146
|
+
data,
|
|
147
|
+
result
|
|
148
|
+
};
|
|
123
149
|
};
|
package/tests/htmlcs.js
CHANGED
|
@@ -1,94 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2022–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
|
|
1
23
|
/*
|
|
2
24
|
htmlcs
|
|
3
25
|
This test implements the HTML CodeSniffer ruleset.
|
|
4
26
|
*/
|
|
5
27
|
|
|
28
|
+
// IMPORTS
|
|
29
|
+
|
|
30
|
+
// Module to handle files.
|
|
31
|
+
const fs = require('fs/promises');
|
|
32
|
+
|
|
6
33
|
// FUNCTIONS
|
|
7
|
-
|
|
34
|
+
|
|
35
|
+
// Runs HTML CodeSniffer on the page and returns an act report.
|
|
8
36
|
exports.reporter = async (page, options) => {
|
|
9
|
-
const {rules} = options;
|
|
37
|
+
const {report, rules} = options;
|
|
38
|
+
const data = {};
|
|
10
39
|
const result = {};
|
|
11
|
-
//
|
|
12
|
-
await
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
window.HTMLCS_WCAG2AAA.sniffs = rules;
|
|
40
|
+
// Get the HTMLCS script.
|
|
41
|
+
const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
|
|
42
|
+
const scriptNonce = report.jobData && report.jobData.lastScriptNonce;
|
|
43
|
+
// Define the rules to be employed as those of WCAG 2 level AAA.
|
|
44
|
+
let messageStrings = [];
|
|
45
|
+
for (const actStandard of ['WCAG2AAA']) {
|
|
46
|
+
const nextIssues = await page.evaluate(args => {
|
|
47
|
+
// Add the HTMLCS script to the page.
|
|
48
|
+
const scriptText = args[2];
|
|
49
|
+
const scriptNonce = args[3];
|
|
50
|
+
const script = document.createElement('script');
|
|
51
|
+
script.nonce = scriptNonce;
|
|
52
|
+
script.textContent = scriptText;
|
|
53
|
+
document.head.insertAdjacentElement('beforeend', script);
|
|
54
|
+
// If only some rules are to be employed:
|
|
55
|
+
const actStandard = args[0];
|
|
56
|
+
const rules = args[1];
|
|
57
|
+
if (rules && Array.isArray(rules) && rules.length) {
|
|
58
|
+
// Redefine WCAG 2 AAA as including only them.
|
|
59
|
+
if (! window.HTMLCS_WCAG2AAA) {
|
|
60
|
+
window.HTMLCS_WCAG2AAA = {};
|
|
34
61
|
}
|
|
35
|
-
|
|
36
|
-
let issues = null;
|
|
37
|
-
try {
|
|
38
|
-
issues = window.HTMLCS_RUNNER.run(standard);
|
|
39
|
-
}
|
|
40
|
-
catch(error) {
|
|
41
|
-
console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
|
|
42
|
-
}
|
|
43
|
-
return issues;
|
|
44
|
-
}, [standard, rules]);
|
|
45
|
-
if (nextIssues && nextIssues.every(issue => typeof issue === 'string')) {
|
|
46
|
-
messageStrings.push(... nextIssues);
|
|
62
|
+
window.HTMLCS_WCAG2AAA.sniffs = rules;
|
|
47
63
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
64
|
+
// Run the tests.
|
|
65
|
+
let issues = null;
|
|
66
|
+
try {
|
|
67
|
+
issues = window.HTMLCS_RUNNER.run(actStandard);
|
|
52
68
|
}
|
|
69
|
+
catch(error) {
|
|
70
|
+
console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
|
|
71
|
+
}
|
|
72
|
+
return issues;
|
|
73
|
+
}, [actStandard, rules, scriptText, scriptNonce]);
|
|
74
|
+
if (nextIssues && nextIssues.every(issue => typeof issue === 'string')) {
|
|
75
|
+
messageStrings.push(... nextIssues);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
data.prevented = true;
|
|
79
|
+
data.error = 'ERROR executing HTMLCS_RUNNER in the page';
|
|
80
|
+
break;
|
|
53
81
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
}
|
|
83
|
+
if (! data.prevented) {
|
|
84
|
+
// Sort the issues by class and standard.
|
|
85
|
+
messageStrings.sort();
|
|
86
|
+
// Remove any duplicate issues.
|
|
87
|
+
messageStrings = [... new Set(messageStrings)];
|
|
88
|
+
// Initialize the result.
|
|
89
|
+
result.Error = {};
|
|
90
|
+
result.Warning = {};
|
|
91
|
+
// For each issue:
|
|
92
|
+
messageStrings.forEach(string => {
|
|
93
|
+
const parts = string.split(/\|/, 6);
|
|
94
|
+
const partCount = parts.length;
|
|
95
|
+
if (partCount < 6) {
|
|
96
|
+
console.log(`ERROR: Issue string ${string} has too few parts`);
|
|
97
|
+
}
|
|
98
|
+
// If it is an error or a warning (not a notice):
|
|
99
|
+
else if (['Error', 'Warning'].includes(parts[0])) {
|
|
100
|
+
/*
|
|
101
|
+
Add the issue to an issueClass.issueCode.description array in the result.
|
|
102
|
+
This saves space, because, although some descriptions are issue-specific, such as
|
|
103
|
+
descriptions that state the contrast ratio of an element, most descriptions are
|
|
104
|
+
generic, so typically many violations share a description.
|
|
105
|
+
*/
|
|
106
|
+
const issueCode = parts[1].replace(/^WCAG2|\.Principle\d\.Guideline[\d_]+/g, '');
|
|
107
|
+
if (! result[parts[0]][issueCode]) {
|
|
108
|
+
result[parts[0]][issueCode] = {};
|
|
68
109
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
/*
|
|
72
|
-
Add the issue to an issueClass.issueCode.description array in the result.
|
|
73
|
-
This saves space, because, although some descriptions are issue-specific, such as
|
|
74
|
-
descriptions that state the contrast ratio of an element, most descriptions are
|
|
75
|
-
generic, so typically many issues share a description.
|
|
76
|
-
*/
|
|
77
|
-
const issueCode = parts[1].replace(/^WCAG2|\.Principle\d\.Guideline[\d_]+/g, '');
|
|
78
|
-
if (! result[parts[0]][issueCode]) {
|
|
79
|
-
result[parts[0]][issueCode] = {};
|
|
80
|
-
}
|
|
81
|
-
if (! result[parts[0]][issueCode][parts[4]]) {
|
|
82
|
-
result[parts[0]][issueCode][parts[4]] = [];
|
|
83
|
-
}
|
|
84
|
-
result[parts[0]][issueCode][parts[4]].push({
|
|
85
|
-
tagName: parts[2],
|
|
86
|
-
id: parts[3],
|
|
87
|
-
code: parts[5]
|
|
88
|
-
});
|
|
110
|
+
if (! result[parts[0]][issueCode][parts[4]]) {
|
|
111
|
+
result[parts[0]][issueCode][parts[4]] = [];
|
|
89
112
|
}
|
|
90
|
-
|
|
91
|
-
|
|
113
|
+
result[parts[0]][issueCode][parts[4]].push({
|
|
114
|
+
tagName: parts[2],
|
|
115
|
+
id: parts[3],
|
|
116
|
+
code: parts[5]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
92
120
|
}
|
|
93
|
-
return {
|
|
121
|
+
return {
|
|
122
|
+
data,
|
|
123
|
+
result
|
|
124
|
+
};
|
|
94
125
|
};
|
package/tests/ibm.js
CHANGED
|
@@ -1,19 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
|
|
1
23
|
/*
|
|
2
24
|
ibm
|
|
3
25
|
This test implements the IBM Equal Access ruleset for accessibility.
|
|
4
26
|
The 'withNewContent' argument determines whether the test package should be
|
|
5
27
|
given the URL of the page to be tested (true) or the page content (false).
|
|
6
|
-
|
|
28
|
+
|
|
7
29
|
This test depends on aceconfig.js.
|
|
8
30
|
|
|
9
31
|
This tool is compatible with Windows only if the accessibility-checker package
|
|
10
32
|
is revised. See README.md for details.
|
|
11
33
|
*/
|
|
12
|
-
|
|
34
|
+
|
|
35
|
+
// IMPORTS
|
|
36
|
+
|
|
13
37
|
const fs = require('fs').promises;
|
|
14
38
|
// Scanner. Importing and executing 'close' crashed the Node process.
|
|
15
39
|
const {getCompliance} = require('accessibility-checker');
|
|
16
|
-
|
|
40
|
+
|
|
41
|
+
// FUNCTIONS
|
|
42
|
+
|
|
43
|
+
// Runs the IBM test and returns the result.
|
|
17
44
|
const run = async (content, timeLimit) => {
|
|
18
45
|
const nowLabel = (new Date()).toISOString().slice(0, 19);
|
|
19
46
|
// Start the timeout clock.
|
|
@@ -37,11 +64,11 @@ const run = async (content, timeLimit) => {
|
|
|
37
64
|
return null;
|
|
38
65
|
}
|
|
39
66
|
};
|
|
40
|
-
// Revises report totals for any rule limitation.
|
|
41
|
-
const limitRuleTotals = (
|
|
67
|
+
// Revises act-report totals for any rule limitation.
|
|
68
|
+
const limitRuleTotals = (actReport, rules) => {
|
|
42
69
|
if (rules && Array.isArray(rules) && rules.length) {
|
|
43
|
-
const totals =
|
|
44
|
-
const items =
|
|
70
|
+
const totals = actReport.summary.counts;
|
|
71
|
+
const items = actReport.results;
|
|
45
72
|
totals.violation = totals.recommendation = 0;
|
|
46
73
|
items.forEach(item => {
|
|
47
74
|
if (rules.includes(item.ruleId)) {
|
|
@@ -51,21 +78,24 @@ const limitRuleTotals = (report, rules) => {
|
|
|
51
78
|
}
|
|
52
79
|
};
|
|
53
80
|
// Trims an IBM report.
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
const trimActReport = (data, actReport, withItems, rules) => {
|
|
82
|
+
// If the act report includes a summary:
|
|
83
|
+
if (actReport && actReport.summary) {
|
|
84
|
+
// Remove excluded rules from the act report.
|
|
85
|
+
limitRuleTotals(actReport, rules);
|
|
86
|
+
// If the act report includes totals:
|
|
87
|
+
const totals = actReport.summary.counts;
|
|
59
88
|
if (totals) {
|
|
60
|
-
|
|
89
|
+
// If itemization is required:
|
|
61
90
|
if (withItems) {
|
|
91
|
+
// Trim the items.
|
|
62
92
|
if (rules && Array.isArray(rules) && rules.length) {
|
|
63
|
-
|
|
93
|
+
actReport.items = actReport.results.filter(item => rules.includes(item.ruleId));
|
|
64
94
|
}
|
|
65
95
|
else {
|
|
66
|
-
|
|
96
|
+
actReport.items = actReport.results;
|
|
67
97
|
}
|
|
68
|
-
|
|
98
|
+
actReport.items.forEach(item => {
|
|
69
99
|
delete item.apiArgs;
|
|
70
100
|
delete item.category;
|
|
71
101
|
delete item.ignored;
|
|
@@ -75,31 +105,43 @@ const trimReport = (report, withItems, rules) => {
|
|
|
75
105
|
delete item.value;
|
|
76
106
|
});
|
|
77
107
|
}
|
|
108
|
+
// Return the act report, trimmed.
|
|
109
|
+
return {
|
|
110
|
+
totals,
|
|
111
|
+
items: actReport.items
|
|
112
|
+
};
|
|
78
113
|
}
|
|
114
|
+
// Otherwise, i.e. if it excludes totals:
|
|
79
115
|
else {
|
|
116
|
+
// Report this.
|
|
80
117
|
data.prevented = true;
|
|
81
|
-
data.error = 'ERROR:
|
|
118
|
+
data.error = 'ERROR: No totals reported';
|
|
119
|
+
// Return an empty act report.
|
|
120
|
+
return {
|
|
121
|
+
totals: {},
|
|
122
|
+
items: []
|
|
123
|
+
};
|
|
82
124
|
}
|
|
83
125
|
}
|
|
126
|
+
// Otherwise, i.e. if it excludes a summary:
|
|
84
127
|
else {
|
|
128
|
+
// Report this.
|
|
85
129
|
data.prevented = true;
|
|
86
|
-
data.error = 'ERROR:
|
|
130
|
+
data.error = 'ERROR: No summary reported';
|
|
131
|
+
// Return an empty act report.
|
|
132
|
+
return {
|
|
133
|
+
totals: {},
|
|
134
|
+
items: []
|
|
135
|
+
};
|
|
87
136
|
}
|
|
88
|
-
return data;
|
|
89
137
|
};
|
|
90
|
-
// Performs the IBM tests and returns
|
|
138
|
+
// Performs the IBM tests and returns an act report.
|
|
91
139
|
const doTest = async (content, withItems, timeLimit, rules) => {
|
|
92
140
|
// Conduct the test and get the result.
|
|
93
|
-
|
|
141
|
+
const data = {};
|
|
94
142
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
catch(error) {
|
|
98
|
-
console.log(`ibm test failed ${error.message.slice(0, 100)}...`);
|
|
99
|
-
report = null;
|
|
100
|
-
}
|
|
101
|
-
// If the test did not crash or time out:
|
|
102
|
-
if (report) {
|
|
143
|
+
const runReport = await run(content, timeLimit);
|
|
144
|
+
const actReport = runReport && runReport.report;
|
|
103
145
|
// Delete any report files.
|
|
104
146
|
try {
|
|
105
147
|
const reportNames = await fs.readdir('results');
|
|
@@ -108,37 +150,61 @@ const doTest = async (content, withItems, timeLimit, rules) => {
|
|
|
108
150
|
}
|
|
109
151
|
}
|
|
110
152
|
catch(error) {
|
|
111
|
-
console.log('
|
|
153
|
+
console.log('No result files created');
|
|
112
154
|
}
|
|
113
|
-
// Return
|
|
114
|
-
const
|
|
115
|
-
return
|
|
155
|
+
// Return a trimmed act report.
|
|
156
|
+
const trimmedReport = trimActReport(data, actReport, withItems, rules);
|
|
157
|
+
return {
|
|
158
|
+
data,
|
|
159
|
+
result: trimmedReport
|
|
160
|
+
};
|
|
116
161
|
}
|
|
117
|
-
|
|
162
|
+
catch(error) {
|
|
163
|
+
const message = `Act failed (${error.message.slice(0, 200)})`;
|
|
164
|
+
console.log(message);
|
|
165
|
+
data.prevented = true;
|
|
166
|
+
data.error = message;
|
|
118
167
|
return {
|
|
119
|
-
|
|
120
|
-
|
|
168
|
+
data,
|
|
169
|
+
result: {}
|
|
121
170
|
};
|
|
122
171
|
}
|
|
123
172
|
};
|
|
124
|
-
//
|
|
173
|
+
// Performs ibm tests and returns an act report.
|
|
125
174
|
exports.reporter = async (page, options) => {
|
|
126
175
|
const {withItems, withNewContent, rules} = options;
|
|
127
176
|
const contentType = withNewContent ? 'new' : 'existing';
|
|
128
177
|
console.log(`>>>>>> Content type: ${contentType}`);
|
|
129
|
-
let result;
|
|
130
178
|
const timeLimit = 30;
|
|
131
179
|
const typeContent = contentType === 'existing' ? await page.content() : await page.url();
|
|
132
180
|
try {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
181
|
+
const actReport = await doTest(typeContent, withItems, timeLimit, rules);
|
|
182
|
+
const {data, result} = actReport;
|
|
183
|
+
if (data && data.prevented) {
|
|
184
|
+
const message = `ERROR: Act failed or timed out at ${timeLimit} seconds`;
|
|
185
|
+
console.log(message);
|
|
186
|
+
data.error = data.error ? `${data.error}; ${message}` : message;
|
|
187
|
+
return {
|
|
188
|
+
data,
|
|
189
|
+
result: {}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
return {
|
|
194
|
+
data,
|
|
195
|
+
result
|
|
196
|
+
};
|
|
136
197
|
}
|
|
137
198
|
}
|
|
138
199
|
catch(error) {
|
|
139
|
-
|
|
140
|
-
console.log(
|
|
200
|
+
const message = `ERROR: Act crashed (${error.message.slice(0, 200)})`;
|
|
201
|
+
console.log(message);
|
|
202
|
+
return {
|
|
203
|
+
data: {
|
|
204
|
+
prevented: true,
|
|
205
|
+
error: message
|
|
206
|
+
},
|
|
207
|
+
result: {}
|
|
208
|
+
};
|
|
141
209
|
}
|
|
142
|
-
// Return the result. Execution of close() crashed the Node process.
|
|
143
|
-
return {result};
|
|
144
210
|
};
|