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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "45.0.2",
3
+ "version": "45.0.4",
4
4
  "description": "Run 1000 web accessibility tests from 10 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
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, tagName} = instance;
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.toLowerCase());
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 an the instance also specifies an excerpt:
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 milliseconds for the act.
816
- const timeLimit = 1000 * timeLimits[act.which] || 15000;
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
- // Get the test results.
80
- await reportLoc.waitFor({
81
- state: 'attached',
82
- timeout: 1000 * timeLimit
83
- })
84
- .catch(error => {
85
- const message
86
- = `aslint testing timed out at ${timeLimit} seconds (${error.message.slice(0, 400)})`;
87
- console.log(`ERROR: ${message}`);
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 results arrived in time:
107
+ // If the injection and the result attachment both succeeded:
93
108
  if (! data.prevented) {
94
- // Get them.
95
- const actReport = await reportLoc.textContent();
96
- // Populate the act report.
97
- result = JSON.parse(actReport);
98
- // If any rules were reported violated:
99
- if (result.rules) {
100
- // For each such rule:
101
- Object.keys(result.rules).forEach(ruleID => {
102
- // If the rule was passed or skipped or rules to be tested were specified and exclude it:
103
- const excluded = act.rules && ! act.rules.includes(ruleID);
104
- const instanceType = result.rules[ruleID].status.type;
105
- // If rules to be tested were specified and exclude it or the rule was passed or skipped:
106
- if (excluded || ['passed', 'skipped'].includes(instanceType)) {
107
- // Delete the rule report.
108
- delete result.rules[ruleID];
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
- const result = {};
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 the data arrive:
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
  };