testaro 9.0.2 → 10.1.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/README.md +8 -3
- package/actSpecs.js +6 -0
- package/call.js +2 -2
- package/package.json +1 -1
- package/tests/alfa.js +8 -3
- package/watch.js +61 -48
package/README.md
CHANGED
|
@@ -591,14 +591,15 @@ The arguments passed to `cycle` by a module or to `watch` by a user are:
|
|
|
591
591
|
- whether to watch a directory (`true`) or the network (`false`)
|
|
592
592
|
- whether to continue watching indefinitely after the first report (`true` or `false`)
|
|
593
593
|
- how many seconds to wait after finding no job before checking again (a nonnegative number)
|
|
594
|
+
- optionally, where the watched jobs are located
|
|
594
595
|
|
|
595
596
|
##### Directory watch
|
|
596
597
|
|
|
597
|
-
With directory watch, Testaro checks whether the `todo` subdirectory of the job directory
|
|
598
|
+
With directory watch, Testaro checks whether the `todo` subdirectory of the job directory contains a job. The job directory is given by the fourth passed argument, if present, or, if not, then by `process.env.JOBDIR`.
|
|
598
599
|
|
|
599
|
-
When Testaro finds one or more jobs to do, the `watch` module runs the first job, saves the report in the `raw` subdirectory of the `process.env.REPORTDIR
|
|
600
|
+
When Testaro finds one or more jobs to do, the `watch` module runs the first job, saves the report in the `raw` subdirectory of the report directory. The report directory is given by `process.env.REPORTDIR`. Testaro also moves the job file from the `todo` subdirectory to the `done` subdirectory of the job directory.
|
|
600
601
|
|
|
601
|
-
Since Testaro runs the first job (i.e. the job whose file name is first in ASCII order), whoever populates the `todo` subdirectory of the
|
|
602
|
+
Since Testaro runs the first job (i.e. the job whose file name is first in ASCII order), whoever populates the `todo` subdirectory of the job directory with job files has control over the order in which Testaro runs them. For example, to force a new job to be run before the already waiting jobs, one can give it a filename that comes before that of the first waiting job.
|
|
602
603
|
|
|
603
604
|
##### Network watch
|
|
604
605
|
|
|
@@ -610,6 +611,10 @@ With network watch, the initiator of an interaction is Testaro, not the server.
|
|
|
610
611
|
|
|
611
612
|
If multiple workstations run Testaro and do work for the same server, the server can assign jobs to specific agents by requiring each instance of Testaro to have a distinct value of `process.env.AGENT`.
|
|
612
613
|
|
|
614
|
+
The URL from which Testaro requests jobs is given by the fourth passed argument, if present, or, if not, then by `process.env.JOB_URL`.
|
|
615
|
+
|
|
616
|
+
The URL to which Testaro sends reports is given by the `sources.sendReportTo` property of each job, if the property exists, or, if not, by `process.env.REPORT_URL`.
|
|
617
|
+
|
|
613
618
|
### Environment variables
|
|
614
619
|
|
|
615
620
|
In addition to their uses described above, environment variables can be used by commands of type `text`, as documented in the `commands.js` file.
|
package/actSpecs.js
CHANGED
package/call.js
CHANGED
|
@@ -57,11 +57,11 @@ const callRun = async jobIDStart => {
|
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
59
|
// Starts a watch.
|
|
60
|
-
const callWatch = async (isDirWatch, isForever, interval) => {
|
|
60
|
+
const callWatch = async (isDirWatch, isForever, interval, watchee = null) => {
|
|
61
61
|
const whenType = isForever === 'true' ? 'repeating' : 'one-time';
|
|
62
62
|
const whereType = isDirWatch === 'true' ? 'directory' : 'network';
|
|
63
63
|
console.log(`Starting ${whenType} ${whereType} watch`);
|
|
64
|
-
await cycle(isDirWatch === 'true', isForever === 'true', Number.parseInt(interval, 10));
|
|
64
|
+
await cycle(isDirWatch === 'true', isForever === 'true', Number.parseInt(interval, 10), watchee);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
// ########## OPERATION
|
package/package.json
CHANGED
package/tests/alfa.js
CHANGED
|
@@ -7,12 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
const {Audit} = require('@siteimprove/alfa-act');
|
|
9
9
|
const {Scraper} = require('@siteimprove/alfa-scraper');
|
|
10
|
-
|
|
10
|
+
let alfaRules = require('@siteimprove/alfa-rules').default;
|
|
11
11
|
|
|
12
12
|
// FUNCTIONS
|
|
13
13
|
|
|
14
14
|
// Conducts and reports an alfa test.
|
|
15
|
-
exports.reporter = async page => {
|
|
15
|
+
exports.reporter = async (page, rules) => {
|
|
16
|
+
// If only some rules are to be employed:
|
|
17
|
+
if (rules && rules.length) {
|
|
18
|
+
// Remove the other rules.
|
|
19
|
+
alfaRules = alfaRules.filter(rule => rules.includes(rule.uri.replace(/^.+-/, '')));
|
|
20
|
+
}
|
|
16
21
|
// Get the document containing the summaries of the alfa rules.
|
|
17
22
|
const context = page.context();
|
|
18
23
|
const rulePage = await context.newPage();
|
|
@@ -53,7 +58,7 @@ exports.reporter = async page => {
|
|
|
53
58
|
};
|
|
54
59
|
await Scraper.with(async scraper => {
|
|
55
60
|
for (const input of await scraper.scrape(page.url())) {
|
|
56
|
-
const audit = Audit.of(input, alfaRules
|
|
61
|
+
const audit = Audit.of(input, alfaRules);
|
|
57
62
|
const outcomes = Array.from(await audit.evaluate());
|
|
58
63
|
outcomes.forEach((outcome, index) => {
|
|
59
64
|
const {target} = outcome;
|
package/watch.js
CHANGED
|
@@ -25,13 +25,13 @@ const reportDir = process.env.REPORTDIR;
|
|
|
25
25
|
// ########## FUNCTIONS
|
|
26
26
|
|
|
27
27
|
// Checks for a directory job.
|
|
28
|
-
const checkDirJob = async
|
|
28
|
+
const checkDirJob = async watchee => {
|
|
29
29
|
try {
|
|
30
|
-
const
|
|
30
|
+
const watchJobDir = watchee || jobDir;
|
|
31
|
+
const toDoDirFileNames = await fs.readdir(`${watchJobDir}/todo`);
|
|
31
32
|
const jobFileNames = toDoDirFileNames.filter(fileName => fileName.endsWith('.json'));
|
|
32
33
|
if (jobFileNames.length) {
|
|
33
|
-
|
|
34
|
-
const jobJSON = await fs.readFile(`${jobDir}/todo/${jobFileNames[0]}`, 'utf8');
|
|
34
|
+
const jobJSON = await fs.readFile(`${watchJobDir}/todo/${jobFileNames[0]}`, 'utf8');
|
|
35
35
|
try {
|
|
36
36
|
const job = JSON.parse(jobJSON, null, 2);
|
|
37
37
|
return job;
|
|
@@ -44,7 +44,7 @@ const checkDirJob = async () => {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
|
-
console.log('
|
|
47
|
+
console.log('No job to do');
|
|
48
48
|
return {};
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -52,10 +52,11 @@ const checkDirJob = async () => {
|
|
|
52
52
|
return {};
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
// Checks for a network job.
|
|
56
|
-
const checkNetJob = async
|
|
55
|
+
// Checks for and returns a network job.
|
|
56
|
+
const checkNetJob = async watchee => {
|
|
57
|
+
const watchJobURL = watchee || jobURL;
|
|
57
58
|
const job = await new Promise(resolve => {
|
|
58
|
-
const wholeURL = `${protocol}://${
|
|
59
|
+
const wholeURL = `${protocol}://${watchJobURL}?agent=${agent}`;
|
|
59
60
|
const request = client.request(wholeURL, response => {
|
|
60
61
|
const chunks = [];
|
|
61
62
|
response.on('data', chunk => {
|
|
@@ -83,7 +84,9 @@ const checkNetJob = async () => {
|
|
|
83
84
|
});
|
|
84
85
|
request.end();
|
|
85
86
|
});
|
|
86
|
-
|
|
87
|
+
if (job.id) {
|
|
88
|
+
console.log(`Network job ${job.id} received`);
|
|
89
|
+
}
|
|
87
90
|
return job;
|
|
88
91
|
};
|
|
89
92
|
// Writes a directory report.
|
|
@@ -108,48 +111,57 @@ const writeDirReport = async report => {
|
|
|
108
111
|
// Submits a network report to a server and returns the server response.
|
|
109
112
|
const writeNetReport = async report => {
|
|
110
113
|
const ack = await new Promise(resolve => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
114
|
+
if (report.sources) {
|
|
115
|
+
// Get the report destination from the report or the environment.
|
|
116
|
+
const destination = report.sources.sendReportTo;
|
|
117
|
+
const wholeURL = destination || `${process.env.PROTOCOL}://${reportURL}`;
|
|
118
|
+
// Contact the server.
|
|
119
|
+
const request = client.request(wholeURL, {method: 'POST'}, response => {
|
|
120
|
+
const chunks = [];
|
|
121
|
+
response.on('data', chunk => {
|
|
122
|
+
chunks.push(chunk);
|
|
123
|
+
});
|
|
124
|
+
response.on('end', () => {
|
|
125
|
+
const content = chunks.join('');
|
|
126
|
+
try {
|
|
127
|
+
resolve(JSON.parse(content));
|
|
128
|
+
}
|
|
129
|
+
catch(error) {
|
|
130
|
+
resolve({
|
|
131
|
+
error: 'ERROR: Response was not JSON',
|
|
132
|
+
message: error.message,
|
|
133
|
+
status: response.statusCode,
|
|
134
|
+
content: content.slice(0, 200)
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
130
138
|
});
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
report.jobData.agent = agent;
|
|
140
|
+
request.on('error', error => {
|
|
141
|
+
console.log(`ERROR submitting job report (${error.message})`);
|
|
142
|
+
resolve({
|
|
143
|
+
error: 'ERROR: Job report submission failed',
|
|
144
|
+
message: error.message
|
|
145
|
+
});
|
|
138
146
|
});
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
147
|
+
// Send the report to the server.
|
|
148
|
+
request.write(JSON.stringify(report, null, 2));
|
|
149
|
+
request.end();
|
|
150
|
+
console.log(`Report ${report.id} submitted`);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.log('ERROR: Report has no sources property');
|
|
154
|
+
}
|
|
144
155
|
});
|
|
145
156
|
// Return the server response.
|
|
146
157
|
return ack;
|
|
147
158
|
};
|
|
148
159
|
// Archives a job.
|
|
149
|
-
const archiveJob = async job => {
|
|
160
|
+
const archiveJob = async (job, watchee) => {
|
|
150
161
|
const jobJSON = JSON.stringify(job, null, 2);
|
|
151
|
-
|
|
152
|
-
await fs.
|
|
162
|
+
const watchJobDir = watchee || jobDir;
|
|
163
|
+
await fs.writeFile(`${watchJobDir}/done/${job.id}.json`, jobJSON);
|
|
164
|
+
await fs.rm(`${watchJobDir}/todo/${job.id}.json`);
|
|
153
165
|
};
|
|
154
166
|
// Waits.
|
|
155
167
|
const wait = ms => {
|
|
@@ -194,7 +206,7 @@ const runJob = async (job, isDirWatch) => {
|
|
|
194
206
|
}
|
|
195
207
|
};
|
|
196
208
|
// Checks for a job, performs it, and submits a report, once or repeatedly.
|
|
197
|
-
exports.cycle = async (isDirWatch, isForever, interval) => {
|
|
209
|
+
exports.cycle = async (isDirWatch, isForever, interval, watchee = null) => {
|
|
198
210
|
const intervalMS = 1000 * Number.parseInt(interval);
|
|
199
211
|
let statusOK = true;
|
|
200
212
|
// Prevent a wait before the first iteration.
|
|
@@ -207,21 +219,21 @@ exports.cycle = async (isDirWatch, isForever, interval) => {
|
|
|
207
219
|
// Check for a job.
|
|
208
220
|
let job;
|
|
209
221
|
if (isDirWatch) {
|
|
210
|
-
job = await checkDirJob();
|
|
222
|
+
job = await checkDirJob(watchee);
|
|
211
223
|
}
|
|
212
224
|
else {
|
|
213
|
-
job = await checkNetJob();
|
|
225
|
+
job = await checkNetJob(watchee);
|
|
214
226
|
}
|
|
215
227
|
// If there was one:
|
|
216
228
|
if (job.id) {
|
|
217
|
-
// Run it
|
|
229
|
+
// Run it, save a report, and if applicable send the report to the job source.
|
|
218
230
|
console.log(`Running job ${job.id}`);
|
|
219
231
|
await runJob(JSON.parse(JSON.stringify(job)), isDirWatch);
|
|
220
232
|
console.log(`Job ${job.id} finished`);
|
|
221
233
|
// If a directory was watched:
|
|
222
234
|
if (isDirWatch) {
|
|
223
235
|
// Archive the job.
|
|
224
|
-
await archiveJob(job);
|
|
236
|
+
await archiveJob(job, watchee);
|
|
225
237
|
console.log(`Job ${job.id} archived`);
|
|
226
238
|
}
|
|
227
239
|
// If watching was specified for only 1 job, quit.
|
|
@@ -231,6 +243,7 @@ exports.cycle = async (isDirWatch, isForever, interval) => {
|
|
|
231
243
|
}
|
|
232
244
|
// Otherwise, i.e. if no job was found:
|
|
233
245
|
else {
|
|
246
|
+
console.log('No job to do');
|
|
234
247
|
// Cause a wait before the next check.
|
|
235
248
|
empty = true;
|
|
236
249
|
}
|