testaro 41.0.2 → 42.0.1

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,7 +132,6 @@ Here is an example of a job:
132
132
  ```javaScript
133
133
  {
134
134
  id: '250110T1200-7f-4',
135
- what: 'aside mislocation',
136
135
  strict: true,
137
136
  isolate: true,
138
137
  standard: 'also',
@@ -143,17 +142,16 @@ Here is an example of a job:
143
142
  timeLimit: 80,
144
143
  creationTimeStamp: '241229T0537',
145
144
  executionTimeStamp: '250110T1200',
145
+ sendReportTo: 'https://abccorp.com/api/report',
146
+ target: {
147
+ what: 'Real Estate Management',
148
+ url: 'https://abccorp.com/mgmt/realproperty.html'
149
+ },
146
150
  sources: {
147
151
  script: 'ts99',
148
152
  batch: 'departments',
149
153
  mergeID: '7f',
150
- sendReportTo: 'https://abccorp.com/api/report',
151
154
  requester: 'malavu@abccorp.com'
152
- target: {
153
- what: 'Real Estate Management',
154
- url: 'https://abccorp.com/mgmt/realproperty.html'
155
- },
156
- lastTarget: false,
157
155
  },
158
156
  acts: [
159
157
  {
@@ -194,7 +192,9 @@ Job properties:
194
192
  - `timeLimit`: the number of seconds allowed for the execution of the job.
195
193
  - `creationTimeStamp`: a string in `yymmddThhMM` format, describing when the job was created.
196
194
  - `executionTimeStamp`: a string in `yymmddThhMM` format, specifying a date and time before which the job is not to be performed.
197
- - `sources`: an object describing the source of the job.
195
+ - `sendReportTo`: the URL to which the job report is to be sent, or `''` if not a `netWatch` job.
196
+ - `target`: data about the target of the job, or `{}` if the job involves multiple targets.
197
+ - `sources`: data optionally inserted into the job by the job creator for use by the job creator.
198
198
  - `acts`: an array of the acts to be performed (documented below).
199
199
 
200
200
  ## Acts
@@ -237,7 +237,7 @@ When the texts of multiple elements of the same type will contain the same `whic
237
237
 
238
238
  #### Navigations
239
239
 
240
- An example of a **navigation** is the act of type `launch` above. The launch configuration is inherited from properties of the job, except that the act may override any of those properties.
240
+ An example of a **navigation** is the act of type `launch` above. The launch configuration is inherited from the `deviceID`, `browserID`, `lowMotion`, and `target` properties of the job, except that the act may override any of those properties.
241
241
 
242
242
  If any act alters the page, you can restore the page to its original state for the next act by inserting a new `launch` act (and, if necessary, additional page-specific acts) between them.
243
243
 
package/call.js CHANGED
@@ -83,7 +83,7 @@ const callRun = async jobIDStart => {
83
83
  // Otherwise, i.e. if the job does not exist.
84
84
  else {
85
85
  // Report the error.
86
- console.log('ERROR: No specified job exists');
86
+ console.log('ERROR: Specified job does not exist');
87
87
  }
88
88
  };
89
89
  // Starts a directory watch, converting the interval argument to a number.
