testaro 45.0.2 → 45.0.4
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/package.json +1 -1
- package/procs/identify.js +13 -3
- package/procs/job.js +7 -10
- package/run.js +2 -2
- package/tests/aslint.js +54 -30
- package/tests/wave.js +4 -2
package/package.json
CHANGED
package/procs/identify.js
CHANGED
|
@@ -83,6 +83,15 @@ const addIDs = async (locators, recipient) => {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
|
+
// Sanitizes a tag name.
|
|
87
|
+
const tagify = tagName => {
|
|
88
|
+
const lcTagName = tagName.toLowerCase();
|
|
89
|
+
const safeTagName = lcTagName.replace(/[^a-z0-9]/g, '');
|
|
90
|
+
if (safeTagName !== lcTagName) {
|
|
91
|
+
console.log(`ERROR: Tag name ${tagName} invalid`);
|
|
92
|
+
}
|
|
93
|
+
return safeTagName;
|
|
94
|
+
};
|
|
86
95
|
// Returns the XPath and box ID of the element of a standard instance.
|
|
87
96
|
exports.identify = async (instance, page) => {
|
|
88
97
|
// If the instance does not yet have both boxID and pathID properties:
|
|
@@ -92,7 +101,8 @@ exports.identify = async (instance, page) => {
|
|
|
92
101
|
boxID: '',
|
|
93
102
|
pathID: ''
|
|
94
103
|
};
|
|
95
|
-
const {excerpt, id, location
|
|
104
|
+
const {excerpt, id, location} = instance;
|
|
105
|
+
const tagName = tagify(instance.tagName);
|
|
96
106
|
const {type, spec} = location;
|
|
97
107
|
// If the instance specifies a CSS selector or XPath location:
|
|
98
108
|
if (['selector', 'xpath'].includes(type)) {
|
|
@@ -156,14 +166,14 @@ exports.identify = async (instance, page) => {
|
|
|
156
166
|
// If either ID remains undefined and the instance specifies a tag name:
|
|
157
167
|
if (tagName && ! (elementID.boxID && elementID.pathID)) {
|
|
158
168
|
// Get locators for elements with the tag name.
|
|
159
|
-
let locators = page.locator(tagName
|
|
169
|
+
let locators = page.locator(tagName);
|
|
160
170
|
// If there is exactly 1 of them:
|
|
161
171
|
let locatorCount = await locators.count();
|
|
162
172
|
if (locatorCount === 1) {
|
|
163
173
|
// Add a box ID and a path ID to the result.
|
|
164
174
|
await addIDs(locators, elementID);
|
|
165
175
|
}
|
|
166
|
-
// If either ID remains undefined
|
|
176
|
+
// If either ID remains undefined and the instance also specifies an excerpt:
|
|
167
177
|
if (excerpt && ! (elementID.boxID && elementID.pathID)) {
|
|
168
178
|
// Get the plain text parts of the excerpt, converting ... to an empty string.
|
|
169
179
|
const minTagExcerpt = excerpt.replace(/<[^>]+>/g, '<>');
|
package/procs/job.js
CHANGED
|
@@ -266,23 +266,20 @@ exports.isValidJob = job => {
|
|
|
266
266
|
};
|
|
267
267
|
// Executes an asynchronous function with a time limit.
|
|
268
268
|
exports.doBy = async function(timeLimit, obj, fnName, fnArgs, noticePrefix) {
|
|
269
|
-
let timer;
|
|
269
|
+
let timer, fnResolver;
|
|
270
|
+
// Start the function execution.
|
|
271
|
+
const fnPromise = new Promise(async function(resolve) {
|
|
272
|
+
fnResolver = resolve;
|
|
273
|
+
resolve(await obj[fnName](... fnArgs));
|
|
274
|
+
});
|
|
270
275
|
// Start a timer.
|
|
271
276
|
const timerPromise = new Promise(resolve => {
|
|
272
277
|
timer = setTimeout(() => {
|
|
273
278
|
console.log(`ERROR: ${noticePrefix} timed out at ${timeLimit} seconds`);
|
|
279
|
+
setTimeout(() => {fnResolver('aborted')}, 100);
|
|
274
280
|
resolve('timedOut');
|
|
275
281
|
}, 1000 * timeLimit);
|
|
276
282
|
});
|
|
277
|
-
// Start the function execution.
|
|
278
|
-
/*
|
|
279
|
-
const fnPromise = new Promise(async resolve => {
|
|
280
|
-
resolve(await fn(... fnArgs));
|
|
281
|
-
});
|
|
282
|
-
*/
|
|
283
|
-
const fnPromise = new Promise(async function(resolve) {
|
|
284
|
-
resolve(await obj[fnName](... fnArgs));
|
|
285
|
-
});
|
|
286
283
|
// Get the timeout or the value returned by the function, whichever is first.
|
|
287
284
|
const result = await Promise.race([timerPromise, fnPromise]);
|
|
288
285
|
clearTimeout(timer);
|
package/run.js
CHANGED
|
@@ -812,8 +812,8 @@ const doActs = async (report, actIndex, page) => {
|
|
|
812
812
|
// Get the start time of the act.
|
|
813
813
|
const startTime = Date.now();
|
|
814
814
|
try {
|
|
815
|
-
// Get the time limit in
|
|
816
|
-
const timeLimit =
|
|
815
|
+
// Get the time limit in seconds for the act.
|
|
816
|
+
const timeLimit = timeLimits[act.which] || 15;
|
|
817
817
|
// Perform the specified tests of the tool.
|
|
818
818
|
const actReport = await require(`./tests/${act.which}`)
|
|
819
819
|
.reporter(page, report, actIndex, timeLimit);
|
package/tests/aslint.js
CHANGED
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
// Module to handle files.
|
|
31
31
|
const fs = require('fs/promises');
|
|
32
|
+
// Utility module.
|
|
33
|
+
const {doBy} = require('../procs/job');
|
|
32
34
|
|
|
33
35
|
// FUNCTIONS
|
|
34
36
|
|
|
@@ -46,7 +48,7 @@ exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
|
46
48
|
const act = report.acts[actIndex];
|
|
47
49
|
const {jobData} = report;
|
|
48
50
|
const scriptNonce = jobData && jobData.lastScriptNonce;
|
|
49
|
-
// Inject the ASLint bundle and runner into the page.
|
|
51
|
+
// Inject the ASLint bundle and runner into the head of the page.
|
|
50
52
|
await page.evaluate(args => {
|
|
51
53
|
const {scriptNonce, aslintBundle, aslintRunner} = args;
|
|
52
54
|
// Bundle.
|
|
@@ -76,38 +78,60 @@ exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
|
76
78
|
const reportLoc = page.locator('#aslintResult');
|
|
77
79
|
// If the injection succeeded:
|
|
78
80
|
if (! data.prevented) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
console.log(`
|
|
81
|
+
try {
|
|
82
|
+
// Wait for the test results to be attached to the page.
|
|
83
|
+
const waitOptions = {
|
|
84
|
+
state: 'attached',
|
|
85
|
+
timeout: 1000 * timeLimit
|
|
86
|
+
};
|
|
87
|
+
await reportLoc.waitFor(waitOptions);
|
|
88
|
+
// const timeResult = await doBy(timeLimit, reportLoc, 'waitFor', [waitArg], 'aslint testing');
|
|
89
|
+
// console.log(`timeResult type is ${typeof timeResult}`);
|
|
90
|
+
// If the result attachment timed out:
|
|
91
|
+
/*
|
|
92
|
+
if (timeResult === 'timedOut') {
|
|
93
|
+
// Report this.
|
|
94
|
+
data.prevented = true;
|
|
95
|
+
data.error = 'Attachment of results to page by aslint timed out';
|
|
96
|
+
await page.close({runBeforeUnload: true});
|
|
97
|
+
}
|
|
98
|
+
*/
|
|
99
|
+
}
|
|
100
|
+
catch(error) {
|
|
101
|
+
const message = 'Attachment of test results to page failed';
|
|
102
|
+
console.log(message);
|
|
88
103
|
data.prevented = true;
|
|
89
|
-
data.error = message
|
|
90
|
-
}
|
|
104
|
+
data.error = `${message} (${error.message})`;
|
|
105
|
+
}
|
|
91
106
|
}
|
|
92
|
-
// If the
|
|
107
|
+
// If the injection and the result attachment both succeeded:
|
|
93
108
|
if (! data.prevented) {
|
|
94
|
-
// Get
|
|
95
|
-
const actReport = await reportLoc
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
// Get their text.
|
|
110
|
+
const actReport = await doBy(timeLimit, reportLoc, 'textContent', [], 'aslint report retrieval');
|
|
111
|
+
// If the text was obtained in time:
|
|
112
|
+
if (actReport !== 'timedOut') {
|
|
113
|
+
// Populate the act report.
|
|
114
|
+
result = JSON.parse(actReport);
|
|
115
|
+
// If any rules were reported violated:
|
|
116
|
+
if (result.rules) {
|
|
117
|
+
// For each such rule:
|
|
118
|
+
Object.keys(result.rules).forEach(ruleID => {
|
|
119
|
+
// If the rule was passed or skipped or rules to be tested were specified and exclude it:
|
|
120
|
+
const excluded = act.rules && ! act.rules.includes(ruleID);
|
|
121
|
+
const instanceType = result.rules[ruleID].status.type;
|
|
122
|
+
// If rules to be tested were specified and exclude it or the rule was passed or skipped:
|
|
123
|
+
if (excluded || ['passed', 'skipped'].includes(instanceType)) {
|
|
124
|
+
// Delete the rule report.
|
|
125
|
+
delete result.rules[ruleID];
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Otherwise, i.e. if the text was not obtained in time:
|
|
131
|
+
else {
|
|
132
|
+
// Report this.
|
|
133
|
+
data.prevented = true;
|
|
134
|
+
data.error = 'Retrieval of result text timed out';
|
|
111
135
|
}
|
|
112
136
|
}
|
|
113
137
|
// Return the act report.
|
package/tests/wave.js
CHANGED
|
@@ -41,9 +41,10 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
41
41
|
const waveKey = process.env.WAVE_KEY;
|
|
42
42
|
// Initialize the results.
|
|
43
43
|
const data = {};
|
|
44
|
-
|
|
44
|
+
let result = {};
|
|
45
45
|
try {
|
|
46
46
|
result = await new Promise(resolve => {
|
|
47
|
+
// Get the test results.
|
|
47
48
|
https.get(
|
|
48
49
|
{
|
|
49
50
|
host: 'wave.webaim.org',
|
|
@@ -54,7 +55,7 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
54
55
|
response.on('data', chunk => {
|
|
55
56
|
rawReport += chunk;
|
|
56
57
|
});
|
|
57
|
-
// When
|
|
58
|
+
// When they arrive:
|
|
58
59
|
response.on('end', async () => {
|
|
59
60
|
// Delete unnecessary properties.
|
|
60
61
|
const actResult = JSON.parse(rawReport);
|
|
@@ -114,6 +115,7 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
114
115
|
});
|
|
115
116
|
}
|
|
116
117
|
catch (error) {
|
|
118
|
+
console.log(`ERROR: ${error.message}`);
|
|
117
119
|
data.prevented = true;
|
|
118
120
|
data.error = error.message;
|
|
119
121
|
};
|