testaro 14.2.6 → 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.
@@ -20,7 +20,7 @@ const addFailure = async (withItems, input, inputText, autocomplete, data) => {
20
20
  // If itemization is required:
21
21
  if (withItems) {
22
22
  // Add the item to the data.
23
- data.items.push([autocomplete, inputText.slice(0, 100)]);
23
+ data.items.push([autocomplete, input.id || '', inputText.slice(0, 100)]);
24
24
  }
25
25
  }
26
26
  };
@@ -77,12 +77,14 @@ exports.reporter = async (page, withItems) => {
77
77
  issueID: `autocomplete-${item[0]}`,
78
78
  what: `Input is missing the required autocomplete attribute with value ${item[0]}`,
79
79
  ordinalSeverity: 2,
80
+ tagName: 'INPUT',
81
+ id: item[1] || '',
80
82
  location: {
81
83
  doc: '',
82
84
  type: '',
83
85
  spec: ''
84
86
  },
85
- excerpt: item[1]
87
+ excerpt: item[2]
86
88
  });
87
89
  });
88
90
  }
@@ -91,6 +93,8 @@ exports.reporter = async (page, withItems) => {
91
93
  issueID: 'autocomplete',
92
94
  what: 'Inputs are missing required autocomplete attributes',
93
95
  ordinalSeverity: 2,
96
+ tagName: '',
97
+ id: '',
94
98
  location: {
95
99
  doc: '',
96
100
  type: '',
package/testaro/bulk.js CHANGED
@@ -18,13 +18,17 @@ exports.reporter = async page => {
18
18
  });
19
19
  const visibleElements = await page.$$('body :visible');
20
20
  data.visibleElements = visibleElements.length;
21
+ const count = Math.round(data.visibleElements / 400);
21
22
  return {
22
23
  data,
23
- totals: [Math.round(data.visibleElements / 400), 0, 0, 0],
24
+ totals: [count, 0, 0, 0],
24
25
  standardInstances: data.visibleElements < 200 ? [] : [{
25
26
  issueID: 'bulk',
26
27
  what: 'Page contains a large number of visible elements',
28
+ count,
27
29
  ordinalSeverity: 0,
30
+ tagName: 'HTML',
31
+ id: '',
28
32
  location: {
29
33
  doc: '',
30
34
  type: '',
@@ -17,6 +17,8 @@ exports.reporter = async page => {
17
17
  issueID: 'docType',
18
18
  what: 'Document has no standard HTML doctype preamble',
19
19
  ordinalSeverity: 3,
20
+ tagName: 'HTML',
21
+ id: '',
20
22
  location: {
21
23
  doc: '',
22
24
  type: '',
package/testaro/dupAtt.js CHANGED
@@ -53,11 +53,12 @@ exports.reporter = async (page, withItems) => {
53
53
  // Extract the opening tags of its elements.
54
54
  let elements = rawPage.match(/<[a-zA-Z][^<>]+>/g);
55
55
  // Delete their enclosing angle brackets and the values of any attributes in them.
56
- elements = elements.map(el => el.replace(/^< *|=[^ ]*| *>$/g, ''));
56
+ const elementsWithVals = elements.map(el => el.replace(/^< *| *>$/g, ''));
57
+ const elementsWithoutVals = elementsWithVals.map(el => el.replace(/^ *|=[^ ]*$/g, ''));
57
58
  // For each element:
58
- elements.forEach(element => {
59
+ elementsWithoutVals.forEach((elementWithoutVals, index) => {
59
60
  // Identify its tag name and attributes.
60
- const terms = element.split(' ');
61
+ const terms = elementWithoutVals.split(' ');
61
62
  // If it has 2 or more attributes:
62
63
  if (terms.length > 2) {
63
64
  // If any is duplicated:
@@ -65,11 +66,14 @@ exports.reporter = async (page, withItems) => {
65
66
  const attributes = terms.slice(1);
66
67
  const attSet = new Set(attributes);
67
68
  if (attSet.size < attributes.length) {
68
- // Add this to the data.
69
+ // Add it to the data.
69
70
  data.total++;
70
71
  if (withItems) {
71
72
  data.items.push({
72
73
  tagName,
74
+ id: terms.includes('id')
75
+ ? elementsWithVals[index].replace(/^.+id=/, '').replace(/ .*$/, '')
76
+ : '',
73
77
  attributes
74
78
  });
75
79
  }
@@ -83,6 +87,8 @@ exports.reporter = async (page, withItems) => {
83
87
  issueID: 'dupAtt',
84
88
  what: `Element ${item.tagName} has 2 attributes with the same name`,
85
89
  ordinalSeverity: 2,
90
+ tagName: item.tagName,
91
+ id: item.id,
86
92
  location: {
87
93
  doc: '',
88
94
  type: '',
package/testaro/embAc.js CHANGED
@@ -32,6 +32,7 @@ exports.reporter = async (page, withItems) => await page.$$eval(
32
32
  }
33
33
  items.push({
34
34
  embeddedElement: bad.tagName,
35
+ embeddedID: bad.id,
35
36
  excerpt: compact(container.outerHTML)
36
37
  });
37
38
  }
@@ -45,8 +46,10 @@ exports.reporter = async (page, withItems) => await page.$$eval(
45
46
  items.forEach(item => {
46
47
  standardInstances.push({
47
48
  issueID: `embAc-${item.embeddedElement}`,
48
- what: `Element ${item.embeddedElement} is embedded in a link or button`,
49
+ what: `${item.embeddedElement} element is embedded in a link or button`,
49
50
  ordinalSeverity: 2,
51
+ tagName: item.embeddedElement,
52
+ id: item.id,
50
53
  location: {
51
54
  doc: '',
52
55
  type: '',
@@ -60,7 +63,10 @@ exports.reporter = async (page, withItems) => await page.$$eval(
60
63
  standardInstances.push({
61
64
  issueID: 'embAc',
62
65
  what: 'Interactive elements are contained by links or buttons',
66
+ count: total,
63
67
  ordinalSeverity: 2,
68
+ tagName: '',
69
+ id: '',
64
70
  location: {
65
71
  doc: '',
66
72
  type: '',
package/testaro/filter.js CHANGED
@@ -40,6 +40,7 @@ exports.reporter = async (page, withItems) => {
40
40
  filterData.forEach(filterDatum => {
41
41
  data.items.push({
42
42
  tagName: filterDatum.element.tagName,
43
+ id: filterDatum.element.id,
43
44
  text: compact(filterDatum.element.textContent) || compact(filterDatum.element.outerHTML),
44
45
  impact: filterDatum.impact
45
46
  });
@@ -53,8 +54,10 @@ exports.reporter = async (page, withItems) => {
53
54
  data.items.forEach(item => {
54
55
  standardInstances.push({
55
56
  issueID: 'filterStyle',
56
- what: `Element ${item.tagName} has a filter style that impacts ${item.impact} elements`,
57
+ what: `${item.tagName} element has a filter style that impacts ${item.impact} elements`,
57
58
  ordinalSeverity: 2,
59
+ tagName: item.toUpperCase(),
60
+ id: item.id,
58
61
  location: {
59
62
  doc: '',
60
63
  type: '',
@@ -69,6 +72,8 @@ exports.reporter = async (page, withItems) => {
69
72
  issueID: 'filterStyle',
70
73
  what: 'Elements have filter styles impacting other elements',
71
74
  ordinalSeverity: 2,
75
+ tagName: '',
76
+ id: '',
72
77
  location: {
73
78
  doc: '',
74
79
  type: '',
package/testaro/focAll.js CHANGED
@@ -67,7 +67,10 @@ exports.reporter = async page => {
67
67
  standardInstances: data.discrepancy ? [{
68
68
  issueID: 'focAll',
69
69
  what: 'Some focusable elements are not Tab-focusable or vice versa',
70
+ count: Math.abs(data.discrepancy),
70
71
  ordinalSeverity: 2,
72
+ tagName: '',
73
+ id: '',
71
74
  location: {
72
75
  doc: '',
73
76
  type: '',
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: `Element ${item.tagName} has ${qualifier} focus indicator`,
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: '',
@@ -186,18 +189,39 @@ exports.reporter = async (page, withItems, revealAll = false, allowedDelay = 250
186
189
  });
187
190
  });
188
191
  }
189
- else if (types.nonOutlinePresent.total || types.indicatorMissing.total) {
190
- standardInstances.push({
191
- issueID: 'focInd',
192
- what: 'Elements have missing or non-outline focus indicators',
193
- ordinalSeverity: types.indicatorMissing.total ? 3 : 2,
194
- location: {
195
- doc: '',
196
- type: '',
197
- spec: ''
198
- },
199
- excerpt: ''
200
- });
192
+ else {
193
+ if (types.indicatorMissing.total) {
194
+ standardInstances.push({
195
+ issueID: 'focInd-missing',
196
+ what: 'Elements have missing focus indicators',
197
+ count: types.indicatorMissing.total,
198
+ ordinalSeverity: 3,
199
+ tagName: '',
200
+ id: '',
201
+ location: {
202
+ doc: '',
203
+ type: '',
204
+ spec: ''
205
+ },
206
+ excerpt: ''
207
+ });
208
+ }
209
+ if (types.nonOutlinePresent.total) {
210
+ standardInstances.push({
211
+ issueID: 'focInd-nonoutline',
212
+ what: 'Elements have non-outline focus indicators',
213
+ count: types.nonOutlinePresent.total,
214
+ ordinalSeverity: 2,
215
+ tagName: '',
216
+ id: '',
217
+ location: {
218
+ doc: '',
219
+ type: '',
220
+ spec: ''
221
+ },
222
+ excerpt: ''
223
+ });
224
+ }
201
225
  }
202
226
  // Reload the page.
203
227
  try {
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: `Element ${which} ${gripe}`,
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: '',
@@ -174,18 +174,39 @@ exports.reporter = async (page, withItems) => {
174
174
  });
175
175
  });
176
176
  }
177
- else if (totals[2] || totals[3]) {
178
- standardInstances.push({
179
- issueID: 'focOp',
180
- what: 'Focusable elements are inoperable or vice versa',
181
- ordinalSeverity: totals[3] ? 3 : 2,
182
- location: {
183
- doc: '',
184
- type: '',
185
- spec: ''
186
- },
187
- excerpt: ''
188
- });
177
+ else {
178
+ if (totals[2]) {
179
+ standardInstances.push({
180
+ issueID: 'focOp-onlyFocusable',
181
+ what: 'Focusable elements are inoperable',
182
+ count: totals[2],
183
+ ordinalSeverity: 2,
184
+ tagName: '',
185
+ id: '',
186
+ location: {
187
+ doc: '',
188
+ type: '',
189
+ spec: ''
190
+ },
191
+ excerpt: ''
192
+ });
193
+ }
194
+ if (totals[3]) {
195
+ standardInstances.push({
196
+ issueID: 'focOp-onlyOperable',
197
+ what: 'Operable elements are nonfocusable',
198
+ count: totals[3],
199
+ ordinalSeverity: 3,
200
+ tagName: '',
201
+ id: '',
202
+ location: {
203
+ doc: '',
204
+ type: '',
205
+ spec: ''
206
+ },
207
+ excerpt: ''
208
+ });
209
+ }
189
210
  }
190
211
  // Reload the page.
191
212
  try {
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(compact(link.textContent));
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
  }
@@ -46,7 +51,10 @@ exports.reporter = async (page, withItems) => {
46
51
  standardInstances.push({
47
52
  issueID: 'focVis',
48
53
  what: 'Visible links are above or to the left of the display',
54
+ count: data.total,
49
55
  ordinalSeverity: 2,
56
+ tagName: 'A',
57
+ id: '',
50
58
  location: {
51
59
  doc: '',
52
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,17 +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
+ count: data.totals[issue],
411
412
  ordinalSeverity: severity[issue],
413
+ tagName: item.tagName,
414
+ id: item.id,
412
415
  location: {
413
416
  doc: '',
414
417
  type: '',
415
418
  spec: ''
416
419
  },
417
- excerpt: `${itemID}: ${item.text}`
420
+ excerpt: item.text
418
421
  });
419
422
  });
420
423
  });
@@ -423,7 +426,10 @@ exports.reporter = async (page, withItems, sampleSize = -1) => {
423
426
  standardInstances.push({
424
427
  issueID: 'hover',
425
428
  what: 'Hovering has unexpected impacts',
429
+ count: Object.values(data.totals).reduce((total, current) => total + current),
426
430
  ordinalSeverity: totals.reduce((max, current, index) => current ? index : max, 0),
431
+ tagName: '',
432
+ id: '',
427
433
  location: {
428
434
  doc: '',
429
435
  type: '',
@@ -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: '',
@@ -176,18 +179,39 @@ exports.reporter = async (page, withItems) => {
176
179
  });
177
180
  });
178
181
  }
179
- else if (data.totals.mislabeled || data.totals.unlabeled) {
180
- standardInstances.push({
181
- issueID: 'labClash',
182
- what: 'Element labels are conflicting or missing',
183
- ordinalSeverity: data.totals.unlabeled ? 3 : 2,
184
- location: {
185
- doc: '',
186
- type: '',
187
- spec: ''
188
- },
189
- excerpt: ''
190
- });
182
+ else {
183
+ if (data.totals.unlabeled) {
184
+ standardInstances.push({
185
+ issueID: 'labClash-unlabeled',
186
+ what: 'Element labels are missing',
187
+ count: data.totals.unlabeled,
188
+ ordinalSeverity: 3,
189
+ tagName: '',
190
+ id: '',
191
+ location: {
192
+ doc: '',
193
+ type: '',
194
+ spec: ''
195
+ },
196
+ excerpt: ''
197
+ });
198
+ }
199
+ if (data.totals.mislabeled) {
200
+ standardInstances.push({
201
+ issueID: 'labClash-mislabeled',
202
+ what: 'Element labels are conflicting',
203
+ count: data.totals.mislabeled,
204
+ ordinalSeverity: 2,
205
+ tagName: '',
206
+ id: '',
207
+ location: {
208
+ doc: '',
209
+ type: '',
210
+ spec: ''
211
+ },
212
+ excerpt: ''
213
+ });
214
+ }
191
215
  }
192
216
  return {
193
217
  data,
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 badLinkTexts = await page.$$eval(
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 => compact(link.textContent));
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: badLinkTexts.length
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 = badLinkTexts;
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
  }
@@ -40,7 +45,10 @@ exports.reporter = async (page, withItems) => {
40
45
  standardInstances.push({
41
46
  issueID: 'linkTo',
42
47
  what: 'Links are missing href attributes',
48
+ count: data.total,
43
49
  ordinalSeverity: 2,
50
+ tagName: 'A',
51
+ id: '',
44
52
  location: {
45
53
  doc: '',
46
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 ulAdjacentLinkTexts = [];
29
- const nulAdjacentLinkTexts = [];
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 text to the array of their texts.
39
+ // If required, add its data to the array of their data.
39
40
  if (withItems) {
40
- ulAdjacentLinkTexts.push(text);
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
- nulAdjacentLinkTexts.push(text);
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: ulAdjacentLinkTexts,
66
- notUnderlined: nulAdjacentLinkTexts
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: 'Element a is inline but has no underline',
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
  }
@@ -88,7 +97,10 @@ exports.reporter = async (page, withItems) => {
88
97
  standardInstances.push({
89
98
  issueID: 'linkUl',
90
99
  what: 'Inline links are missing underlines',
100
+ count: adjacent.total - adjacent.underlined,
91
101
  ordinalSeverity: 1,
102
+ tagName: 'A',
103
+ id: '',
92
104
  location: {
93
105
  doc: '',
94
106
  type: '',
@@ -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
- itemData.tagName = await page.evaluate(element => element.tagName, currentItem);
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
  }
@@ -203,14 +208,14 @@ exports.reporter = async (page, withItems) => {
203
208
  isCorrect = await testKey(
204
209
  menu, menuItems, currentItem, 'End', 'end', itemCount - 1, isCorrect, itemData
205
210
  );
206
- // Update the menu-item status (Node 14 does not support the ES 2021 &&= operator).
211
+ // Update the menu status (Node 14 does not support the ES 2021 &&= operator).
207
212
  menuIsCorrect = menuIsCorrect && isCorrect;
208
213
  // Increment the data.
209
214
  data.totals.menuItems[isCorrect ? 'correct' : 'incorrect']++;
210
215
  if (withItems) {
211
216
  data.menuItems[isCorrect ? 'correct' : 'incorrect'].push(itemData);
212
217
  }
213
- // Process the next tab element.
218
+ // Process the next menu item.
214
219
  return await testMenuItems(menu, menuItems, index + 1, orientation, menuIsCorrect);
215
220
  }
216
221
  // Otherwise, i.e. if all menu items have been tested:
@@ -271,14 +276,17 @@ exports.reporter = async (page, withItems) => {
271
276
  data.menuItems.incorrect.forEach(item => {
272
277
  standardInstances.push({
273
278
  issueID: 'menuNav',
274
- what: `Element ${item.tagName} is a menu item but has nonstandard navigation`,
279
+ what: `Menu item responds nonstandardly to ${item.navigationErrors.join(', ')}`,
280
+ count: item.navigationErrors.length,
275
281
  ordinalSeverity: 1,
282
+ tagName: item.tagName,
283
+ id: item.id,
276
284
  location: {
277
285
  doc: '',
278
286
  type: '',
279
287
  spec: ''
280
288
  },
281
- excerpt: `${item.tagName}: ${item.text}`
289
+ excerpt: item.text
282
290
  });
283
291
  });
284
292
  }
@@ -286,7 +294,10 @@ exports.reporter = async (page, withItems) => {
286
294
  standardInstances.push({
287
295
  issueID: 'menuNav',
288
296
  what: 'Menus and menu items have nonstandard navigation',
289
- ordinalSeverity: 2,
297
+ count: data.totals.navigations.all.incorrect,
298
+ ordinalSeverity: 1,
299
+ tagName: '',
300
+ id: '',
290
301
  location: {
291
302
  doc: '',
292
303
  type: '',