package/netWatch.js CHANGED
@@ -132,9 +132,9 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
132
132
  .on('end', async () => {
133
133
  const content = chunks.join('');
134
134
  try {
135
- // If there was no job to do:
136
135
  let contentObj = JSON.parse(content);
137
136
  let jobInvalidity = '';
137
+ // If there was no job to do:
138
138
  if (! Object.keys(contentObj).length) {
139
139
  // Report this.
140
140
  console.log(`No job to do at ${url}`);
@@ -142,8 +142,7 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
142
142
  }
143
143
  // Otherwise, i.e. if there was a job or a message:
144
144
  else {
145
- const {id, message, sources} = contentObj;
146
- const sendReportTo = sources ? sources.sendReportTo : '';
145
+ const {id, message, sendReportTo, sources} = contentObj;
147
146
  // If the server sent a message, not a job:
148
147
  if (message) {
149
148
  // Report it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "41.0.2",
3
+ "version": "42.0.1",
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
@@ -96,7 +96,7 @@ exports.identify = async (instance, page) => {
96
96
  const {type, spec} = location;
97
97
  // If the instance specifies a CSS selector or XPath location:
98
98
  if (['selector', 'xpath'].includes(type)) {
99
- // Get a locator of the element.
99
+ // Get locators for elements with that specifier.
100
100
  let specifier = spec;
101
101
  if (type === 'xpath') {
102
102
  specifier = spec.replace(/\/text\(\)\[\d+\]$/, '');
@@ -107,33 +107,50 @@ exports.identify = async (instance, page) => {
107
107
  }
108
108
  try {
109
109
  const locators = page.locator(specifier);
110
+ // Get their count, or throw an error if the specifier is invalid.
110
111
  const locatorCount = await locators.count();
111
- // If the count of matching elements is 1:
112
+ // If the specifier is valid and the count is 1:
112
113
  if (locatorCount === 1) {
113
114
  // Add a box ID and a path ID to the result.
114
115
  await addIDs(locators, elementID);
115
116
  }
116
- // Otherwise, if the count is not 1 and the instance specifies an XPath location:
117
+ /*
118
+ Otherwise, if the specifier is valid, the count is not 1, and the instance specifies
119
+ an XPath location:
120
+ */
117
121
  else if (type === 'xpath') {
118
122
  // Use the XPath location as the path ID.
119
123
  elementID.pathID = spec;
120
124
  }
121
125
  }
126
+ // If the specifier is invalid:
122
127
  catch(error) {
123
- console.log(`ERROR locating element by CSS selector or XPath (${error.message})`);
128
+ // Add this to the instance.
129
+ instance.invalidity = {
130
+ badProperty: 'location',
131
+ validityError: error.message
132
+ };
124
133
  }
125
134
  }
126
135
  }
127
136
  // If either ID remains undefined and the instance specifies an element ID:
128
137
  if (id && ! (elementID.boxID && elementID.pathID)) {
129
- // Get the first of the locators for elements with the ID.
138
+ /*
139
+ Get the first locator for an element with the ID, or throw an error if the identifier is
140
+ invalid.
141
+ */
130
142
  try {
131
143
  let locator = page.locator(`#${id.replace(/([-&;/]|^\d)/g, '\\$1')}`).first();
132
144
  // Add a box ID and a path ID to the result.
133
145
  await addIDs(locator, elementID);
134
146
  }
147
+ // If the identifier is invalid:
135
148
  catch(error) {
136
- console.log(`ERROR locating element by ID (${error.message})`);
149
+ // Add this to the instance.
150
+ instance.invalidity = {
151
+ badProperty: 'id',
152
+ validityError: error.message
153
+ };
137
154
  }
138
155
  }
139
156
  // If either ID remains undefined and the instance specifies a tag name:
package/procs/job.js CHANGED
@@ -196,6 +196,8 @@ exports.isValidJob = job => {
196
196
  timeLimit,
197
197
  creationTimeStamp,
198
198
  executionTimeStamp,
199
+ sendReportTo,
200
+ target,
199
201
  sources,
200
202
  acts
201
203
  } = job;
@@ -237,12 +239,13 @@ exports.isValidJob = job => {
237
239
  ) {
238
240
  return 'bad job executionTimeStamp';
239
241
  }
240
- if (
241
- ! sources
242
- || typeof sources !== 'object'
243
- || ! ['script', 'batch', 'target'].every(key => sources[key])
244
- || ! ['what', 'url'].every(key => sources.target[key])
245
- ) {
242
+ if (typeof sendReportTo !== 'string' || sendReportTo && ! isURL(sendReportTo)) {
243
+ return 'bad job sendReportTo';
244
+ }
245
+ if (typeof target !== 'object' || target.url && ! isURL(target.url) || target.what === '') {
246
+ return 'bad job target';
247
+ }
248
+ if (sources && typeof sources !== 'object') {
246
249
  return 'Bad job sources';
247
250
  }
248
251
  if (
package/run.js CHANGED
@@ -622,7 +622,7 @@ const doActs = async (report, actIndex, page) => {
622
622
  // Launch the specified browser on the specified device and navigate to the specified URL.
623
623
  const launchResult = await launch(
624
624
  report,
625
- act.url || report.sources.target.url,
625
+ act.url || report.target.url,
626
626
  debug,
627
627
  waits,
628
628
  act.deviceID || report.deviceID,
package/tests/ed11y.js CHANGED
@@ -48,7 +48,7 @@ exports.reporter = async (page, options) => {
48
48
  const timer = setTimeout(() => {
49
49
  // Return this as the report.
50
50
  resolve({
51
- facts: {
51
+ result: {
52
52
  prevented: true,
53
53
  error: 'ed11y timed out'
54
54
  }
@@ -151,37 +151,52 @@ exports.reporter = async (page, options) => {
151
151
  }
152
152
  catch(error) {
153
153
  resolve({
154
- facts: {
154
+ result: {
155
155
  prevented: true,
156
156
  error: error.message
157
157
  }
158
158
  });
159
159
  };
160
160
  }), {scriptNonce, script, rulesToTest: act.rules});
161
- // Add the violation facts to the result.
162
- const factsJSHandle = await reportJSHandle.getProperty('facts');
163
- const facts = await factsJSHandle.jsonValue();
164
- const result = facts;
165
- // If there were any violations:
166
- const {violations} = facts;
167
- if (violations && violations.length) {
168
- // Get the violating elements.
169
- const elementsJSHandle = await reportJSHandle.getProperty('elements');
170
- const elementJSHandles = await elementsJSHandle.getProperties();
171
- // For each violation:
172
- for (const index in violations) {
173
- // Get its path ID.
174
- const elementHandle = elementJSHandles.get(index).asElement();
175
- const pathID = await xPath(elementHandle);
176
- // Add it to the violation facts.
177
- violations[index].pathID = pathID;
161
+ // Initialize the result as the violation facts.
162
+ const resultJSHandle = await reportJSHandle.getProperty('facts');
163
+ const result = await resultJSHandle.jsonValue();
164
+ // If there were any violation facts:
165
+ if (result) {
166
+ // Get the violations from them.
167
+ const {violations} = result;
168
+ // If any exist:
169
+ if (violations && violations.length) {
170
+ // Get the violating elements.
171
+ const elementsJSHandle = await reportJSHandle.getProperty('elements');
172
+ const elementJSHandles = await elementsJSHandle.getProperties();
173
+ // For each violation:
174
+ for (const index in violations) {
175
+ // Get its path ID from the identically indexed element.
176
+ const elementHandle = elementJSHandles.get(index).asElement();
177
+ const pathID = await xPath(elementHandle);
178
+ // Add the path ID to the violation facts of the result.
179
+ violations[index].pathID = pathID;
180
+ };
181
+ }
182
+ // Return the data and result, discarding the separate element data.
183
+ return {
184
+ data: {
185
+ prevented: result.prevented
186
+ },
187
+ result
178
188
  };
179
189
  }
180
- // Return the report.
181
- return {
182
- data: {
183
- prevented: facts.prevented
184
- },
185
- result
186
- };
190
+ // Otherwise, i.e. if there were no violation facts:
191
+ else {
192
+ // Return this.
193
+ return {
194
+ data: {
195
+ prevented: false
196
+ },
197
+ result: {
198
+ prevented: false,
199
+ }
200
+ }
201
+ }
187
202
  };
package/tests/nuVal.js CHANGED
@@ -47,9 +47,14 @@ exports.reporter = async (page, options) => {
47
47
  const pageContent = await page.content();
48
48
  // Get the source.
49
49
  const sourceData = await getSource(page);
50
- // If it was not obtained:
51
- const data = {};
50
+ const data = {
51
+ docTypes: {
52
+ pageContent: {},
53
+ rawPage: {}
54
+ }
55
+ };
52
56
  const result = {};
57
+ // If it was not obtained:
53
58
  if (sourceData.prevented) {
54
59
  // Report this.
55
60
  data.prevented = true;
@@ -66,8 +71,9 @@ exports.reporter = async (page, options) => {
66
71
  }
67
72
  };
68
73
  const nuURL = 'https://validator.w3.org/nu/?parser=html&out=json';
74
+ const pageTypes = [['pageContent', pageContent], ['rawPage', sourceData.source]];
69
75
  // For each page type:
70
- for (const page of [['pageContent', pageContent], ['rawPage', sourceData.source]]) {
76
+ for (const page of pageTypes) {
71
77
  try {
72
78
  // Get a Nu Html Checker report on it.
73
79
  fetchOptions.body = page[1];
@@ -96,10 +102,16 @@ exports.reporter = async (page, options) => {
96
102
  catch (error) {
97
103
  const message = `ERROR getting results for ${page[0]} (${error.message})`;
98
104
  console.log(message);
99
- data.prevented = true;
100
- data.error = message;
105
+ data.docTypes[page[0]].prevented = true;
106
+ data.docTypes[page[0]].error = message;
101
107
  };
102
108
  };
109
+ // If both page types prevented testing:
110
+ if (pageTypes.every(pageType => data.docTypes[pageType[0]].prevented)) {
111
+ // Report this.
112
+ data.prevented = true;
113
+ data.error = 'Both doc types prevented';
114
+ }
103
115
  }
104
116
  return {
105
117
  data,