testaro 5.0.0 → 5.1.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/run.js +2 -2
- package/samples/scripts/tp12.json +162 -0
- package/tests/htmlcs.js +47 -35
package/package.json
CHANGED
package/run.js
CHANGED
|
@@ -37,7 +37,7 @@ const tests = {
|
|
|
37
37
|
focInd: 'focus indicators',
|
|
38
38
|
focOp: 'focusability and operability',
|
|
39
39
|
hover: 'hover-caused content additions',
|
|
40
|
-
htmlcs: 'HTML CodeSniffer WCAG 2.1
|
|
40
|
+
htmlcs: 'HTML CodeSniffer WCAG 2.1 AA ruleset',
|
|
41
41
|
ibm: 'IBM Accessibility Checker',
|
|
42
42
|
labClash: 'labeling inconsistencies',
|
|
43
43
|
linkUl: 'adjacent-link underlining',
|
|
@@ -560,7 +560,7 @@ const visit = async (act, page, isStrict) => {
|
|
|
560
560
|
// If the visit fails:
|
|
561
561
|
if (response === 'error') {
|
|
562
562
|
// Give up.
|
|
563
|
-
const errorMsg = `ERROR:
|
|
563
|
+
const errorMsg = `ERROR: Attempts to visit ${requestedURL} failed`;
|
|
564
564
|
console.log(errorMsg);
|
|
565
565
|
act.result = errorMsg;
|
|
566
566
|
await page.goto('about:blank')
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "tp12",
|
|
3
|
+
"what": "Alfa, Axe, HTML CodeSniffer, IBM, Tenon, WAVE, and 16 custom tests",
|
|
4
|
+
"strict": true,
|
|
5
|
+
"commands": [
|
|
6
|
+
{
|
|
7
|
+
"type": "launch",
|
|
8
|
+
"which": "webkit",
|
|
9
|
+
"what": "Webkit browser"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "url",
|
|
13
|
+
"which": "https://*",
|
|
14
|
+
"what": "any page"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "tenonRequest",
|
|
18
|
+
"id": "a",
|
|
19
|
+
"withNewContent": true,
|
|
20
|
+
"what": "Tenon API version 2 test request"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"type": "test",
|
|
24
|
+
"which": "motion",
|
|
25
|
+
"what": "spontaneous change of content; requires webkit",
|
|
26
|
+
"delay": 2500,
|
|
27
|
+
"interval": 2500,
|
|
28
|
+
"count": 5
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "launch",
|
|
32
|
+
"which": "chromium",
|
|
33
|
+
"what": "Chromium browser"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "url",
|
|
37
|
+
"which": "https://*",
|
|
38
|
+
"what": "any page"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "test",
|
|
42
|
+
"which": "bulk",
|
|
43
|
+
"what": "count of visible elements"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "test",
|
|
47
|
+
"which": "embAc",
|
|
48
|
+
"withItems": true,
|
|
49
|
+
"what": "active elements incorrectly embedded in each other"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"type": "test",
|
|
53
|
+
"which": "focAll",
|
|
54
|
+
"what": "Tab-focusability"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"type": "test",
|
|
58
|
+
"which": "focInd",
|
|
59
|
+
"revealAll": false,
|
|
60
|
+
"allowedDelay": 250,
|
|
61
|
+
"withItems": true,
|
|
62
|
+
"what": "focus indicators"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"type": "test",
|
|
66
|
+
"which": "focOp",
|
|
67
|
+
"withItems": true,
|
|
68
|
+
"what": "focusability and operability of elements"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"type": "test",
|
|
72
|
+
"which": "hover",
|
|
73
|
+
"headSize": 20,
|
|
74
|
+
"headSampleSize": 20,
|
|
75
|
+
"tailSampleSize": 15,
|
|
76
|
+
"withItems": true,
|
|
77
|
+
"what": "hover impacts"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"type": "test",
|
|
81
|
+
"which": "labClash",
|
|
82
|
+
"withItems": true,
|
|
83
|
+
"what": "unlabeled and mislabeled form controls"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"type": "test",
|
|
87
|
+
"which": "linkUl",
|
|
88
|
+
"withItems": true,
|
|
89
|
+
"what": "underlining of inline links"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"type": "test",
|
|
93
|
+
"which": "menuNav",
|
|
94
|
+
"withItems": true,
|
|
95
|
+
"what": "keyboard navigation within true-focus menus"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"type": "test",
|
|
99
|
+
"which": "radioSet",
|
|
100
|
+
"withItems": true,
|
|
101
|
+
"what": "grouping of radio buttons in fieldsets"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"type": "test",
|
|
105
|
+
"which": "role",
|
|
106
|
+
"what": "validity and necessity of role assignments"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"type": "test",
|
|
110
|
+
"which": "styleDiff",
|
|
111
|
+
"withItems": true,
|
|
112
|
+
"what": "style consistency of headings, buttons, and links"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"type": "test",
|
|
116
|
+
"which": "tabNav",
|
|
117
|
+
"withItems": true,
|
|
118
|
+
"what": "keyboard navigation within tab lists"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"type": "test",
|
|
122
|
+
"which": "zIndex",
|
|
123
|
+
"withItems": true,
|
|
124
|
+
"what": "elements with non-auto z indexes"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"type": "test",
|
|
128
|
+
"which": "alfa",
|
|
129
|
+
"what": "Siteimprove alfa"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "test",
|
|
133
|
+
"which": "axe",
|
|
134
|
+
"detailLevel": 2,
|
|
135
|
+
"rules": [],
|
|
136
|
+
"what": "Axe core, all rules"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"type": "test",
|
|
140
|
+
"which": "htmlcs",
|
|
141
|
+
"what": "HTML CodeSniffer"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"type": "test",
|
|
145
|
+
"which": "ibm",
|
|
146
|
+
"withItems": true,
|
|
147
|
+
"what": "IBM Accessibility Checker, with page content and again with URL"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"type": "test",
|
|
151
|
+
"which": "tenon",
|
|
152
|
+
"id": "a",
|
|
153
|
+
"what": "Tenon API version 2 result retrieval"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"type": "test",
|
|
157
|
+
"which": "wave",
|
|
158
|
+
"reportType": 4,
|
|
159
|
+
"what": "WAVE, report-type 4"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
package/tests/htmlcs.js
CHANGED
|
@@ -6,45 +6,57 @@
|
|
|
6
6
|
// FUNCTIONS
|
|
7
7
|
// Runs HTML CodeSniffer on the page.
|
|
8
8
|
exports.reporter = async page => {
|
|
9
|
+
const result = {};
|
|
9
10
|
await page.addScriptTag({
|
|
10
11
|
path: `${__dirname}/../htmlcs/HTMLCS.js`
|
|
12
|
+
})
|
|
13
|
+
.catch(error => {
|
|
14
|
+
console.log(`ERROR adding the htmlcs script to the page (${error.message})`);
|
|
15
|
+
result.prevented = true;
|
|
16
|
+
result.error = 'ERROR adding the htmlcs script to the page';
|
|
11
17
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Sort the issues by class and standard.
|
|
18
|
-
messageStrings.sort();
|
|
19
|
-
// Remove any duplicate issues.
|
|
20
|
-
messageStrings = [... new Set(messageStrings)];
|
|
21
|
-
// Initialize the result.
|
|
22
|
-
const result = {
|
|
23
|
-
Error: {},
|
|
24
|
-
Warning: {}
|
|
25
|
-
};
|
|
26
|
-
// For each issue:
|
|
27
|
-
messageStrings.forEach(string => {
|
|
28
|
-
const parts = string.split(/\|/g);
|
|
29
|
-
const partCount = parts.length;
|
|
30
|
-
if (partCount !== 6) {
|
|
31
|
-
console.log(`ERROR: Issue string ${string} has too few or too many parts`);
|
|
18
|
+
if (! result.prevented) {
|
|
19
|
+
let messageStrings = [];
|
|
20
|
+
for (const standard of ['WCAG2AA']) {
|
|
21
|
+
const nextIssues = await page.evaluate(standard => HTMLCS_RUNNER.run(standard), standard);
|
|
22
|
+
messageStrings.push(... nextIssues);
|
|
32
23
|
}
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
// Sort the issues by class and standard.
|
|
25
|
+
messageStrings.sort();
|
|
26
|
+
// Remove any duplicate issues.
|
|
27
|
+
messageStrings = [... new Set(messageStrings)];
|
|
28
|
+
// Initialize the result.
|
|
29
|
+
result.Error = {};
|
|
30
|
+
result.Warning = {};
|
|
31
|
+
// For each issue:
|
|
32
|
+
messageStrings.forEach(string => {
|
|
33
|
+
const parts = string.split(/\|/, 6);
|
|
34
|
+
const partCount = parts.length;
|
|
35
|
+
if (partCount < 6) {
|
|
36
|
+
console.log(`ERROR: Issue string ${string} has too few parts`);
|
|
41
37
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
// If it is an error or a warning (not a notice):
|
|
39
|
+
else if (['Error', 'Warning'].includes(parts[0])) {
|
|
40
|
+
/*
|
|
41
|
+
Add the issue to an issueClass.issueCode.description array in the result.
|
|
42
|
+
This saves space, because, although some descriptions are issue-specific, such as
|
|
43
|
+
descriptions that state the contrast ratio of an element, most descriptions are
|
|
44
|
+
generic, so typically many issues share a description.
|
|
45
|
+
*/
|
|
46
|
+
const issueCode = parts[1].replace(/^WCAG2|\.Principle\d\.Guideline[\d_]+/g, '');
|
|
47
|
+
if (! result[parts[0]][issueCode]) {
|
|
48
|
+
result[parts[0]][issueCode] = {};
|
|
49
|
+
}
|
|
50
|
+
if (! result[parts[0]][issueCode][parts[4]]) {
|
|
51
|
+
result[parts[0]][issueCode][parts[4]] = [];
|
|
52
|
+
}
|
|
53
|
+
result[parts[0]][issueCode][parts[4]].push({
|
|
54
|
+
tagName: parts[2],
|
|
55
|
+
id: parts[3],
|
|
56
|
+
code: parts[5]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
49
61
|
return {result};
|
|
50
62
|
};
|