testaro 69.5.0 → 69.6.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 CHANGED
@@ -132,17 +132,15 @@ REPORTDIR=../testing/reports
132
132
  # Name of this Testaro instance when it listens for jobs and sends reports to requesting hosts.
133
133
  AGENT=agentabc
134
134
  #----------------------------
135
- # When Testaro polls network hosts to ask for new jobs, data on those hosts.
136
- # URL of host 0 to poll.
137
- NETWATCH_URL_0_JOB=http://localhost:3000/api/assignJob/agentabc
138
- # URL of host 0 to which to send progress reports during jobs.
139
- NETWATCH_URL_0_OBSERVE=http://localhost:3000/api/granular/agentabc
140
- # URL of host 0 to which to send completed job reports.
141
- NETWATCH_URL_0_REPORT=http://localhost:3000/api/takeReport/agentabc
142
- # Password to give to host 0 to authenticate this instance.
143
- NETWATCH_URL_0_AUTH=abcxyz
144
- # Which network hosts to poll for jobs (comma-separated list of indices).
145
- NETWATCH_URLS=0
135
+ # When Testaro polls a network host to ask for new jobs, data on the host.
136
+ # URL to poll.
137
+ NETWATCH_JOB=http://localhost:3000/api/assignJob/agentabc
138
+ # URL to which to send progress reports during jobs.
139
+ NETWATCH_OBSERVE=http://localhost:3000/api/granular/agentabc
140
+ # URL to which to send completed job reports.
141
+ NETWATCH_REPORT=http://localhost:3000/api/takeReport/agentabc
142
+ # Password to give to the host to authenticate this instance.
143
+ NETWATCH_AUTH=abcxyz
146
144
  ```
147
145
 
148
146
  ## Jobs
package/netWatch.js CHANGED
@@ -29,10 +29,11 @@ const {nowString} = require('./procs/dateTime');
29
29
 
30
30
  // CONSTANTS
31
31
 
32
- const netWatchURLIDs = process.env.NETWATCH_URLS.split(/,/);
33
- const jobURLs = netWatchURLIDs.map(id => process.env[`NETWATCH_URL_${id}_JOB`]);
34
- const reportURLs = netWatchURLIDs.map(id => process.env[`NETWATCH_URL_${id}_REPORT`]);
35
- const auths = netWatchURLIDs.map(id => process.env[`NETWATCH_URL_${id}_AUTH`]);
32
+ const jobURL = new URL(process.env.NETWATCH_URL_JOB);
33
+ const jobHost = jobURL.host;
34
+ const reportURL = new URL(process.env.NETWATCH_URL_REPORT);
35
+ const reportHost = reportURL.host;
36
+ const agentPW = process.env.NETWATCH_URL_AUTH;
36
37
 
37
38
  // FUNCTIONS
38
39
 
@@ -44,39 +45,22 @@ const wait = ms => {
44
45
  }, ms);
45
46
  });
46
47
  };
47
- // Serves an object in JSON format.
48
- const serveObject = (object, response) => {
49
- response.setHeader('Content-Type', 'application/json; charset=utf-8');
48
+ // Ends a response with an object in JSON format.
49
+ const respondWithObject = (object, response) => {
50
+ response.setHeader('content-type', 'application/json; charset=utf-8');
50
51
  response.end(JSON.stringify(object));
51
52
  };
52
- // Removes the query if any, or otherwise the final segment, from a URL.
53
- const getURLBase = url => url.replace(/[?/][^?/.]+$/, '');
54
53
  /*
55
54
  Requests a network job and, when found, performs and reports it.
56
55
  Arguments:
57
56
  0. whether to continue watching after a job is run.
58
- 1: interval in seconds from a cycle of no-job checks to the next cycle.
57
+ 1: interval in seconds from a no-job check to the next check.
59
58
  2. whether to ignore unknown-certificate errors from watched servers.
60
59
  */
61
60
  exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) => {
62
- // If the job and report URLs exist and are all valid:
63
- if (
64
- jobURLs
65
- && jobURLs.length
66
- && reportURLs
67
- && reportURLs.length === jobURLs.length
68
- && jobURLs.every((jobURL, index) => {
69
- const allDefined = [jobURL, reportURLs[index]].every(url => url);
70
- const allSchemed = allDefined
71
- && [jobURL, reportURLs[index]]
72
- .every(url => ['http://', 'https://'].some(prefix => url.startsWith(prefix)));
73
- return allSchemed;
74
- })
75
- ) {
61
+ // If the job and report URLs exist and are valid:
62
+ if (jobURL && reportURL) {
76
63
  // Configure the watch.
77
- const urlCount = jobURLs.length;
78
- let cycleIndex = -1;
79
- let urlIndex = -1;
80
64
  let noJobYet = true;
81
65
  let abort = false;
82
66
  const certInfo = `Certificate-${isCertTolerant ? '' : 'in'}tolerant`;
@@ -87,122 +71,123 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
87
71
  );
88
72
  // As long as watching is to continue:
89
73
  while ((isForever || noJobYet) && ! abort) {
90
- // If the cycle is complete:
91
- if (cycleIndex === urlCount - 1) {
92
- // Wait for the specified interval.
93
- await wait(1000 * intervalInSeconds);
94
- // Log the start of a cycle.
95
- console.log('--');
96
- }
97
- // Otherwise, i.e. if the cycle is incomplete:
98
- else {
99
- // Wait briefly.
100
- await wait(1000);
101
- }
74
+ // Log the start of a check.
75
+ console.log('--');
102
76
  // Configure the next check.
103
- cycleIndex = ++cycleIndex % urlCount;
104
- urlIndex = ++urlIndex % urlCount;
105
- const jobURL = jobURLs[urlIndex];
106
- const publicURL = auths[urlIndex] ? jobURL : getURLBase(jobURL);
107
- const logStart = `Requested job from ${publicURL} and got `;
77
+ const logStart = `Requested job from ${jobHost} and got `;
108
78
  // Perform it.
109
79
  await new Promise(resolve => {
110
80
  try {
111
- const client = jobURL.startsWith('https://') ? httpsClient : httpClient;
81
+ const client = jobURL.protocol === 'https:' ? httpsClient : httpClient;
112
82
  // Request a job.
113
- const requestOptions = isCertTolerant ? {rejectUnauthorized: false} : {};
114
- if (auths[urlIndex]) {
115
- requestOptions.method = 'POST';
116
- }
83
+ const requestOptions = {
84
+ method: 'POST',
85
+ headers: {
86
+ host: jobHost,
87
+ 'content-type': 'application/json; charset=utf-8'
88
+ }
89
+ };
117
90
  client.request(jobURL, requestOptions, response => {
91
+ // Initialize a collection of data from the response.
118
92
  const chunks = [];
119
93
  response
120
94
  // If the response throws an error:
121
95
  .on('error', async error => {
122
96
  // Report it.
123
97
  console.log(`${logStart}error message ${error.message}`);
98
+ // Stop checking.
99
+ abort = true;
124
100
  resolve(true);
125
101
  })
102
+ // If the response delivers data:
126
103
  .on('data', chunk => {
104
+ // Add them to the collection.
127
105
  chunks.push(chunk);
128
106
  })
129
- // When the response arrives:
107
+ // When the response is completed:
130
108
  .on('end', async () => {
131
109
  const content = chunks.join('');
132
- // It should be JSON. If it is:
133
110
  try {
111
+ // Parse it as a JSON job.
134
112
  let contentObj = JSON.parse(content);
135
113
  const {id, sources} = contentObj;
136
- // If it is empty:
114
+ // If it is a no-job message:
137
115
  if (! Object.keys(contentObj).length) {
138
116
  // Report this.
139
- console.log(`${logStart}no job to do`);
117
+ console.log(`${logStart}no job to do; waiting ${intervalInSeconds} sec before next check`);
118
+ // Wait for the specified interval.
119
+ await wait(1000 * intervalInSeconds);
140
120
  resolve(true);
141
121
  }
142
- // Otherwise, if it is a job:
122
+ // Otherwise, if a job was received:
143
123
  else if (id) {
144
124
  // Check it for validity.
145
- const jobInvalidity = isValidJob(contentObj);
125
+ const jobValidity = isValidJob(contentObj);
146
126
  // If it is invalid:
147
- if (! jobInvalidity.isValid) {
127
+ if (! jobValidity.isValid) {
148
128
  // Report this to the server.
149
- serveObject({
129
+ respondWithObject({
150
130
  message: `invalidJob`,
151
- error: jobInvalidity.error
131
+ error: jobValidity.error
152
132
  }, response);
153
- console.log(`${logStart}invalid job (${jobInvalidity.error})`);
133
+ console.log(`${logStart}invalid job (${jobValidity.error})`);
154
134
  resolve(true);
155
135
  }
156
136
  // Otherwise, i.e. if it is valid:
157
137
  else {
158
- // Restart the cycle.
159
- cycleIndex = -1;
160
138
  // Prevent further watching, if unwanted.
161
139
  noJobYet = false;
162
140
  // Add the agent and the server ID to the job.
163
141
  sources.agent = process.env.AGENT || '';
164
- sources.serverID = urlIndex;
165
142
  // Perform the job and create a report.
166
- console.log(`${logStart}job ${id} for server ${urlIndex} (${nowString()})`);
143
+ console.log(`${logStart}job ${id} (${nowString()})`);
167
144
  try {
168
145
  const report = await doJob(contentObj);
169
- const responseObj = auths[urlIndex] ? {
170
- agentPW: auths[urlIndex],
146
+ const responseObj = {
147
+ agentPW,
171
148
  report
172
- } : report;
149
+ };
173
150
  let responseJSON = JSON.stringify(responseObj, null, 2);
174
151
  console.log(`Job ${id} finished (${nowString()})`);
175
- const reportURL = reportURLs[urlIndex];
176
- const publicReportURL = auths[urlIndex] ? reportURL : getURLBase(reportURL);
177
- const reportClient = reportURL.startsWith('https://')
178
- ? httpsClient
179
- : httpClient;
180
- const reportLogStart = `Submitted report ${id} to ${publicReportURL} and got `;
181
- // Send the report to the server that assigned the job.
182
- reportClient.request(reportURL, {method: 'POST'}, repResponse => {
152
+ const reportLogStart = `Submitted report ${id} to ${reportURL} and got `;
153
+ const requestOptions = {
154
+ method: 'POST',
155
+ headers: {
156
+ host: reportHost,
157
+ 'content-type': 'application/json; charset=utf-8'
158
+ }
159
+ };
160
+ // Submit the report.
161
+ const client = reportURL.protocol === 'https:' ? httpsClient : httpClient;
162
+ client.request(reportURL, requestOptions, repResponse => {
163
+ // Initialize a collection of data from the response.
183
164
  const chunks = [];
184
165
  repResponse
185
166
  // If the response to the report threw an error:
186
167
  .on('error', async error => {
187
168
  // Report this.
188
169
  console.log(`${reportLogStart}error message ${error.message}\n`);
170
+ // Stop checking.
171
+ abort = true;
189
172
  resolve(true);
190
173
  })
174
+ // If the response delivers data:
191
175
  .on('data', chunk => {
176
+ // Add them to the collection.
192
177
  chunks.push(chunk);
193
178
  })
194
- // When the response to the report arrives:
179
+ // When the response to the report is completed:
195
180
  .on('end', async () => {
196
181
  const content = chunks.join('');
197
- // It should be JSON. If it is:
198
182
  try {
183
+ // Parse it as a JSON message.
199
184
  const ackObj = JSON.parse(content);
200
185
  // Report it.
201
186
  console.log(
202
187
  `${reportLogStart}response message: ${JSON.stringify(ackObj, null, 2)}\n`
203
188
  );
204
189
  }
205
- // Otherwise, i.e. if it is not JSON:
190
+ // If it is not JSON:
206
191
  catch(error) {
207
192
  // Report this.
208
193
  console.log(
@@ -223,6 +208,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
223
208
  console.log(
224
209
  `ERROR ${error.code} in report submission: ${reportLogStart}error message ${error.message}\n`
225
210
  );
211
+ // Stop checking.
212
+ abort = true;
226
213
  resolve(true);
227
214
  })
228
215
  // Finish submitting the report.
@@ -230,6 +217,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
230
217
  }
231
218
  catch(error) {
232
219
  console.log(`ERROR performing job ${id} (${error.message})`);
220
+ // Stop checking.
221
+ abort = true;
233
222
  resolve(true);
234
223
  }
235
224
  }
@@ -245,6 +234,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
245
234
  catch(error) {
246
235
  // Report this.
247
236
  console.log(`ERROR: ${logStart}status ${response.statusCode}, error message ${error.message}, and non-JSON response ${content.slice(0, 1000)}\n`);
237
+ // Stop checking.
238
+ abort = true;
248
239
  resolve(true);
249
240
  };
250
241
  });
@@ -255,44 +246,52 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
255
246
  if (error.code && error.code.includes('ECONNREFUSED')) {
256
247
  // Report this.
257
248
  console.log(`${logStart}no connection`);
249
+ // Stop checking.
250
+ abort = true;
258
251
  }
259
252
  // Otherwise, if it was a DNS failure:
260
253
  else if (error.code && error.code.includes('ENOTFOUND')) {
261
254
  // Report this.
262
255
  console.log(`${logStart}no domain name resolution`);
256
+ // Stop checking.
257
+ abort = true;
263
258
  }
264
259
  // Otherwise, if it was any other error with a message:
265
260
  else if (error.message) {
266
261
  // Report this.
267
262
  console.log(`ERROR: ${logStart}got error message ${error.message.slice(0, 200)}`);
263
+ // Stop checking.
264
+ abort = true;
268
265
  }
269
266
  // Otherwise, i.e. if it was any other error with no message:
270
267
  else {
271
268
  // Report this.
272
269
  console.log(`ERROR: ${logStart}got an error with no message`);
270
+ // Stop checking.
271
+ abort = true;
273
272
  }
274
273
  resolve(true);
275
274
  })
276
- // Finish sending the job request, with a password if a POST request.
277
- .end(auths[urlIndex] ? JSON.stringify({
278
- agentPW: auths[urlIndex]
279
- }) : '');
275
+ // Finish sending the job request.
276
+ .end(JSON.stringify({
277
+ agentPW
278
+ }));
280
279
  }
281
280
  // If requesting a job throws an error:
282
281
  catch(error) {
283
- // Abort the watch.
284
- abort = true;
285
282
  // Report this.
286
283
  console.log(`ERROR requesting a network job (${error.message})`);
284
+ // Stop checking.
285
+ abort = true;
287
286
  resolve(true);
288
287
  }
289
288
  });
290
289
  }
291
- console.log('Watching complete');
290
+ console.log(`Watching ${abort ? 'aborted' : 'complete'}`);
292
291
  }
293
- // Otherwise, i.e. if the job URLs do not exist or are invalid:
292
+ // Otherwise, i.e. if the job or report URL does not exist or is invalid:
294
293
  else {
295
294
  // Report this.
296
- console.log('ERROR: List of job URLs invalid');
295
+ console.log('ERROR: Job or report URL does not exist or is invalid');
297
296
  }
298
297
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "69.5.0",
3
+ "version": "69.6.2",
4
4
  "description": "Run 1000 web accessibility tests from 11 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/procs/doActs.js CHANGED
@@ -49,21 +49,24 @@ const waits = Number.parseInt(process.env.WAITS) || 0;
49
49
  // Time limits in seconds on tools, accounting for page reloads by 6 Testaro tests.
50
50
  const timeLimits = {
51
51
  alfa: 30,
52
+ aslint: 45,
52
53
  ed11y: 30,
54
+ htmlcs: 30,
53
55
  ibm: 30,
54
- testaro: 150 + Math.round(6 * waits / 1000)
56
+ nuVal: 30,
57
+ nuVnu: 20,
58
+ qualWeb: 45,
59
+ testaro: 150 + Math.round(6 * waits / 1000),
60
+ wax: 35
55
61
  };
56
62
  // Timeout multiplier.
57
63
  const timeoutMultiplier = Number.parseFloat(process.env.TIMEOUT_MULTIPLIER) || 1;
58
64
 
59
65
  // FUNCTIONS
60
66
 
61
- // Sends a notice to an observer.
67
+ // Sends a notice to a network observer.
62
68
  const tellServer = (report, messageParams, logMessage) => {
63
- const {serverID} = report.sources;
64
- const observerURL = typeof serverID === 'number'
65
- ? process.env[`NETWATCH_URL_${serverID}_OBSERVE`]
66
- : '';
69
+ const observerURL = process.env.NETWATCH_URL_OBSERVE;
67
70
  if (observerURL) {
68
71
  const whoParams = `agent=${agent}&jobID=${report.id || ''}`;
69
72
  const wholeURL = `${observerURL}?${whoParams}&${messageParams}`;
@@ -306,7 +309,6 @@ exports.doActs = async (report, opts = {}) => {
306
309
  type,
307
310
  which
308
311
  });
309
- console.log(`${message} (observer notified)`);
310
312
  }
311
313
  catch (error) {
312
314
  console.log(`${message} (observer notification failed: ${errorStart(error)})`);
package/run.js CHANGED
@@ -52,6 +52,8 @@ exports.doJob = async (job, opts = {}) => {
52
52
  }
53
53
  // Otherwise, i.e. if it is valid:
54
54
  else {
55
+ // Report this.
56
+ console.log(`Starting job ${job.id} (${job.target.what})`);
55
57
  // Add initialized job data to the report.
56
58
  const startTime = new Date();
57
59
  report.jobData = {
package/tests/nuVal.js CHANGED
@@ -50,8 +50,8 @@ exports.reporter = async (page, report, actIndex) => {
50
50
  const fetchOptions = {
51
51
  method: 'post',
52
52
  headers: {
53
- 'User-Agent': 'Mozilla/5.0',
54
- 'Content-Type': 'text/html; charset=utf-8'
53
+ 'user-agent': 'Mozilla/5.0',
54
+ 'content-type': 'text/html; charset=utf-8'
55
55
  },
56
56
  body: testTarget
57
57
  };