testaro 12.4.2 → 12.5.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/package.json +1 -1
- package/tests/dupAtt.js +31 -14
- package/tests/nuVal.js +67 -74
package/package.json
CHANGED
package/tests/dupAtt.js
CHANGED
|
@@ -38,22 +38,39 @@ exports.reporter = async (page, withItems) => {
|
|
|
38
38
|
return {result: data};
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
// Change any spacing character sequences in it to single spaces.
|
|
42
|
+
rawPage = rawPage.replace(/\s+/g, ' ');
|
|
43
|
+
// Remove any escaped quotation marks from it.
|
|
44
|
+
rawPage = rawPage.replace(/\\"|\\'/g, '');
|
|
45
|
+
// Remove any quoted text from it.
|
|
46
|
+
rawPage = rawPage.replace(/"[^<>\r\n"]*"|'[^<>\r\n']*'/g, '');
|
|
47
|
+
// Remove any script code from it.
|
|
48
|
+
rawPage = rawPage.replace(/<(script [^<>]+)>.*?<\/script>/g, '$1');
|
|
49
|
+
// Remove any comments from it.
|
|
50
|
+
rawPage = rawPage.replace(/<!--.*?-->/g, '');
|
|
51
|
+
// Extract the opening tags of its elements.
|
|
52
|
+
let elements = rawPage.match(/<[a-zA-Z][^<>]+>/g);
|
|
53
|
+
// Delete their enclosing angle brackets and the values of any attributes in them.
|
|
54
|
+
elements = elements.map(el => el.replace(/^< *| *= *"[^"]*"|= *[^ ]+| *>$/g, ''));
|
|
46
55
|
// For each element:
|
|
47
56
|
elements.forEach(element => {
|
|
48
|
-
// Identify its attributes.
|
|
49
|
-
const
|
|
50
|
-
// If
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
// Identify its tag name and attributes.
|
|
58
|
+
const terms = element.split(' ');
|
|
59
|
+
// If it has 2 or more attributes:
|
|
60
|
+
if (terms.length > 2) {
|
|
61
|
+
// If any is duplicated:
|
|
62
|
+
const tagName = terms[0].toUpperCase();
|
|
63
|
+
const attributes = terms.slice(1);
|
|
64
|
+
const attSet = new Set(attributes);
|
|
65
|
+
if (attSet.size < attributes.length) {
|
|
66
|
+
// Add this to the data.
|
|
67
|
+
data.total++;
|
|
68
|
+
if (withItems) {
|
|
69
|
+
data.items.push({
|
|
70
|
+
tagName,
|
|
71
|
+
attributes
|
|
72
|
+
});
|
|
73
|
+
}
|
|
57
74
|
}
|
|
58
75
|
}
|
|
59
76
|
});
|
package/tests/nuVal.js
CHANGED
|
@@ -1,92 +1,85 @@
|
|
|
1
1
|
/*
|
|
2
2
|
nuVal
|
|
3
|
-
This test subjects a page to the Nu Html Checker
|
|
4
|
-
|
|
3
|
+
This test subjects a page and its source to the Nu Html Checker, thereby testing scripted
|
|
4
|
+
content found only in the loaded page and erroneous content before the browser corrects it.
|
|
5
|
+
The API erratically replaces left and right double quotation marks with invalid UTF-8, which
|
|
5
6
|
appears as 2 or 3 successive instances of the replacement character (U+fffd). Therefore, this
|
|
6
7
|
test removes all such quotation marks and the replacement character. That causes
|
|
7
8
|
'Bad value “” for' to become 'Bad value for'. Since the corruption of quotation marks is
|
|
8
9
|
erratic, no better solution is known.
|
|
9
10
|
*/
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
// ########## IMPORTS
|
|
13
|
+
|
|
14
|
+
// Module to make HTTP requests.
|
|
15
|
+
const fetch = require('node-fetch');
|
|
16
|
+
// Module to process files.
|
|
17
|
+
const fs = require('fs/promises');
|
|
18
|
+
|
|
19
|
+
// ########## FUNCTIONS
|
|
20
|
+
|
|
11
21
|
exports.reporter = async (page, messages) => {
|
|
22
|
+
// Get the browser-parsed page.
|
|
12
23
|
const pageContent = await page.content();
|
|
13
|
-
// Get the
|
|
14
|
-
const
|
|
24
|
+
// Get the page source.
|
|
25
|
+
const url = page.url();
|
|
26
|
+
const scheme = url.replace(/:.+/, '');
|
|
27
|
+
let rawPage;
|
|
28
|
+
if (scheme === 'file') {
|
|
29
|
+
const filePath = url.slice(7);
|
|
30
|
+
rawPage = await fs.readFile(filePath, 'utf8');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
15
33
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
/*
|
|
19
|
-
Alternatives (more timeout-prone): host=validator.nu; path=/?parser=html@out=json
|
|
20
|
-
That host crashes instead of ending with a fatal error.
|
|
21
|
-
*/
|
|
22
|
-
host: 'validator.w3.org',
|
|
23
|
-
path: '/nu/?parser=html&out=json',
|
|
24
|
-
method: 'POST',
|
|
25
|
-
headers: {
|
|
26
|
-
'User-Agent': 'Mozilla/5.0',
|
|
27
|
-
'Content-Type': 'text/html; charset=utf-8'
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
response => {
|
|
31
|
-
let report = '';
|
|
32
|
-
response.on('data', chunk => {
|
|
33
|
-
report += chunk;
|
|
34
|
-
});
|
|
35
|
-
// When the data arrive:
|
|
36
|
-
response.on('end', async () => {
|
|
37
|
-
try {
|
|
38
|
-
// Delete left and right quotation marks and their erratic invalid replacements.
|
|
39
|
-
const result = JSON.parse(report.replace(/[\u{fffd}“”]/ug, ''));
|
|
40
|
-
return resolve(result);
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
console.log(`ERROR: Validation failed (${error.message})`);
|
|
44
|
-
return resolve({
|
|
45
|
-
prevented: true,
|
|
46
|
-
error: error.message,
|
|
47
|
-
report
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
);
|
|
53
|
-
request.write(pageContent);
|
|
54
|
-
request.end();
|
|
55
|
-
request.on('error', error => {
|
|
56
|
-
console.log(error.message);
|
|
57
|
-
return resolve({
|
|
58
|
-
prevented: true,
|
|
59
|
-
error: error.message
|
|
60
|
-
});
|
|
61
|
-
});
|
|
34
|
+
const rawPageResponse = await fetch(url);
|
|
35
|
+
rawPage = await rawPageResponse.text();
|
|
62
36
|
}
|
|
63
37
|
catch(error) {
|
|
64
|
-
console.log(error.message);
|
|
65
|
-
return
|
|
38
|
+
console.log(`ERROR getting page for nuVal test (${error.message})`);
|
|
39
|
+
return {result: {
|
|
66
40
|
prevented: true,
|
|
67
|
-
error:
|
|
68
|
-
}
|
|
41
|
+
error: 'ERROR getting page for nuVal test'
|
|
42
|
+
}};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Get the data from Nu validations.
|
|
46
|
+
const fetchOptions = {
|
|
47
|
+
method: 'post',
|
|
48
|
+
headers: {
|
|
49
|
+
'User-Agent': 'Mozilla/5.0',
|
|
50
|
+
'Content-Type': 'text/html; charset=utf-8'
|
|
69
51
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
};
|
|
53
|
+
// More reliable service than validator.nu.
|
|
54
|
+
const nuURL = 'https://validator.w3.org/nu/?parser=html&out=json';
|
|
55
|
+
const data = {};
|
|
56
|
+
// For each page type:
|
|
57
|
+
for (const page of [['pageContent', pageContent], ['rawPage', rawPage]]) {
|
|
58
|
+
try {
|
|
59
|
+
// Get a Nu Html Checker report on it.
|
|
60
|
+
fetchOptions.body = page[1];
|
|
61
|
+
const nuResult = await fetch(nuURL, fetchOptions);
|
|
62
|
+
const nuData = await nuResult.json();
|
|
63
|
+
const nuDataClean = JSON.parse(JSON.stringify(nuData).replace(/[\u{fffd}“”]/ug, ''));
|
|
64
|
+
// Delete left and right quotation marks and their erratic invalid replacements.
|
|
65
|
+
data[page[0]] = nuDataClean;
|
|
66
|
+
// If there is a report and restrictions on the report messages were specified:
|
|
67
|
+
if (! data[page[0]].error && messages && Array.isArray(messages) && messages.length) {
|
|
68
|
+
// Remove all messages except those specified.
|
|
69
|
+
const messageSpecs = messages.map(messageSpec => messageSpec.split(':', 2));
|
|
70
|
+
data[page[0]].messages = data[page[0]].messages.filter(message => messageSpecs.some(
|
|
71
|
+
messageSpec => message.type === messageSpec[0]
|
|
72
|
+
&& message.message.startsWith(messageSpec[1])
|
|
73
|
+
));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.log(`ERROR: nuVal report validation failed (${error.message})`);
|
|
78
|
+
return {result: {
|
|
75
79
|
prevented: true,
|
|
76
|
-
error:
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
}, 1000 * timeLimit);
|
|
80
|
-
});
|
|
81
|
-
// Get the result, or an error report if nuVal timed out after 12 seconds.
|
|
82
|
-
const data = await Promise.race([dataPromise, timeoutPromise]);
|
|
83
|
-
// If there is a report and restrictions on the report messages were specified:
|
|
84
|
-
if (! data.error && messages && Array.isArray(messages) && messages.length) {
|
|
85
|
-
// Remove all messages except those specified.
|
|
86
|
-
const messageSpecs = messages.map(messageSpec => messageSpec.split(':', 2));
|
|
87
|
-
data.messages = data.messages.filter(message => messageSpecs.some(
|
|
88
|
-
messageSpec => message.type === messageSpec[0] && message.message.startsWith(messageSpec[1])
|
|
89
|
-
));
|
|
80
|
+
error: 'nuVal report validation failed',
|
|
81
|
+
}};
|
|
82
|
+
}
|
|
90
83
|
}
|
|
91
84
|
return {result: data};
|
|
92
85
|
};
|