testaro 60.18.2 → 61.1.0
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/AGENTS.md +1 -1
- package/README.md +6 -6
- package/{VALIDATION_README.md → VALIDATION.md} +1 -1
- package/actSpecs.js +1 -1
- package/package.json +3 -2
- package/procs/job.js +2 -1
- package/procs/standardize.js +82 -33
- package/run.js +1 -1
- package/tests/nuVal.js +2 -7
- package/tests/nuVnu.js +131 -0
package/AGENTS.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
- **Main dirs**: `/tests` (tool test definitions), `/procs` (shared procedures), `/validation` (test validators), root (core modules)
|
|
15
15
|
- **Key files**: `run.js` (main executor), `actSpecs.js` (act specifications), `call.js` (CLI entry), `tests/testaro.js` (Testaro tool rules)
|
|
16
|
-
- **Tools**: Integrates
|
|
16
|
+
- **Tools**: Integrates 12 accessibility tools (Axe, Alfa, IBM Checker, QualWeb, ASLint, WAVE, WallyAX, Ed11y, HTML CodeSniffer, Nu Validator API, Nu Html Checker, Testaro)
|
|
17
17
|
- **Data flow**: Jobs (JSON) → run.js → tool tests → reports (with standardized results)
|
|
18
18
|
- **Env vars**: Required for WallyAX (`WAX_KEY`), WAVE (`WAVE_KEY`); optional `DEBUG`, `WAITS`, `JOBDIR`, `REPORTDIR`, `AGENT`
|
|
19
19
|
|
package/README.md
CHANGED
|
@@ -342,9 +342,9 @@ That means that a test act (i.e. an act with a `type` property having the value
|
|
|
342
342
|
|
|
343
343
|
If a particular test act either must have or may have any other properties, those properties are specified in the `tools` property in `actSpecs.js`.
|
|
344
344
|
|
|
345
|
-
When you include a `rules` property, you limit the tests of the tool that are performed or reported. For some tools (`alfa`, `axe`, `htmlcs`, `qualWeb`, `testaro`, and `wax`), only the specified tests are performed. Other tools (`aslint`, `ed11y`, `ibm`, `nuVal`, and `wave`) do not allow such a limitation, so, for those tools, all tests are performed but results are reported from only the specified tests.
|
|
345
|
+
When you include a `rules` property, you limit the tests of the tool that are performed or reported. For some tools (`alfa`, `axe`, `htmlcs`, `qualWeb`, `testaro`, and `wax`), only the specified tests are performed. Other tools (`aslint`, `ed11y`, `ibm`, `nuVal`, `nuVnu`, and `wave`) do not allow such a limitation, so, for those tools, all tests are performed but results are reported from only the specified tests.
|
|
346
346
|
|
|
347
|
-
The `nuVal`, `qualWeb`, and `testaro` tools require specific formats for the `rules` property. Those formats are described below in the sections about those tools.
|
|
347
|
+
The `nuVal`, `nuVnu`, `qualWeb`, and `testaro` tools require specific formats for the `rules` property. Those formats are described below in the sections about those tools.
|
|
348
348
|
|
|
349
349
|
##### Examples of test acts
|
|
350
350
|
|
|
@@ -490,9 +490,9 @@ Experimentation indicates that the `ibm` tool emits untrappable errors for some
|
|
|
490
490
|
|
|
491
491
|
#### Nu Html Checker
|
|
492
492
|
|
|
493
|
-
The `nuVal`
|
|
493
|
+
The `nuVal` and `nuVnu` tools perform the tests of the Nu Html Checker.
|
|
494
494
|
|
|
495
|
-
Its `rules` argument is **not** an array of rule IDs, but instead is an array of rule _specifications_. A rule specification for `nuVal` is a string with the format `=ruleID` or `~ruleID`. The `=` prefix indicates that the rule ID is invariable. The `~` prefix indicates that the rule ID is variable, in which case the `ruleID` part of the specification is a matching regular expression, rather than the exact text of a message. This `rules` format arises from the fact that `nuVal`
|
|
495
|
+
Its `rules` argument is **not** an array of rule IDs, but instead is an array of rule _specifications_. A rule specification for `nuVal` or `nuVnu` is a string with the format `=ruleID` or `~ruleID`. The `=` prefix indicates that the rule ID is invariable. The `~` prefix indicates that the rule ID is variable, in which case the `ruleID` part of the specification is a matching regular expression, rather than the exact text of a message. This `rules` format arises from the fact that `nuVal` and `nuVnu` generate customized messages and do not accompany them with rule identifiers.
|
|
496
496
|
|
|
497
497
|
#### QualWeb
|
|
498
498
|
|
|
@@ -731,7 +731,7 @@ This instance says that a `button` element violates a rule named `rule01`.
|
|
|
731
731
|
|
|
732
732
|
The element has no `id` attribute to distinguish it from other `button` elements, but the tool describes its location. This tool uses an XPath to do that. Tools use various methods for location description, namely:
|
|
733
733
|
|
|
734
|
-
- `
|
|
734
|
+
- `code` (line, starting column, and ending column): Nu Html Checker (API and installed)
|
|
735
735
|
- `selector` (CSS selector): Axe, QualWeb, WAVE
|
|
736
736
|
- `xpath`: Alfa, ASLint, Equal Access
|
|
737
737
|
- `box` (coordinates, width, and height of the element box): Editoria11y, Testaro
|
|
@@ -771,7 +771,7 @@ This standard format reflects some judgments. For example:
|
|
|
771
771
|
|
|
772
772
|
- The `ordinalSeverity` property of an instance involves interpretation. Tools may report severity, certainty, priority, or some combination of those. They may use ordinal or metric quantifications. If they quantify ordinally, their scales may have more or fewer than 4 ranks. Testaro coerces each tool’s severity, certainty, and/or priority classification into a 4-rank ordinal classification. This classification is deemed to express the most common pattern among the tools.
|
|
773
773
|
- The `tagName` property of an instance may not always be obvious, because in some cases the rule being tested for requires a relationship among more than one element (e.g., “An X element may not have a Y element as its parent”).
|
|
774
|
-
- The `ruleID` property of an instance is a matching rule if the tool issues a message but no rule identifier for each instance. The `nuVal`
|
|
774
|
+
- The `ruleID` property of an instance is a matching rule if the tool issues a message but no rule identifier for each instance. The `nuVal` and `nuVnu` tools do this. In this case, Testaro is classifying the messages into rules.
|
|
775
775
|
- The `ruleID` property of an instance may reclassify tool rules. For example, if a tool rule covers multiple situations that are dissimilar, that rule may be split into multiple rules with distinct `ruleID` properties.
|
|
776
776
|
|
|
777
777
|
You are not dependent on the judgments incorporated into the standard format, because Testaro can give you the original reports from the tools as the `result` property of a `test` act.
|
package/actSpecs.js
CHANGED
|
@@ -133,7 +133,7 @@ exports.actSpecs = {
|
|
|
133
133
|
{
|
|
134
134
|
which: [true, 'string', 'isTest', 'tool name'],
|
|
135
135
|
launch: [false, 'object', '', 'new target, browserID, and/or what, if any'],
|
|
136
|
-
rules: [false, 'array', 'areStrings', 'rule IDs or (for testaro or
|
|
136
|
+
rules: [false, 'array', 'areStrings', 'rule IDs or (for testaro, nuVal, or nuVnu) specifications, if not all']
|
|
137
137
|
}
|
|
138
138
|
],
|
|
139
139
|
text: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testaro",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "61.1.0",
|
|
4
4
|
"description": "Run 1000 web accessibility tests from 11 tools and get a standardized report",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
"playwright-dompath": "*",
|
|
49
49
|
"playwright-extra": "*",
|
|
50
50
|
"playwright-extra-plugin-stealth": "*",
|
|
51
|
-
"puppeteer-extra-plugin-stealth": "*"
|
|
51
|
+
"puppeteer-extra-plugin-stealth": "*",
|
|
52
|
+
"vnu-jar": "*"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"dom-accessibility-api": "*",
|
package/procs/job.js
CHANGED
|
@@ -31,7 +31,8 @@ const tools = exports.tools = {
|
|
|
31
31
|
ed11y: 'Editoria11y',
|
|
32
32
|
htmlcs: 'HTML CodeSniffer WCAG 2.1 AA ruleset',
|
|
33
33
|
ibm: 'IBM Accessibility Checker',
|
|
34
|
-
nuVal: 'Nu Html Checker',
|
|
34
|
+
nuVal: 'Nu Html Checker API',
|
|
35
|
+
nuVnu: 'Nu Html Checker',
|
|
35
36
|
qualWeb: 'QualWeb',
|
|
36
37
|
testaro: 'Testaro',
|
|
37
38
|
wax: 'WallyAX',
|
package/procs/standardize.js
CHANGED
|
@@ -30,31 +30,24 @@ const cap = rawString => {
|
|
|
30
30
|
};
|
|
31
31
|
// Returns whether an id attribute value is valid without character escaping.
|
|
32
32
|
const isBadID = id => /[^-\w]|^\d|^--|^-\d/.test(id);
|
|
33
|
-
// Returns
|
|
33
|
+
// Returns a tag name and the value of an id attribute from a substring of HTML code.
|
|
34
34
|
const getIdentifiers = code => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
// If the id value is invalid without character escaping:
|
|
51
|
-
if (isBadID(id)) {
|
|
52
|
-
// Remove it.
|
|
53
|
-
id = '';
|
|
54
|
-
}
|
|
55
|
-
}
|
|
35
|
+
// Normalize the code.
|
|
36
|
+
code = code.replace(/\s+/g, ' ').replace(/\\"/g, '"');
|
|
37
|
+
// Get the first start tag of an element, if any.
|
|
38
|
+
const startTagData = code.match(/^.*?< ?([^>]*)/);
|
|
39
|
+
// If there is any:
|
|
40
|
+
if (startTagData) {
|
|
41
|
+
// Get the tag name.
|
|
42
|
+
const tagNameData = startTagData[1].match(/^[A-Za-z]+/);
|
|
43
|
+
const tagName = tagNameData ? tagNameData[0].toUpperCase() : '';
|
|
44
|
+
// Get the value of the id attribute, if any.
|
|
45
|
+
const idData = startTagData[1].match(/ id="([^"]+)"/);
|
|
46
|
+
const id = idData ? idData[1] : '';
|
|
47
|
+
// Return the tag name and the value of the id attribute, if any.
|
|
48
|
+
return [tagName, id];
|
|
56
49
|
}
|
|
57
|
-
return [
|
|
50
|
+
return ['', ''];
|
|
58
51
|
};
|
|
59
52
|
/*
|
|
60
53
|
Differentiates some rule IDs of aslint.
|
|
@@ -221,30 +214,77 @@ const doNuVal = (result, standardResult, docType) => {
|
|
|
221
214
|
const items = result[docType] && result[docType].messages;
|
|
222
215
|
if (items && items.length) {
|
|
223
216
|
items.forEach(item => {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
217
|
+
const {extract, firstColumn, lastColumn, lastLine, message, subType, type} = item;
|
|
218
|
+
const identifiers = getIdentifiers(extract);
|
|
219
|
+
if (! identifiers[0] && message) {
|
|
220
|
+
const tagNameLCArray = message.match(
|
|
227
221
|
/^Element ([^ ]+)|^An (img) element| (meta|script) element| element (script)| tag (script)/
|
|
228
222
|
);
|
|
229
223
|
if (tagNameLCArray && tagNameLCArray[1]) {
|
|
230
224
|
identifiers[0] = tagNameLCArray[1].toUpperCase();
|
|
231
225
|
}
|
|
232
226
|
}
|
|
233
|
-
|
|
227
|
+
let spec = '';
|
|
228
|
+
const locationSegments = [lastLine, firstColumn, lastColumn];
|
|
229
|
+
if (locationSegments.every(segment => typeof segment === 'number')) {
|
|
230
|
+
spec = locationSegments.join(':');
|
|
231
|
+
}
|
|
234
232
|
const instance = {
|
|
235
|
-
ruleID:
|
|
236
|
-
what:
|
|
233
|
+
ruleID: message,
|
|
234
|
+
what: message,
|
|
237
235
|
ordinalSeverity: -1,
|
|
238
236
|
tagName: identifiers[0],
|
|
239
237
|
id: identifiers[1],
|
|
240
238
|
location: {
|
|
241
239
|
doc: docType === 'pageContent' ? 'dom' : 'source',
|
|
242
|
-
type: '
|
|
243
|
-
spec
|
|
240
|
+
type: 'code',
|
|
241
|
+
spec
|
|
244
242
|
},
|
|
245
|
-
excerpt: cap(
|
|
243
|
+
excerpt: cap(extract)
|
|
244
|
+
};
|
|
245
|
+
if (type === 'info' && subType === 'warning') {
|
|
246
|
+
instance.ordinalSeverity = 0;
|
|
247
|
+
}
|
|
248
|
+
else if (type === 'error') {
|
|
249
|
+
instance.ordinalSeverity = subType === 'fatal' ? 3 : 2;
|
|
250
|
+
}
|
|
251
|
+
standardResult.instances.push(instance);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
// Converts issue instances from a nuVnu document type.
|
|
256
|
+
const doNuVnu = (result, standardResult, docType) => {
|
|
257
|
+
const items = result[docType] && result[docType].messages;
|
|
258
|
+
if (items && items.length) {
|
|
259
|
+
items.forEach(item => {
|
|
260
|
+
const {extract, firstColumn, lastColumn, lastLine, message, subType, type} = item;
|
|
261
|
+
const identifiers = getIdentifiers(extract);
|
|
262
|
+
if (! identifiers[0] && message) {
|
|
263
|
+
const tagNameLCArray = message.match(
|
|
264
|
+
/^Element ([^ ]+)|^An (img) element| (meta|script) element| element (script)| tag (script)/
|
|
265
|
+
);
|
|
266
|
+
if (tagNameLCArray && tagNameLCArray[1]) {
|
|
267
|
+
identifiers[0] = tagNameLCArray[1].toUpperCase();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
let spec = '';
|
|
271
|
+
const locationSegments = [lastLine, firstColumn, lastColumn];
|
|
272
|
+
if (locationSegments.every(segment => typeof segment === 'number')) {
|
|
273
|
+
spec = locationSegments.join(':');
|
|
274
|
+
}
|
|
275
|
+
const instance = {
|
|
276
|
+
ruleID: message,
|
|
277
|
+
what: message,
|
|
278
|
+
ordinalSeverity: -1,
|
|
279
|
+
tagName: identifiers[0],
|
|
280
|
+
id: identifiers[1],
|
|
281
|
+
location: {
|
|
282
|
+
doc: docType === 'pageContent' ? 'dom' : 'source',
|
|
283
|
+
type: 'code',
|
|
284
|
+
spec
|
|
285
|
+
},
|
|
286
|
+
excerpt: cap(extract)
|
|
246
287
|
};
|
|
247
|
-
const {type, subType} = item;
|
|
248
288
|
if (type === 'info' && subType === 'warning') {
|
|
249
289
|
instance.ordinalSeverity = 0;
|
|
250
290
|
}
|
|
@@ -568,6 +608,15 @@ const convert = (toolName, data, result, standardResult) => {
|
|
|
568
608
|
doNuVal(result, standardResult, 'rawPage');
|
|
569
609
|
}
|
|
570
610
|
}
|
|
611
|
+
// nuVnu
|
|
612
|
+
else if (toolName === 'nuVnu' && (result.pageContent || result.rawPage)) {
|
|
613
|
+
if (result.pageContent) {
|
|
614
|
+
doNuVnu(result, standardResult, 'pageContent');
|
|
615
|
+
}
|
|
616
|
+
if (result.rawPage) {
|
|
617
|
+
doNuVnu(result, standardResult, 'rawPage');
|
|
618
|
+
}
|
|
619
|
+
}
|
|
571
620
|
// qualWeb
|
|
572
621
|
else if (
|
|
573
622
|
toolName === 'qualWeb'
|
package/run.js
CHANGED
|
@@ -83,7 +83,7 @@ const timeLimits = {
|
|
|
83
83
|
alfa: 20,
|
|
84
84
|
ed11y: 30,
|
|
85
85
|
ibm: 30,
|
|
86
|
-
testaro:
|
|
86
|
+
testaro: 150 + Math.round(6 * waits / 1000)
|
|
87
87
|
};
|
|
88
88
|
// Timeout multiplier.
|
|
89
89
|
const timeoutMultiplier = Number.parseFloat(process.env.TIMEOUT_MULTIPLIER) || 1;
|
package/tests/nuVal.js
CHANGED
|
@@ -9,13 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
/*
|
|
11
11
|
nuVal
|
|
12
|
-
This tool subjects a page and its source to the Nu Html Checker, thereby testing scripted
|
|
13
|
-
|
|
14
|
-
The API erratically replaces left and right double quotation marks with invalid UTF-8, which
|
|
15
|
-
appears as 2 or 3 successive instances of the replacement character (U+fffd). Therefore, this
|
|
16
|
-
test removes all such quotation marks and the replacement character. That causes
|
|
17
|
-
'Bad value “” for' to become 'Bad value for'. Since the corruption of quotation marks is
|
|
18
|
-
erratic, no better solution is known.
|
|
12
|
+
This tool subjects a page and its source to the Nu Html Checker, thereby testing scripted content found only in the loaded page and erroneous content before the browser corrects it. The API erratically replaces left and right double quotation marks with invalid UTF-8, which appears as 2 or 3 successive instances of the replacement character (U+fffd). Therefore, this test removes all such quotation marks and the replacement character. That causes 'Bad value “” for' to become 'Bad value for'. Since the corruption of quotation marks is erratic, no better solution is known.
|
|
13
|
+
This tool is the API version of the Nu Html Checker. It is an alternative to the vnu tool, which uses the same validator as an installed dependency. Each tool has advantages and disadvantages. The main advantage of nuVal is that it does not require the Testaro host to provide a Java virtual machine. The main disadvantage of nuVal is that it returns 502 status errors when the content being uploaded is larger than about 80,000 bytes. The main advantage of the vnu tool is that it can evaluate pages larger than about 80,000 bytes and pages reachable from the host that Testaro runs on even if not reachable from the public Internet.
|
|
19
14
|
*/
|
|
20
15
|
|
|
21
16
|
// IMPORTS
|
package/tests/nuVnu.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/*
|
|
2
|
+
© 2022–2024 CVS Health and/or one of its affiliates. All rights reserved.
|
|
3
|
+
© 2025 Jonathan Robert Pool.
|
|
4
|
+
|
|
5
|
+
Licensed under the MIT License. See LICENSE file at the project root or
|
|
6
|
+
https://opensource.org/license/mit/ for details.
|
|
7
|
+
|
|
8
|
+
SPDX-License-Identifier: MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
This tool subjects a page and its source to the Nu Html Checker, thereby testing scripted content found only in the loaded page and erroneous content before the browser corrects it. The API erratically replaces left and right double quotation marks with invalid UTF-8, which appears as 2 or 3 successive instances of the replacement character (U+fffd). Therefore, this test removes all such quotation marks and the replacement character. That causes 'Bad value “” for' to become 'Bad value for'. Since the corruption of quotation marks is erratic, no better solution is known.
|
|
13
|
+
This tool is the installed version of the Nu Html Checker. It is an alternative to the nuVal tool, which uses the same validator as a web service of the World Wide Web Consortium (W3C). Each tool has advantages and disadvantages. The main advantage of the nuVnu tool is that it can evaluate pages larger than about 80,000 bytes and pages reachable from the host that Testaro runs on even if not reachable from the public Internet. The main advantage of nuVal is that it does not require the Testaro host to provide a Java virtual machine.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// IMPORTS
|
|
17
|
+
|
|
18
|
+
// Module to perform file operations.
|
|
19
|
+
const fs = require('fs/promises');
|
|
20
|
+
// Module to define the operating-system temporary-file directory.
|
|
21
|
+
const os = require('os');
|
|
22
|
+
// Module to run tests.
|
|
23
|
+
const {vnu} = require('vnu-jar');
|
|
24
|
+
// Module to get the document source.
|
|
25
|
+
const {getSource} = require('../procs/getSource');
|
|
26
|
+
|
|
27
|
+
// CONSTANTS
|
|
28
|
+
|
|
29
|
+
const tmpDir = os.tmpdir();
|
|
30
|
+
|
|
31
|
+
// FUNCTIONS
|
|
32
|
+
|
|
33
|
+
// Conducts and reports the Nu Html Checker tests.
|
|
34
|
+
exports.reporter = async (page, report, actIndex) => {
|
|
35
|
+
const act = report.acts[actIndex];
|
|
36
|
+
const {rules} = act;
|
|
37
|
+
// Get the browser-parsed page.
|
|
38
|
+
const pageContent = await page.content();
|
|
39
|
+
const pagePath = `${tmpDir}/nuVnu-page-${report.id}.html`;
|
|
40
|
+
// Save it.
|
|
41
|
+
await fs.writeFile(pagePath, pageContent);
|
|
42
|
+
// Get the source.
|
|
43
|
+
const sourceData = await getSource(page);
|
|
44
|
+
const data = {
|
|
45
|
+
docTypes: {
|
|
46
|
+
pageContent: {},
|
|
47
|
+
rawPage: {}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const result = {};
|
|
51
|
+
// If the source was not obtained:
|
|
52
|
+
if (sourceData.prevented) {
|
|
53
|
+
// Report this.
|
|
54
|
+
data.prevented = true;
|
|
55
|
+
data.error = sourceData.error;
|
|
56
|
+
}
|
|
57
|
+
// Otherwise, i.e. if it was obtained:
|
|
58
|
+
else {
|
|
59
|
+
const sourcePath = `${tmpDir}/nuVnu-source-${report.id}.html`;
|
|
60
|
+
// Save the source.
|
|
61
|
+
await fs.writeFile(sourcePath, sourceData.source);
|
|
62
|
+
const pageTypes = [['pageContent', pagePath], ['rawPage', sourcePath]];
|
|
63
|
+
// For each page type:
|
|
64
|
+
for (const page of pageTypes) {
|
|
65
|
+
let nuResult;
|
|
66
|
+
try {
|
|
67
|
+
// Get Nu Html Checker output on it.
|
|
68
|
+
const nuOutput = await vnu.check(['--format', 'json', '--stdout', page[1]]);
|
|
69
|
+
// Consider the JSON output to be the result.
|
|
70
|
+
nuResult = nuOutput;
|
|
71
|
+
}
|
|
72
|
+
// If any error was thrown:
|
|
73
|
+
catch (error) {
|
|
74
|
+
let errorMessage = error.message;
|
|
75
|
+
// If it was due to an incompatible Java version:
|
|
76
|
+
if (errorMessage.includes('Unsupported major.minor version')) {
|
|
77
|
+
// Revise the error messageand report this.
|
|
78
|
+
errorMessage = `Installed version of Java is incompatible. Details: ${errorMessage}`;
|
|
79
|
+
data.docTypes[page[0]].prevented = true;
|
|
80
|
+
data.docTypes[page[0]].error = errorMessage;
|
|
81
|
+
}
|
|
82
|
+
// Otherwise, i.e. if it was not due to an incompatible Java version:
|
|
83
|
+
else {
|
|
84
|
+
try {
|
|
85
|
+
// Treat the output as a JSON result reporting rule violations.
|
|
86
|
+
nuResult = JSON.parse(error.message);
|
|
87
|
+
// But, if parsing it as JSON fails:
|
|
88
|
+
} catch (error) {
|
|
89
|
+
// Report this.
|
|
90
|
+
data.docTypes[page[0]].prevented = true;
|
|
91
|
+
data.docTypes[page[0]].error = `Error getting result (${error.message.slice(0, 300)});`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Delete the temporary file.
|
|
96
|
+
await fs.unlink(page[1]);
|
|
97
|
+
// If a result with or without reported violations was obtained:
|
|
98
|
+
if (nuResult) {
|
|
99
|
+
// Delete left and right quotation marks and their erratic invalid replacements.
|
|
100
|
+
const nuResultClean = JSON.parse(JSON.stringify(nuResult).replace(/[\u{fffd}“”]/ug, ''));
|
|
101
|
+
result[page[0]] = nuResultClean;
|
|
102
|
+
// If there is a report and rules were specified:
|
|
103
|
+
if (! result[page[0]].error && rules && Array.isArray(rules) && rules.length) {
|
|
104
|
+
// Remove all messages except those specified.
|
|
105
|
+
result[page[0]].messages = result[page[0]].messages.filter(message => rules.some(rule => {
|
|
106
|
+
if (rule[0] === '=') {
|
|
107
|
+
return message.message === rule.slice(1);
|
|
108
|
+
}
|
|
109
|
+
else if (rule[0] === '~') {
|
|
110
|
+
return new RegExp(rule.slice(1)).test(message.message);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log(`ERROR: Invalid nuVal rule ${rule}`);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// If both page types prevented testing:
|
|
121
|
+
if (pageTypes.every(pageType => data.docTypes[pageType[0]].prevented)) {
|
|
122
|
+
// Report this.
|
|
123
|
+
data.prevented = true;
|
|
124
|
+
data.error = 'Both doc types prevented';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
data,
|
|
129
|
+
result
|
|
130
|
+
};
|
|
131
|
+
};
|