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 +9 -9
- package/call.js +1 -1
- package/netWatch.js +2 -3
- package/package.json +1 -1
- package/procs/identify.js +23 -6
- package/procs/job.js +9 -6
- package/run.js +1 -1
- package/tests/ed11y.js +41 -26
- package/tests/nuVal.js +17 -5
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
|
-
- `
|
|
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:
|
|
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
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
162
|
-
const
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
//
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
|
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,
|