testaro 47.2.1 → 48.0.2
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/README.md +8 -8
- package/call.js +1 -1
- package/dirWatch.js +5 -7
- package/netWatch.js +1 -1
- package/package.json +1 -1
- package/procs/doTestAct.js +121 -0
- package/run.js +712 -724
- package/tests/alfa.js +3 -6
- package/tests/ibm.js +10 -5
- package/validation/executors/run.js +2 -2
- package/validation/validateTest.js +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,9 @@ The purposes of Testaro are to:
|
|
|
10
10
|
- provide programmatic access to accessibility tests defined by several tools
|
|
11
11
|
- facilitate the integration of the reports of the tools into a unified report
|
|
12
12
|
|
|
13
|
-
Testaro is described in
|
|
13
|
+
Testaro is described in two papers:
|
|
14
|
+
- [How to run a thousand accessibility tests](https://medium.com/cvs-health-tech-blog/how-to-run-a-thousand-accessibility-tests-63692ad120c3)
|
|
15
|
+
- [Testaro: Efficient Ensemble Testing for Web Accessibility](https://arxiv.org/abs/2309.10167)
|
|
14
16
|
|
|
15
17
|
The need for multi-tool integration, and its costs, are discussed in [Accessibility Metatesting: Comparing Nine Testing Tools](https://arxiv.org/abs/2304.07591).
|
|
16
18
|
|
|
@@ -729,13 +731,11 @@ A job can be immediately executed as follows:
|
|
|
729
731
|
|
|
730
732
|
```javascript
|
|
731
733
|
const {doJob} = require('./run');
|
|
732
|
-
doJob(
|
|
733
|
-
.then(
|
|
734
|
+
doJob(job)
|
|
735
|
+
.then(report => …);
|
|
734
736
|
```
|
|
735
737
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
Testaro will run the job and modify the `report` object. When Testaro finishes, the `acts` and `jobData` properties of `report` will contain the results. The final statement can further process the `report` object as desired in the `then` callback.
|
|
738
|
+
Testaro will run the job and return a modified `report` object. When Testaro finishes, the `acts` and `jobData` properties of `report` will contain the results. The final statement can further process the `report` object as desired in the `then` callback.
|
|
739
739
|
|
|
740
740
|
The Testilo package contains functions that can create jobs from scripts and add scores and explanations to reports.
|
|
741
741
|
|
|
@@ -865,7 +865,7 @@ The rationales motivating the Testaro-defined tests can be found in comments wit
|
|
|
865
865
|
|
|
866
866
|
On some occasions a test throws an error that cannot be handled with a `try`-`catch` structure. It has been observed, for example, that the `ibm` test does this when the page content, rather than the page URL, is given to `getCompliance()` and the target is `https://globalsolutions.org`, `https://monsido.com`, or `https://www.ambetterhealth.com/`.
|
|
867
867
|
|
|
868
|
-
Some tools take apparently infinite time to perform their tests on some pages. To handle such stalling, Testaro subjects
|
|
868
|
+
Some tools take apparently infinite time to perform their tests on some pages. To handle such stalling, Testaro subjects all tools to time limits. The limitation is implemented with forked child processes. Specifically, the `procs/doTestAct.js` module is run as a forked process with a `timeout` option for each of the 11 tools.
|
|
869
869
|
|
|
870
870
|
### Activation
|
|
871
871
|
|
|
@@ -902,7 +902,7 @@ Testaro would become more reliable if the behavior of its tools were monitored f
|
|
|
902
902
|
|
|
903
903
|
## Repository exclusions
|
|
904
904
|
|
|
905
|
-
The files in the `temp` directory are presumed ephemeral and are not tracked by `git`.
|
|
905
|
+
The files in the `temp` directory are presumed ephemeral and are not tracked by `git`. The above-mentioned `procs/doTestAct.js` module stores temporary reports in that directory.
|
|
906
906
|
|
|
907
907
|
## Related packages
|
|
908
908
|
|
package/call.js
CHANGED
|
@@ -75,7 +75,7 @@ const callRun = async jobIDStart => {
|
|
|
75
75
|
report.observe = false;
|
|
76
76
|
report.sendReportTo = '';
|
|
77
77
|
// Run it.
|
|
78
|
-
await doJob(report);
|
|
78
|
+
report = await doJob(report);
|
|
79
79
|
// Archive it.
|
|
80
80
|
await fs.rename(`${todoDir}/${jobFileName}`, `${jobDir}/done/${jobFileName}`);
|
|
81
81
|
// Save the report.
|
package/dirWatch.js
CHANGED
|
@@ -45,8 +45,6 @@ const reportDir = process.env.REPORTDIR;
|
|
|
45
45
|
|
|
46
46
|
// ########## FUNCTIONS
|
|
47
47
|
|
|
48
|
-
// Gets a segment of a timestamp.
|
|
49
|
-
const tsPart = (timeStamp, startIndex) => timeStamp.slice(startIndex, startIndex + 2);
|
|
50
48
|
// Returns a string representing the date and time.
|
|
51
49
|
const nowString = () => (new Date()).toISOString().slice(2, 16);
|
|
52
50
|
// Writes a directory report.
|
|
@@ -115,7 +113,7 @@ exports.dirWatch = async (isForever, intervalInSeconds) => {
|
|
|
115
113
|
const jobJSON = await fs.readFile(`${jobDir}/todo/${jobFileNames[0]}`, 'utf8');
|
|
116
114
|
try {
|
|
117
115
|
const job = JSON.parse(jobJSON);
|
|
118
|
-
|
|
116
|
+
let report = JSON.parse(jobJSON);
|
|
119
117
|
// Ensure it has no server properties.
|
|
120
118
|
job.observe = false;
|
|
121
119
|
job.sendReportTo = '';
|
|
@@ -123,12 +121,12 @@ exports.dirWatch = async (isForever, intervalInSeconds) => {
|
|
|
123
121
|
report.sendReportTo = '';
|
|
124
122
|
const {id} = job;
|
|
125
123
|
console.log(`\n\nDirectory job ${id} ready to do (${nowString()})`);
|
|
126
|
-
// Perform it.
|
|
127
|
-
await doJob(report);
|
|
124
|
+
// Perform it, adding to the report.
|
|
125
|
+
report = await doJob(report);
|
|
128
126
|
console.log(`Job ${id} finished (${nowString()})`);
|
|
129
|
-
//
|
|
127
|
+
// Save the report.
|
|
130
128
|
await writeDirReport(report);
|
|
131
|
-
// Archive
|
|
129
|
+
// Archive the job.
|
|
132
130
|
await archiveJob(job, true);
|
|
133
131
|
}
|
|
134
132
|
catch(error) {
|
package/netWatch.js
CHANGED
|
@@ -164,7 +164,7 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
|
|
|
164
164
|
// Perform the job, adding result data to it.
|
|
165
165
|
console.log(`${logStart}job ${id} (${nowString()})`);
|
|
166
166
|
console.log(`>> It will send report to ${sendReportTo}`);
|
|
167
|
-
await doJob(contentObj);
|
|
167
|
+
contentObj = await doJob(contentObj);
|
|
168
168
|
let reportJSON = JSON.stringify(contentObj, null, 2);
|
|
169
169
|
console.log(`Job ${id} finished (${nowString()})`);
|
|
170
170
|
// Send the report to the specified server.
|
package/package.json
CHANGED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
|
|
4
|
+
MIT License
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
doTestAct
|
|
27
|
+
Performs the tests of an act.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// IMPORTS
|
|
31
|
+
|
|
32
|
+
// Module to perform file operations.
|
|
33
|
+
const fs = require('fs/promises');
|
|
34
|
+
const {launch} = require(`${__dirname}/../run`);
|
|
35
|
+
|
|
36
|
+
// CONSTANTS
|
|
37
|
+
|
|
38
|
+
// Set DEBUG environment variable to 'true' to add debugging features.
|
|
39
|
+
const debug = process.env.DEBUG === 'true';
|
|
40
|
+
// Set WAITS environment variable to a positive number to insert delays (in ms).
|
|
41
|
+
const waits = Number.parseInt(process.env.WAITS) || 0;
|
|
42
|
+
|
|
43
|
+
// VARIABLES
|
|
44
|
+
|
|
45
|
+
const actIndex = Number.parseInt(process.argv[2]);
|
|
46
|
+
|
|
47
|
+
const doTestAct = async () => {
|
|
48
|
+
const reportPath = `${__dirname}/../temp/report.json`;
|
|
49
|
+
// Get the saved report.
|
|
50
|
+
const reportJSON = await fs.readFile(reportPath, 'utf8');
|
|
51
|
+
const report = JSON.parse(reportJSON);
|
|
52
|
+
// Get the act.
|
|
53
|
+
const act = report.acts[actIndex];
|
|
54
|
+
// Get the tool name.
|
|
55
|
+
const {which} = act;
|
|
56
|
+
// Launch a browser, navigate to the URL, and redefine the page of the run module.
|
|
57
|
+
await launch(
|
|
58
|
+
report,
|
|
59
|
+
debug,
|
|
60
|
+
waits,
|
|
61
|
+
act.launch.browserID || report.browserID,
|
|
62
|
+
act.launch.target && act.launch.target.url || report.target.url
|
|
63
|
+
);
|
|
64
|
+
// If the launch aborted the job:
|
|
65
|
+
if (report.jobData && report.jobData.aborted) {
|
|
66
|
+
// Save the revised report.
|
|
67
|
+
const reportJSON = JSON.stringify(report);
|
|
68
|
+
await fs.writeFile(reportPath, reportJSON);
|
|
69
|
+
// Report this.
|
|
70
|
+
process.send('ERROR: Job aborted');
|
|
71
|
+
}
|
|
72
|
+
// Otherwise, i.e. if the launch did not abort the job:
|
|
73
|
+
else {
|
|
74
|
+
// Get the redefined page.
|
|
75
|
+
const {page} = require('../run');
|
|
76
|
+
// If it exists:
|
|
77
|
+
if (page) {
|
|
78
|
+
try {
|
|
79
|
+
// If the page prevents the tool from testing:
|
|
80
|
+
if (page.prevented) {
|
|
81
|
+
// Report this.
|
|
82
|
+
process.send('ERROR: Page prevented testing');
|
|
83
|
+
}
|
|
84
|
+
// Otherwise, i.e. if the page permits testing:
|
|
85
|
+
else {
|
|
86
|
+
// Wait for the act reporter to perform the specified tests of the tool.
|
|
87
|
+
const actReport = await require(`../tests/${which}`).reporter(page, report, actIndex, 65);
|
|
88
|
+
// Add the data and result to the act.
|
|
89
|
+
act.data = actReport.data;
|
|
90
|
+
act.result = actReport.result;
|
|
91
|
+
// If the tool reported that the page prevented testing:
|
|
92
|
+
if (actReport.data && actReport.data.prevented) {
|
|
93
|
+
// Add prevention data to the job data.
|
|
94
|
+
report.jobData.preventions[which] = act.data.error;
|
|
95
|
+
}
|
|
96
|
+
const reportJSON = JSON.stringify(report);
|
|
97
|
+
// Save the revised report.
|
|
98
|
+
await fs.writeFile(reportPath, reportJSON);
|
|
99
|
+
// Send a completion message.
|
|
100
|
+
process.send('Act completed');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// If the tool invocation failed:
|
|
104
|
+
catch(error) {
|
|
105
|
+
// Save the revised report.
|
|
106
|
+
const reportJSON = JSON.stringify(report);
|
|
107
|
+
await fs.writeFile(reportPath, reportJSON);
|
|
108
|
+
// Report the failure.
|
|
109
|
+
const message = error.message.slice(0, 400);
|
|
110
|
+
console.log(`ERROR: Test act ${act.which} failed (${message})`);
|
|
111
|
+
process.send('ERROR performing the act');
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// Otherwise, i.e. if the page does not exist:
|
|
115
|
+
else {
|
|
116
|
+
process.send('ERROR: No page');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
doTestAct();
|