testaro 14.3.0 → 14.4.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/README.md +9 -1
- package/actSpecs.js +1 -1
- package/call.js +1 -0
- package/package.json +1 -1
- package/run.js +35 -23
- package/standardize.js +133 -16
- package/testaro/allHidden.js +12 -0
- package/testaro/attVal.js +6 -0
- package/testaro/autocomplete.js +6 -2
- package/testaro/bulk.js +2 -0
- package/testaro/docType.js +2 -0
- package/testaro/dupAtt.js +10 -4
- package/testaro/embAc.js +6 -1
- package/testaro/filter.js +6 -1
- package/testaro/focAll.js +2 -0
- package/testaro/focInd.js +8 -1
- package/testaro/focOp.js +7 -3
- package/testaro/focVis.js +9 -2
- package/testaro/hover.js +6 -2
- package/testaro/labClash.js +7 -0
- package/testaro/linkTo.js +12 -5
- package/testaro/linkUl.js +20 -9
- package/testaro/menuNav.js +12 -4
- package/testaro/miniText.js +10 -2
- package/testaro/motion.js +5 -3
- package/testaro/nonTable.js +10 -3
- package/testaro/radioSet.js +10 -3
- package/testaro/role.js +8 -3
- package/testaro/styleDiff.js +11 -9
- package/testaro/tabNav.js +11 -2
- package/testaro/titledEl.js +6 -1
- package/testaro/zIndex.js +5 -3
package/testaro/focInd.js
CHANGED
|
@@ -67,6 +67,7 @@ exports.reporter = async (page, withItems, revealAll = false, allowedDelay = 250
|
|
|
67
67
|
if (withItems) {
|
|
68
68
|
const elementData = {
|
|
69
69
|
tagName,
|
|
70
|
+
id: element.id,
|
|
70
71
|
text: (element.textContent.trim() || element.outerHTML.trim()).replace(/\s+/g, ' ')
|
|
71
72
|
.slice(0, 100)
|
|
72
73
|
};
|
|
@@ -174,8 +175,10 @@ exports.reporter = async (page, withItems, revealAll = false, allowedDelay = 250
|
|
|
174
175
|
const qualifier = issueName === 'nonOutlinePresent' ? 'a non-outline' : 'no';
|
|
175
176
|
standardInstances.push({
|
|
176
177
|
issueID: `focInd-${issueName}`,
|
|
177
|
-
what:
|
|
178
|
+
what: `${item.tagName} element has ${qualifier} focus indicator`,
|
|
178
179
|
ordinalSeverity: issueName === 'nonOutlinePresent' ? 2 : 3,
|
|
180
|
+
tagName: item.tagName,
|
|
181
|
+
id: item.id,
|
|
179
182
|
location: {
|
|
180
183
|
doc: '',
|
|
181
184
|
type: '',
|
|
@@ -193,6 +196,8 @@ exports.reporter = async (page, withItems, revealAll = false, allowedDelay = 250
|
|
|
193
196
|
what: 'Elements have missing focus indicators',
|
|
194
197
|
count: types.indicatorMissing.total,
|
|
195
198
|
ordinalSeverity: 3,
|
|
199
|
+
tagName: '',
|
|
200
|
+
id: '',
|
|
196
201
|
location: {
|
|
197
202
|
doc: '',
|
|
198
203
|
type: '',
|
|
@@ -207,6 +212,8 @@ exports.reporter = async (page, withItems, revealAll = false, allowedDelay = 250
|
|
|
207
212
|
what: 'Elements have non-outline focus indicators',
|
|
208
213
|
count: types.nonOutlinePresent.total,
|
|
209
214
|
ordinalSeverity: 2,
|
|
215
|
+
tagName: '',
|
|
216
|
+
id: '',
|
|
210
217
|
location: {
|
|
211
218
|
doc: '',
|
|
212
219
|
type: '',
|
package/testaro/focOp.js
CHANGED
|
@@ -158,12 +158,12 @@ exports.reporter = async (page, withItems) => {
|
|
|
158
158
|
: 'is operable but not focusable';
|
|
159
159
|
const ordinalSeverity = issue === 'onlyFocusable' ? 2 : 3;
|
|
160
160
|
data.items[issue].forEach(item => {
|
|
161
|
-
const itemID = item.id ? ` (ID ${item.id})` : '';
|
|
162
|
-
const which = `${item.tagName}${itemID}`;
|
|
163
161
|
standardInstances.push({
|
|
164
162
|
issueID,
|
|
165
|
-
what:
|
|
163
|
+
what: `${item.tagName} element ${gripe}`,
|
|
166
164
|
ordinalSeverity,
|
|
165
|
+
tagName: item.tagName,
|
|
166
|
+
id: item.id,
|
|
167
167
|
location: {
|
|
168
168
|
doc: '',
|
|
169
169
|
type: '',
|
|
@@ -181,6 +181,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
181
181
|
what: 'Focusable elements are inoperable',
|
|
182
182
|
count: totals[2],
|
|
183
183
|
ordinalSeverity: 2,
|
|
184
|
+
tagName: '',
|
|
185
|
+
id: '',
|
|
184
186
|
location: {
|
|
185
187
|
doc: '',
|
|
186
188
|
type: '',
|
|
@@ -195,6 +197,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
195
197
|
what: 'Operable elements are nonfocusable',
|
|
196
198
|
count: totals[3],
|
|
197
199
|
ordinalSeverity: 3,
|
|
200
|
+
tagName: '',
|
|
201
|
+
id: '',
|
|
198
202
|
location: {
|
|
199
203
|
doc: '',
|
|
200
204
|
type: '',
|
package/testaro/focVis.js
CHANGED
|
@@ -14,7 +14,10 @@ exports.reporter = async (page, withItems) => {
|
|
|
14
14
|
links.forEach(link => {
|
|
15
15
|
link.focus();
|
|
16
16
|
if (link.offsetTop + link.offsetHeight <= 0 || link.offsetLeft + link.offsetWidth <= 0) {
|
|
17
|
-
badLinks.push(
|
|
17
|
+
badLinks.push({
|
|
18
|
+
id: link.id,
|
|
19
|
+
text: compact(link.textContent)
|
|
20
|
+
});
|
|
18
21
|
}
|
|
19
22
|
});
|
|
20
23
|
return badLinks;
|
|
@@ -33,12 +36,14 @@ exports.reporter = async (page, withItems) => {
|
|
|
33
36
|
issueID: 'focVis',
|
|
34
37
|
what: 'Visible link is above or to the left of the display',
|
|
35
38
|
ordinalSeverity: 2,
|
|
39
|
+
tagName: 'A',
|
|
40
|
+
id: item.id,
|
|
36
41
|
location: {
|
|
37
42
|
doc: '',
|
|
38
43
|
type: '',
|
|
39
44
|
spec: ''
|
|
40
45
|
},
|
|
41
|
-
excerpt: item
|
|
46
|
+
excerpt: item.text
|
|
42
47
|
});
|
|
43
48
|
});
|
|
44
49
|
}
|
|
@@ -48,6 +53,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
48
53
|
what: 'Visible links are above or to the left of the display',
|
|
49
54
|
count: data.total,
|
|
50
55
|
ordinalSeverity: 2,
|
|
56
|
+
tagName: 'A',
|
|
57
|
+
id: '',
|
|
51
58
|
location: {
|
|
52
59
|
doc: '',
|
|
53
60
|
type: '',
|
package/testaro/hover.js
CHANGED
|
@@ -269,6 +269,7 @@ const find = async (data, withItems, page, sample) => {
|
|
|
269
269
|
// Add them to the data.
|
|
270
270
|
data.items.impactTriggers.push({
|
|
271
271
|
tagName,
|
|
272
|
+
id: itemData.id,
|
|
272
273
|
text: await textOf(firstTrigger[0], 100),
|
|
273
274
|
additions,
|
|
274
275
|
removals,
|
|
@@ -404,18 +405,19 @@ exports.reporter = async (page, withItems, sampleSize = -1) => {
|
|
|
404
405
|
if (data.items) {
|
|
405
406
|
Object.keys(data.items).forEach(issue => {
|
|
406
407
|
data.items[issue].forEach(item => {
|
|
407
|
-
const itemID = item.id ? ` (ID ${item.id})` : '';
|
|
408
408
|
standardInstances.push({
|
|
409
409
|
issueID: `hover-${issue}`,
|
|
410
410
|
what: what[issue],
|
|
411
411
|
count: data.totals[issue],
|
|
412
412
|
ordinalSeverity: severity[issue],
|
|
413
|
+
tagName: item.tagName,
|
|
414
|
+
id: item.id,
|
|
413
415
|
location: {
|
|
414
416
|
doc: '',
|
|
415
417
|
type: '',
|
|
416
418
|
spec: ''
|
|
417
419
|
},
|
|
418
|
-
excerpt:
|
|
420
|
+
excerpt: item.text
|
|
419
421
|
});
|
|
420
422
|
});
|
|
421
423
|
});
|
|
@@ -426,6 +428,8 @@ exports.reporter = async (page, withItems, sampleSize = -1) => {
|
|
|
426
428
|
what: 'Hovering has unexpected impacts',
|
|
427
429
|
count: Object.values(data.totals).reduce((total, current) => total + current),
|
|
428
430
|
ordinalSeverity: totals.reduce((max, current, index) => current ? index : max, 0),
|
|
431
|
+
tagName: '',
|
|
432
|
+
id: '',
|
|
429
433
|
location: {
|
|
430
434
|
doc: '',
|
|
431
435
|
type: '',
|
package/testaro/labClash.js
CHANGED
|
@@ -140,6 +140,7 @@ exports.reporter = async (page, withItems) => {
|
|
|
140
140
|
data.items.mislabeled.push({
|
|
141
141
|
index,
|
|
142
142
|
tagName: labelee.tagName,
|
|
143
|
+
id: labelee.id,
|
|
143
144
|
type: labelee.type,
|
|
144
145
|
labelTypes,
|
|
145
146
|
texts
|
|
@@ -166,6 +167,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
166
167
|
issueID: `labClash-${issue}`,
|
|
167
168
|
what: `Element ${item.tagName} ${diagnosis}`,
|
|
168
169
|
ordinalSeverity: issue === 'mislabeled' ? 2 : 3,
|
|
170
|
+
tagName: item.tagName,
|
|
171
|
+
id: item.id,
|
|
169
172
|
location: {
|
|
170
173
|
doc: '',
|
|
171
174
|
type: '',
|
|
@@ -183,6 +186,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
183
186
|
what: 'Element labels are missing',
|
|
184
187
|
count: data.totals.unlabeled,
|
|
185
188
|
ordinalSeverity: 3,
|
|
189
|
+
tagName: '',
|
|
190
|
+
id: '',
|
|
186
191
|
location: {
|
|
187
192
|
doc: '',
|
|
188
193
|
type: '',
|
|
@@ -197,6 +202,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
197
202
|
what: 'Element labels are conflicting',
|
|
198
203
|
count: data.totals.mislabeled,
|
|
199
204
|
ordinalSeverity: 2,
|
|
205
|
+
tagName: '',
|
|
206
|
+
id: '',
|
|
200
207
|
location: {
|
|
201
208
|
doc: '',
|
|
202
209
|
type: '',
|
package/testaro/linkTo.js
CHANGED
|
@@ -5,34 +5,39 @@
|
|
|
5
5
|
*/
|
|
6
6
|
exports.reporter = async (page, withItems) => {
|
|
7
7
|
// Identify the visible links without href attributes.
|
|
8
|
-
const
|
|
8
|
+
const badLinkData = await page.$$eval(
|
|
9
9
|
'a:not([href]):visible',
|
|
10
10
|
badLinks => {
|
|
11
11
|
// FUNCTION DEFINITION START
|
|
12
12
|
// Returns a space-minimized copy of a string.
|
|
13
13
|
const compact = string => string.replace(/[\t\n]/g, '').replace(/\s{2,}/g, ' ').trim();
|
|
14
14
|
// FUNCTION DEFINITION END
|
|
15
|
-
return badLinks.map(link =>
|
|
15
|
+
return badLinks.map(link => ({
|
|
16
|
+
id: link.id,
|
|
17
|
+
text: compact(link.textContent)
|
|
18
|
+
}));
|
|
16
19
|
}
|
|
17
20
|
);
|
|
18
21
|
const data = {
|
|
19
|
-
total:
|
|
22
|
+
total: badLinkData.length
|
|
20
23
|
};
|
|
21
24
|
const totals = [0, 0, data.total, 0];
|
|
22
25
|
const standardInstances = [];
|
|
23
26
|
if (withItems) {
|
|
24
|
-
data.items =
|
|
27
|
+
data.items = badLinkData;
|
|
25
28
|
data.items.forEach(item => {
|
|
26
29
|
standardInstances.push({
|
|
27
30
|
issueID: 'linkTo',
|
|
28
31
|
what: 'Element a has no href attribute',
|
|
29
32
|
ordinalSeverity: 2,
|
|
33
|
+
tagName: 'A',
|
|
34
|
+
id: item.id,
|
|
30
35
|
location: {
|
|
31
36
|
doc: '',
|
|
32
37
|
type: '',
|
|
33
38
|
spec: ''
|
|
34
39
|
},
|
|
35
|
-
excerpt: item
|
|
40
|
+
excerpt: item.text
|
|
36
41
|
});
|
|
37
42
|
});
|
|
38
43
|
}
|
|
@@ -42,6 +47,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
42
47
|
what: 'Links are missing href attributes',
|
|
43
48
|
count: data.total,
|
|
44
49
|
ordinalSeverity: 2,
|
|
50
|
+
tagName: 'A',
|
|
51
|
+
id: '',
|
|
45
52
|
location: {
|
|
46
53
|
doc: '',
|
|
47
54
|
type: '',
|
package/testaro/linkUl.js
CHANGED
|
@@ -25,25 +25,32 @@ exports.reporter = async (page, withItems) => {
|
|
|
25
25
|
const adjacentLinks = linkTypes.adjacent;
|
|
26
26
|
const adjacentLinkCount = adjacentLinks.length;
|
|
27
27
|
let underlined = 0;
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const ulAdjacentLinkData = [];
|
|
29
|
+
const nulAdjacentLinkData = [];
|
|
30
30
|
// For each of them:
|
|
31
31
|
adjacentLinks.forEach(link => {
|
|
32
32
|
// Identify the text of the link if itemization is required.
|
|
33
|
+
const id = link.id;
|
|
33
34
|
const text = withItems ? compact(link.textContent) || compact(link.outerHTML) : '';
|
|
34
35
|
// If it is underlined:
|
|
35
36
|
if (window.getComputedStyle(link).textDecorationLine === 'underline') {
|
|
36
37
|
// Increment the count of underlined inline links.
|
|
37
38
|
underlined++;
|
|
38
|
-
// If required, add its
|
|
39
|
+
// If required, add its data to the array of their data.
|
|
39
40
|
if (withItems) {
|
|
40
|
-
|
|
41
|
+
ulAdjacentLinkData.push({
|
|
42
|
+
id,
|
|
43
|
+
text
|
|
44
|
+
});
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
// Otherwise, if it is not underlined and itemization is required:
|
|
44
48
|
else if (withItems) {
|
|
45
49
|
// Add its text to the array of texts of non-underlined inline links.
|
|
46
|
-
|
|
50
|
+
nulAdjacentLinkData.push({
|
|
51
|
+
id,
|
|
52
|
+
text
|
|
53
|
+
});
|
|
47
54
|
}
|
|
48
55
|
});
|
|
49
56
|
// Get the percentage of underlined links among all inline links.
|
|
@@ -62,8 +69,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
62
69
|
};
|
|
63
70
|
if (withItems) {
|
|
64
71
|
data.items = {
|
|
65
|
-
underlined:
|
|
66
|
-
notUnderlined:
|
|
72
|
+
underlined: ulAdjacentLinkData,
|
|
73
|
+
notUnderlined: nulAdjacentLinkData
|
|
67
74
|
};
|
|
68
75
|
}
|
|
69
76
|
const {adjacent} = data.totals;
|
|
@@ -73,14 +80,16 @@ exports.reporter = async (page, withItems) => {
|
|
|
73
80
|
data.items.notUnderlined.forEach(item => {
|
|
74
81
|
standardInstances.push({
|
|
75
82
|
issueID: 'linkUl',
|
|
76
|
-
what: '
|
|
83
|
+
what: 'Link is inline but has no underline',
|
|
77
84
|
ordinalSeverity: 1,
|
|
85
|
+
tagName: 'A',
|
|
86
|
+
id: item.id,
|
|
78
87
|
location: {
|
|
79
88
|
doc: '',
|
|
80
89
|
type: '',
|
|
81
90
|
spec: ''
|
|
82
91
|
},
|
|
83
|
-
excerpt: item
|
|
92
|
+
excerpt: item.text
|
|
84
93
|
});
|
|
85
94
|
});
|
|
86
95
|
}
|
|
@@ -90,6 +99,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
90
99
|
what: 'Inline links are missing underlines',
|
|
91
100
|
count: adjacent.total - adjacent.underlined,
|
|
92
101
|
ordinalSeverity: 1,
|
|
102
|
+
tagName: 'A',
|
|
103
|
+
id: '',
|
|
93
104
|
location: {
|
|
94
105
|
doc: '',
|
|
95
106
|
type: '',
|
package/testaro/menuNav.js
CHANGED
|
@@ -166,7 +166,12 @@ exports.reporter = async (page, withItems) => {
|
|
|
166
166
|
// If itemization is required:
|
|
167
167
|
if (withItems) {
|
|
168
168
|
// Initialize a report on the menu item.
|
|
169
|
-
|
|
169
|
+
const identifiers = await page.evaluate(element => ({
|
|
170
|
+
tagName: element.tagName,
|
|
171
|
+
id: element.id
|
|
172
|
+
}), currentItem);
|
|
173
|
+
itemData.tagName = identifiers.tagName;
|
|
174
|
+
itemData.id = identifiers.id;
|
|
170
175
|
itemData.text = await allText(page, currentItem);
|
|
171
176
|
itemData.navigationErrors = [];
|
|
172
177
|
}
|
|
@@ -271,16 +276,17 @@ exports.reporter = async (page, withItems) => {
|
|
|
271
276
|
data.menuItems.incorrect.forEach(item => {
|
|
272
277
|
standardInstances.push({
|
|
273
278
|
issueID: 'menuNav',
|
|
274
|
-
what:
|
|
275
|
-
`Menu item ${item.tagName} responds nonstandardly to ${item.navigationErrors.join(', ')}`,
|
|
279
|
+
what: `Menu item responds nonstandardly to ${item.navigationErrors.join(', ')}`,
|
|
276
280
|
count: item.navigationErrors.length,
|
|
277
281
|
ordinalSeverity: 1,
|
|
282
|
+
tagName: item.tagName,
|
|
283
|
+
id: item.id,
|
|
278
284
|
location: {
|
|
279
285
|
doc: '',
|
|
280
286
|
type: '',
|
|
281
287
|
spec: ''
|
|
282
288
|
},
|
|
283
|
-
excerpt:
|
|
289
|
+
excerpt: item.text
|
|
284
290
|
});
|
|
285
291
|
});
|
|
286
292
|
}
|
|
@@ -290,6 +296,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
290
296
|
what: 'Menus and menu items have nonstandard navigation',
|
|
291
297
|
count: data.totals.navigations.all.incorrect,
|
|
292
298
|
ordinalSeverity: 1,
|
|
299
|
+
tagName: '',
|
|
300
|
+
id: '',
|
|
293
301
|
location: {
|
|
294
302
|
doc: '',
|
|
295
303
|
type: '',
|
package/testaro/miniText.js
CHANGED
|
@@ -30,7 +30,11 @@ exports.reporter = async (page, withItems) => {
|
|
|
30
30
|
if (pixels < 11) {
|
|
31
31
|
textParent.childNodes.forEach(node => {
|
|
32
32
|
if (node.nodeType === 3 && compact(node.textContent)) {
|
|
33
|
-
miniTexts.push(
|
|
33
|
+
miniTexts.push({
|
|
34
|
+
tagName: textParent.tagName,
|
|
35
|
+
id: textParent.id || '',
|
|
36
|
+
text: compact(node.textContent)
|
|
37
|
+
});
|
|
34
38
|
}
|
|
35
39
|
});
|
|
36
40
|
}
|
|
@@ -49,12 +53,14 @@ exports.reporter = async (page, withItems) => {
|
|
|
49
53
|
issueID: 'miniText',
|
|
50
54
|
what: 'Text font is smaller than 11 pixels',
|
|
51
55
|
ordinalSeverity: 2,
|
|
56
|
+
tagName: text.tagName,
|
|
57
|
+
id: text.id,
|
|
52
58
|
location: {
|
|
53
59
|
doc: '',
|
|
54
60
|
type: '',
|
|
55
61
|
spec: ''
|
|
56
62
|
},
|
|
57
|
-
excerpt: text
|
|
63
|
+
excerpt: text.text
|
|
58
64
|
});
|
|
59
65
|
});
|
|
60
66
|
}
|
|
@@ -64,6 +70,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
64
70
|
what: 'Texts have fonts smaller than 11 pixels',
|
|
65
71
|
count: data.total,
|
|
66
72
|
ordinalSeverity: 2,
|
|
73
|
+
tagName: '',
|
|
74
|
+
id: '',
|
|
67
75
|
location: {
|
|
68
76
|
doc: '',
|
|
69
77
|
type: '',
|
package/testaro/motion.js
CHANGED
|
@@ -98,13 +98,13 @@ exports.reporter = async (page, withItems, delay = 2500, interval = 2500, count
|
|
|
98
98
|
pixelChanges.reduce((count, change) => count + (change ? 1 : 0), 0) / pixelChanges.length, 2
|
|
99
99
|
);
|
|
100
100
|
// Return the result.
|
|
101
|
-
const
|
|
101
|
+
const rawCount = 2 * (meanLocalRatio - 1)
|
|
102
102
|
+ maxLocalRatio - 1
|
|
103
103
|
+ globalRatio - 1
|
|
104
104
|
+ meanPixelChange / 10000
|
|
105
105
|
+ maxPixelChange / 25000
|
|
106
|
-
+ 3 * changeFrequency
|
|
107
|
-
|
|
106
|
+
+ 3 * changeFrequency;
|
|
107
|
+
const count = rawCount ? Math.round(rawCount) : 0;
|
|
108
108
|
return {
|
|
109
109
|
data: {
|
|
110
110
|
bytes,
|
|
@@ -128,6 +128,8 @@ exports.reporter = async (page, withItems, delay = 2500, interval = 2500, count
|
|
|
128
128
|
what: 'Content moves or changes without user request',
|
|
129
129
|
count,
|
|
130
130
|
ordinalSeverity: 2,
|
|
131
|
+
tagName: '',
|
|
132
|
+
id: '',
|
|
131
133
|
location: {
|
|
132
134
|
doc: '',
|
|
133
135
|
type: '',
|
package/testaro/nonTable.js
CHANGED
|
@@ -13,7 +13,10 @@ exports.reporter = async (page, withItems) => {
|
|
|
13
13
|
const compact = string => string.replace(/[\t\n]/g, '').replace(/\s{2,}/g, ' ').trim();
|
|
14
14
|
// Adds the first 100 characters of the code of a pseudotable to the array of pseudotable texts.
|
|
15
15
|
const addBad = table => {
|
|
16
|
-
badTableTexts.push(
|
|
16
|
+
badTableTexts.push({
|
|
17
|
+
id: table.id,
|
|
18
|
+
text: compact(table.outerHTML).slice(0, 100)
|
|
19
|
+
});
|
|
17
20
|
};
|
|
18
21
|
// FUNCTION DEFINITIONS END
|
|
19
22
|
// For each table on the page:
|
|
@@ -63,17 +66,19 @@ exports.reporter = async (page, withItems) => {
|
|
|
63
66
|
const standardInstances = [];
|
|
64
67
|
if (withItems) {
|
|
65
68
|
data.items = badTableTexts;
|
|
66
|
-
data.items.forEach(
|
|
69
|
+
data.items.forEach(item => {
|
|
67
70
|
standardInstances.push({
|
|
68
71
|
issueID: 'nonTable',
|
|
69
72
|
what: 'Table is misused to arrange content',
|
|
70
73
|
ordinalSeverity: 0,
|
|
74
|
+
tagName: 'TABLE',
|
|
75
|
+
id: item.id,
|
|
71
76
|
location: {
|
|
72
77
|
doc: '',
|
|
73
78
|
type: '',
|
|
74
79
|
spec: ''
|
|
75
80
|
},
|
|
76
|
-
excerpt: text
|
|
81
|
+
excerpt: item.text
|
|
77
82
|
});
|
|
78
83
|
});
|
|
79
84
|
}
|
|
@@ -83,6 +88,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
83
88
|
what: 'Tables are misused to arrange content',
|
|
84
89
|
count: data.total,
|
|
85
90
|
ordinalSeverity: 0,
|
|
91
|
+
tagName: 'TABLE',
|
|
92
|
+
id: '',
|
|
86
93
|
location: {
|
|
87
94
|
doc: '',
|
|
88
95
|
type: '',
|
package/testaro/radioSet.js
CHANGED
|
@@ -82,18 +82,23 @@ exports.reporter = async (page, withItems) => {
|
|
|
82
82
|
const nonSetRadios = allRadios.filter(radio => ! setRadios.includes(radio));
|
|
83
83
|
const items = data.items;
|
|
84
84
|
items.inSet = setRadios.map(radio => textOf(radio));
|
|
85
|
-
items.notInSet = nonSetRadios.map(radio =>
|
|
86
|
-
|
|
85
|
+
items.notInSet = nonSetRadios.map(radio => ({
|
|
86
|
+
id: radio.id,
|
|
87
|
+
text: textOf(radio)
|
|
88
|
+
}));
|
|
89
|
+
items.notInSet.forEach(item => {
|
|
87
90
|
standardInstances.push({
|
|
88
91
|
issueID: 'radioSet',
|
|
89
92
|
what: 'Radio button and its peers are not in a fieldset with a legend',
|
|
90
93
|
ordinalSeverity: 2,
|
|
94
|
+
tagName: 'INPUT',
|
|
95
|
+
id: item.id,
|
|
91
96
|
location: {
|
|
92
97
|
doc: '',
|
|
93
98
|
type: '',
|
|
94
99
|
spec: ''
|
|
95
100
|
},
|
|
96
|
-
excerpt: text
|
|
101
|
+
excerpt: item.text
|
|
97
102
|
});
|
|
98
103
|
});
|
|
99
104
|
}
|
|
@@ -103,6 +108,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
103
108
|
what: 'Radio buttons are not validly grouped in fieldsets with legends',
|
|
104
109
|
count: loneRadios,
|
|
105
110
|
ordinalSeverity: 2,
|
|
111
|
+
tagName: 'INPUT',
|
|
112
|
+
id: '',
|
|
106
113
|
location: {
|
|
107
114
|
doc: '',
|
|
108
115
|
type: '',
|
package/testaro/role.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.reporter = async page => await page.$eval('body', body => {
|
|
|
15
15
|
|
|
16
16
|
// CONSTANTS
|
|
17
17
|
|
|
18
|
+
// All roles implicit in HTML elements.
|
|
18
19
|
const badRoles = new Set([
|
|
19
20
|
'article',
|
|
20
21
|
'banner',
|
|
@@ -52,7 +53,7 @@ exports.reporter = async page => await page.$eval('body', body => {
|
|
|
52
53
|
'term',
|
|
53
54
|
'textbox'
|
|
54
55
|
]);
|
|
55
|
-
// All non-abstract roles
|
|
56
|
+
// All non-abstract roles.
|
|
56
57
|
const goodRoles = new Set([
|
|
57
58
|
'alert',
|
|
58
59
|
'alertdialog',
|
|
@@ -410,7 +411,7 @@ exports.reporter = async page => await page.$eval('body', body => {
|
|
|
410
411
|
|
|
411
412
|
// OPERATION
|
|
412
413
|
|
|
413
|
-
// Remove the
|
|
414
|
+
// Remove the element-implicit roles from the non-abstract roles.
|
|
414
415
|
goodRoles.forEach(role => {
|
|
415
416
|
if (badRoles.has(role)) {
|
|
416
417
|
goodRoles.delete(role);
|
|
@@ -489,6 +490,8 @@ exports.reporter = async page => await page.$eval('body', body => {
|
|
|
489
490
|
what: `${tagName} elements have redundant explicit role ${role} (count: ${redCount})`,
|
|
490
491
|
count: redCount,
|
|
491
492
|
ordinalSeverity: 1,
|
|
493
|
+
tagName,
|
|
494
|
+
id: '',
|
|
492
495
|
location: {
|
|
493
496
|
doc: '',
|
|
494
497
|
type: '',
|
|
@@ -502,9 +505,11 @@ exports.reporter = async page => await page.$eval('body', body => {
|
|
|
502
505
|
standardInstances.push({
|
|
503
506
|
issueID: 'role-bad',
|
|
504
507
|
what:
|
|
505
|
-
|
|
508
|
+
`${tagName} elements have invalid or native-replaceable explicit role ${role} (count: ${badCount})`,
|
|
506
509
|
count: badCount,
|
|
507
510
|
ordinalSeverity: 3,
|
|
511
|
+
tagName,
|
|
512
|
+
id: '',
|
|
508
513
|
location: {
|
|
509
514
|
doc: '',
|
|
510
515
|
type: '',
|
package/testaro/styleDiff.js
CHANGED
|
@@ -155,15 +155,15 @@ exports.reporter = async (page, withItems) => {
|
|
|
155
155
|
const totals = [0, 0, 0, 0];
|
|
156
156
|
const standardInstances = [];
|
|
157
157
|
const elementData = {
|
|
158
|
-
adjacentLink: [0, 'In-line links'],
|
|
159
|
-
listLink: [1, 'Links in columns'],
|
|
160
|
-
button: [2, 'Buttons'],
|
|
161
|
-
h1: [3, 'Level-1 headings'],
|
|
162
|
-
h2: [3, 'Level-2 headings'],
|
|
163
|
-
h3: [3, 'Level-3 headings'],
|
|
164
|
-
h4: [3, 'Level-4 headings'],
|
|
165
|
-
h5: [3, 'Level-5 headings'],
|
|
166
|
-
h6: [3, 'Level-6 headings'],
|
|
158
|
+
adjacentLink: [0, 'In-line links', 'A'],
|
|
159
|
+
listLink: [1, 'Links in columns', 'A'],
|
|
160
|
+
button: [2, 'Buttons', 'BUTTON'],
|
|
161
|
+
h1: [3, 'Level-1 headings', 'H1'],
|
|
162
|
+
h2: [3, 'Level-2 headings', 'H2'],
|
|
163
|
+
h3: [3, 'Level-3 headings', 'H3'],
|
|
164
|
+
h4: [3, 'Level-4 headings', 'H4'],
|
|
165
|
+
h5: [3, 'Level-5 headings', 'H5'],
|
|
166
|
+
h6: [3, 'Level-6 headings', 'H6'],
|
|
167
167
|
};
|
|
168
168
|
Object.keys(elementData).forEach(elementName => {
|
|
169
169
|
const elementTotal = data.totals[elementName];
|
|
@@ -178,6 +178,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
178
178
|
what: `${currentData[1]} have ${elementSubtotals.length} different styles`,
|
|
179
179
|
count: extraCount,
|
|
180
180
|
ordinalSeverity: severity,
|
|
181
|
+
tagName: currentData[2],
|
|
182
|
+
id: '',
|
|
181
183
|
location: {
|
|
182
184
|
doc: '',
|
|
183
185
|
type: '',
|
package/testaro/tabNav.js
CHANGED
|
@@ -220,7 +220,10 @@ exports.reporter = async (page, withItems) => {
|
|
|
220
220
|
if (withItems) {
|
|
221
221
|
let found = true;
|
|
222
222
|
// Initialize a report on the element.
|
|
223
|
-
|
|
223
|
+
const moreItemData = await page.evaluate(element => ({
|
|
224
|
+
tagName: element.tagName,
|
|
225
|
+
id: element.id
|
|
226
|
+
}), currentTab)
|
|
224
227
|
.catch(error => {
|
|
225
228
|
console.log(`ERROR: could not get tag name (${error.message})`);
|
|
226
229
|
found = false;
|
|
@@ -228,6 +231,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
228
231
|
return 'ERROR: not found';
|
|
229
232
|
});
|
|
230
233
|
if (found) {
|
|
234
|
+
itemData.tagName = moreItemData.tagName;
|
|
235
|
+
itemData.id = moreItemData.id;
|
|
231
236
|
itemData.text = await allText(page, currentTab);
|
|
232
237
|
itemData.navigationErrors = [];
|
|
233
238
|
}
|
|
@@ -339,12 +344,14 @@ exports.reporter = async (page, withItems) => {
|
|
|
339
344
|
`${item.tagName} element responds nonstandardly to ${item.navigationErrors.join(', ')}`,
|
|
340
345
|
count: item.navigationErrors.length,
|
|
341
346
|
ordinalSeverity: 1,
|
|
347
|
+
tagName: item.tagName,
|
|
348
|
+
id: item.id,
|
|
342
349
|
location: {
|
|
343
350
|
doc: '',
|
|
344
351
|
type: '',
|
|
345
352
|
spec: ''
|
|
346
353
|
},
|
|
347
|
-
excerpt:
|
|
354
|
+
excerpt: item.text
|
|
348
355
|
});
|
|
349
356
|
});
|
|
350
357
|
}
|
|
@@ -354,6 +361,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
354
361
|
what: 'Tablists have nonstandard navigation',
|
|
355
362
|
count: data.totals.navigations.all.incorrect,
|
|
356
363
|
ordinalSeverity: 1,
|
|
364
|
+
tagName: '',
|
|
365
|
+
id: '',
|
|
357
366
|
location: {
|
|
358
367
|
doc: '',
|
|
359
368
|
type: '',
|
package/testaro/titledEl.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.reporter = async (page, withItems) => {
|
|
|
16
16
|
// FUNCTION DEFINITION END
|
|
17
17
|
return badTitleElements.map(element => ({
|
|
18
18
|
tagName: element.tagName,
|
|
19
|
+
id: element.id,
|
|
19
20
|
text: compact(element.textContent),
|
|
20
21
|
title: compact(element.title)
|
|
21
22
|
}));
|
|
@@ -30,8 +31,10 @@ exports.reporter = async (page, withItems) => {
|
|
|
30
31
|
badTitleElements.forEach(element => {
|
|
31
32
|
standardInstances.push({
|
|
32
33
|
issueID: 'titledEl',
|
|
33
|
-
what:
|
|
34
|
+
what: `${element.tagName} element has a title attribute`,
|
|
34
35
|
ordinalSeverity: 2,
|
|
36
|
+
tagName: element.tagName,
|
|
37
|
+
id: element.id,
|
|
35
38
|
location: {
|
|
36
39
|
doc: '',
|
|
37
40
|
type: '',
|
|
@@ -47,6 +50,8 @@ exports.reporter = async (page, withItems) => {
|
|
|
47
50
|
what: 'Ineligible elements have title attributes',
|
|
48
51
|
count: data.total,
|
|
49
52
|
ordinalSeverity: 2,
|
|
53
|
+
tagName: '',
|
|
54
|
+
id: '',
|
|
50
55
|
location: {
|
|
51
56
|
doc: '',
|
|
52
57
|
type: '',
|