testaro 14.2.6 → 14.3.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 CHANGED
@@ -207,6 +207,7 @@ The standard format of each tool report has two properties:
207
207
  - `instances`: an array of objects describing facts about issue instances reported by the tool. Insofar as each tool permits, this object has these properties:
208
208
  - `issueID`: a code identifying the issue
209
209
  - `what`: a description of the issue
210
+ - `count` (optional): the count of instances if this instance represents multiple instances
210
211
  - `ordinalSeverity`: how the tool ranks the severity of the instance, on a 4-point ordinal scale
211
212
  - `location`: an object with three properties:
212
213
  - `doc`: whether the source (`source`) or the browser rendition (`dom`) was tested
@@ -218,11 +219,11 @@ The original result of a test act is recorded as the value of a `result` propert
218
219
 
219
220
  ``` javascript
220
221
  standardResult: {
221
- totals: [2, 0, 1, 0],
222
+ totals: [2, 0, 17, 0],
222
223
  instances: [
223
224
  {
224
225
  issueID: 'rule01',
225
- what: 'button type invalid',
226
+ what: 'Button type invalid',
226
227
  ordinalSeverity: 0,
227
228
  location: {
228
229
  doc: 'dom',
@@ -233,7 +234,7 @@ standardResult: {
233
234
  },
234
235
  {
235
236
  issueID: 'rule01',
236
- what: 'button type invalid',
237
+ what: 'Button type invalid',
237
238
  ordinalSeverity: 1,
238
239
  location: {
239
240
  doc: 'dom',
@@ -244,20 +245,21 @@ standardResult: {
244
245
  },
245
246
  {
246
247
  issueID: 'rule02',
247
- what: 'link href empty',
248
+ what: 'Links have empty href attributes',
249
+ count: 17,
248
250
  ordinalSeverity: 3,
249
251
  location: {
250
- doc: 'dom',
251
- type: 'selector',
252
- spec: '#helplink'
252
+ doc: '',
253
+ type: '',
254
+ spec: ''
253
255
  },
254
- excerpt: '<a id="helplink" href>help</a>'
256
+ excerpt: ''
255
257
  }
256
258
  ]
257
259
  }
258
260
  ```
259
261
 
260
- If a tool has the option to be used without itemization and is being so used, the `instances` array will be empty.
262
+ If a tool has the option to be used without itemization and is being so used, the `instances` array may be empty.
261
263
 
262
264
  ### Acts
263
265
 
@@ -454,29 +456,6 @@ The `continuum` tests makes use of the files in the `continuum` directory. The t
454
456
 
455
457
  Level Access on 22 August 2022 granted authorization for the copying of the `AccessEngine.community.js` file insofar as necessary for allowing Continuum community edition tests to be included in Testaro.
456
458
 
457
- ###### IBM Equal Access
458
-
459
- The `ibm` tests require the `aceconfig.js` file.
460
-
461
- As of 2 March 2023 (version 3.1.45 of `accessibility-checker`), the `ibm` tool threw errors when hosted under the Windows operating system. To prevent these errors, it was possible to edit two files in the `accessibility-checker` package as follows:
462
-
463
- In `node_modules/accessibility-checker/lib/ACEngineManager.js`, remove or comment out these lines starting on line 169:
464
-
465
- ```javaScript
466
- if (nodePath.charAt(0) !== '/') {
467
- nodePath = "../../" + nodePath;
468
- }
469
- ```
470
-
471
- In `node_modules/accessibility-checker/lib/reporters/ACReporterJSON.js`, add these lines starting on line 106, immediately before the line `var resultsFileName = pathLib.join(resultDir, results.label + '.json');`:
472
-
473
- ```javaScript
474
- // Replace the colons in the label with hyphen-minuses.
475
- results.label = results.label.replace(/:/g, '-');
476
- ```
477
-
478
- These changes were proposed as pull requests 1333 and 1334 (https://github.com/IBMa/equal-access/pulls).
479
-
480
459
  ###### HTML CodeSniffer
481
460
 
482
461
  The `htmlcs` tool makes use of the `htmlcs/HTMLCS.js` file. That file was created, and can be recreated if necessary, as follows:
@@ -509,6 +488,31 @@ The changes in `htmlcs/HTMLCS.js` are:
509
488
  > );
510
489
  ```
511
490
 
491
+ ###### IBM Equal Access
492
+
493
+ The `ibm` tests require the `aceconfig.js` file.
494
+
495
+ As of 2 March 2023 (version 3.1.45 of `accessibility-checker`), the `ibm` tool threw errors when hosted under the Windows operating system. To prevent these errors, it was possible to edit two files in the `accessibility-checker` package as follows:
496
+
497
+ In `node_modules/accessibility-checker/lib/ACEngineManager.js`, remove or comment out these lines starting on line 169:
498
+
499
+ ```javaScript
500
+ if (nodePath.charAt(0) !== '/') {
501
+ nodePath = "../../" + nodePath;
502
+ }
503
+ ```
504
+
505
+ In `node_modules/accessibility-checker/lib/reporters/ACReporterJSON.js`, add these lines starting on line 106, immediately before the line `var resultsFileName = pathLib.join(resultDir, results.label + '.json');`:
506
+
507
+ ```javaScript
508
+ // Replace the colons in the label with hyphen-minuses.
509
+ results.label = results.label.replace(/:/g, '-');
510
+ ```
511
+
512
+ These changes were proposed as pull requests 1333 and 1334 (https://github.com/IBMa/equal-access/pulls).
513
+
514
+ The `ibm` tool is one of two tools (`testaro` is the other) with a `withItems` property. If you set `withItems` to `false`, the result includes the counts of “violations” and “recommendations”, but no information about the rules that gave rise to them.
515
+
512
516
  ###### QualWeb
513
517
 
514
518
  The `qualWeb` tool performs the ACT rules, WCAG Techniques, and best-practices tests of QualWeb. Only failures and warnings are included in the report. The EARL report of QualWeb is not generated, because it is equivalent to the report of the ACT rules tests.
@@ -555,6 +559,14 @@ Tenon recommends giving it a public URL rather than giving it the content of a p
555
559
 
556
560
  If a `tenon` test act is included in a job, environment variables named `TENON_USER` and `TENON_PASSWORD` must exist, with your Tenon username and password, respectively, as their values. These could be obtained from [Tenon](https://tenon.io/documentation/overview) until Tenon was closed to new subscribers in or about October 2022.
557
561
 
562
+ ###### Testaro
563
+
564
+ If you do not specify rules when using the `testaro` tool, Testaro will test for the rules listed in the `evalRules` object of the `tests/testaro.js` file.
565
+
566
+ It has been found that the `motion` test of the `testaro` tool measures motion only when the `webkit` browser type is in use. If you want to use `testaro` with different browser types for different tests, you can include 2 or 3 `testaro` test acts in your job, specifying different browser types and different rules.
567
+
568
+ The `testaro` tool (like the `ibm` tool) has a `withItems` property. If you set it to `false`, the `standardResult` object of `testaro` will contain an `instances` property with summaries that identify issues and instance counts. If you set it to `true`, some of the instances will be itemized.
569
+
558
570
  ###### WAVE
559
571
 
560
572
  If a `wave` test act is included in the job, an environment variable named `WAVE_KEY` must exist, with your WAVE API key as its value. You can get it from [WebAIM](https://wave.webaim.org/api/).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "14.2.6",
3
+ "version": "14.3.0",
4
4
  "description": "Automation of accessibility testing",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -3,14 +3,17 @@
3
3
  This test reports a page that is entirely or mainly hidden.
4
4
  */
5
5
  exports.reporter = async page => {
6
+ // Gets the hiddennesses of the document, body, and main region.
6
7
  const data = await page.evaluate(() => {
8
+ // Identify the styles of the document, its body, and its main region.
7
9
  const {body} = document;
8
- const main = body && body.querySelector('main');
10
+ const main = body && body.querySelector('main, [role=main]');
9
11
  const styles = {
10
12
  doc: window.getComputedStyle(document.documentElement),
11
13
  body: body && window.getComputedStyle(body),
12
14
  main: main && window.getComputedStyle(main)
13
15
  };
16
+ // Get the hiddennesses of the regions.
14
17
  const data = {
15
18
  hidden: {
16
19
  document: document.documentElement.hidden,
@@ -38,6 +41,7 @@ exports.reporter = async page => {
38
41
  main: main ? main.ariaHidden === 'true' : false
39
42
  }
40
43
  };
44
+ // Identify whether each region is really hidden.
41
45
  ['document', 'body', 'main'].forEach(element => {
42
46
  if (data.hidden[element] && ! ['block', 'flex'].includes(data.display[element])) {
43
47
  data.reallyHidden[element] = true;
@@ -45,10 +49,11 @@ exports.reporter = async page => {
45
49
  });
46
50
  return data;
47
51
  });
52
+ // For each combination of region and hiddenness:
48
53
  const standardInstances = [];
49
54
  const reportables = {
50
- hidden: [0, 'hidden'],
51
- reallyHidden: [1, 'effectively hidden'],
55
+ hidden: [1, 'hidden'],
56
+ reallyHidden: [2, 'effectively hidden'],
52
57
  visHidden: [0, 'visually hidden'],
53
58
  ariaHidden: [1, 'hidden by ARIA'],
54
59
  document: [1, 'Document', 'document.documentElement'],
@@ -57,7 +62,9 @@ exports.reporter = async page => {
57
62
  };
58
63
  ['document', 'body', 'main'].forEach(region => {
59
64
  ['hidden', 'reallyHidden', 'visHidden', 'ariaHidden'].forEach(hider => {
65
+ // If the region has that hiddenness:
60
66
  if (data[hider][region]) {
67
+ // Add a standard instance for that combination.
61
68
  standardInstances.push({
62
69
  issueID: `allHidden-${hider}-${region}`,
63
70
  what: `${reportables[region][1]} ${reportables[hider][1]}`,
@@ -72,6 +79,7 @@ exports.reporter = async page => {
72
79
  }
73
80
  });
74
81
  });
82
+ // Get the severity totals.
75
83
  const totals = [0, 0, 0, 0];
76
84
  standardInstances.forEach(instance => {
77
85
  totals[instance.ordinalSeverity]++;
package/testaro/bulk.js CHANGED
@@ -18,12 +18,14 @@ 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,
28
30
  location: {
29
31
  doc: '',
package/testaro/embAc.js CHANGED
@@ -60,6 +60,7 @@ exports.reporter = async (page, withItems) => await page.$$eval(
60
60
  standardInstances.push({
61
61
  issueID: 'embAc',
62
62
  what: 'Interactive elements are contained by links or buttons',
63
+ count: total,
63
64
  ordinalSeverity: 2,
64
65
  location: {
65
66
  doc: '',
package/testaro/focAll.js CHANGED
@@ -67,6 +67,7 @@ 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,
71
72
  location: {
72
73
  doc: '',
package/testaro/focInd.js CHANGED
@@ -186,18 +186,35 @@ exports.reporter = async (page, withItems, revealAll = false, allowedDelay = 250
186
186
  });
187
187
  });
188
188
  }
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
- });
189
+ else {
190
+ if (types.indicatorMissing.total) {
191
+ standardInstances.push({
192
+ issueID: 'focInd-missing',
193
+ what: 'Elements have missing focus indicators',
194
+ count: types.indicatorMissing.total,
195
+ ordinalSeverity: 3,
196
+ location: {
197
+ doc: '',
198
+ type: '',
199
+ spec: ''
200
+ },
201
+ excerpt: ''
202
+ });
203
+ }
204
+ if (types.nonOutlinePresent.total) {
205
+ standardInstances.push({
206
+ issueID: 'focInd-nonoutline',
207
+ what: 'Elements have non-outline focus indicators',
208
+ count: types.nonOutlinePresent.total,
209
+ ordinalSeverity: 2,
210
+ location: {
211
+ doc: '',
212
+ type: '',
213
+ spec: ''
214
+ },
215
+ excerpt: ''
216
+ });
217
+ }
201
218
  }
202
219
  // Reload the page.
203
220
  try {
package/testaro/focOp.js CHANGED
@@ -174,18 +174,35 @@ 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
+ location: {
185
+ doc: '',
186
+ type: '',
187
+ spec: ''
188
+ },
189
+ excerpt: ''
190
+ });
191
+ }
192
+ if (totals[3]) {
193
+ standardInstances.push({
194
+ issueID: 'focOp-onlyOperable',
195
+ what: 'Operable elements are nonfocusable',
196
+ count: totals[3],
197
+ ordinalSeverity: 3,
198
+ location: {
199
+ doc: '',
200
+ type: '',
201
+ spec: ''
202
+ },
203
+ excerpt: ''
204
+ });
205
+ }
189
206
  }
190
207
  // Reload the page.
191
208
  try {
package/testaro/focVis.js CHANGED
@@ -46,6 +46,7 @@ exports.reporter = async (page, withItems) => {
46
46
  standardInstances.push({
47
47
  issueID: 'focVis',
48
48
  what: 'Visible links are above or to the left of the display',
49
+ count: data.total,
49
50
  ordinalSeverity: 2,
50
51
  location: {
51
52
  doc: '',
package/testaro/hover.js CHANGED
@@ -408,6 +408,7 @@ exports.reporter = async (page, withItems, sampleSize = -1) => {
408
408
  standardInstances.push({
409
409
  issueID: `hover-${issue}`,
410
410
  what: what[issue],
411
+ count: data.totals[issue],
411
412
  ordinalSeverity: severity[issue],
412
413
  location: {
413
414
  doc: '',
@@ -423,6 +424,7 @@ exports.reporter = async (page, withItems, sampleSize = -1) => {
423
424
  standardInstances.push({
424
425
  issueID: 'hover',
425
426
  what: 'Hovering has unexpected impacts',
427
+ count: Object.values(data.totals).reduce((total, current) => total + current),
426
428
  ordinalSeverity: totals.reduce((max, current, index) => current ? index : max, 0),
427
429
  location: {
428
430
  doc: '',
@@ -176,18 +176,35 @@ exports.reporter = async (page, withItems) => {
176
176
  });
177
177
  });
178
178
  }
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
- });
179
+ else {
180
+ if (data.totals.unlabeled) {
181
+ standardInstances.push({
182
+ issueID: 'labClash-unlabeled',
183
+ what: 'Element labels are missing',
184
+ count: data.totals.unlabeled,
185
+ ordinalSeverity: 3,
186
+ location: {
187
+ doc: '',
188
+ type: '',
189
+ spec: ''
190
+ },
191
+ excerpt: ''
192
+ });
193
+ }
194
+ if (data.totals.mislabeled) {
195
+ standardInstances.push({
196
+ issueID: 'labClash-mislabeled',
197
+ what: 'Element labels are conflicting',
198
+ count: data.totals.mislabeled,
199
+ ordinalSeverity: 2,
200
+ location: {
201
+ doc: '',
202
+ type: '',
203
+ spec: ''
204
+ },
205
+ excerpt: ''
206
+ });
207
+ }
191
208
  }
192
209
  return {
193
210
  data,
package/testaro/linkTo.js CHANGED
@@ -40,6 +40,7 @@ exports.reporter = async (page, withItems) => {
40
40
  standardInstances.push({
41
41
  issueID: 'linkTo',
42
42
  what: 'Links are missing href attributes',
43
+ count: data.total,
43
44
  ordinalSeverity: 2,
44
45
  location: {
45
46
  doc: '',
package/testaro/linkUl.js CHANGED
@@ -88,6 +88,7 @@ exports.reporter = async (page, withItems) => {
88
88
  standardInstances.push({
89
89
  issueID: 'linkUl',
90
90
  what: 'Inline links are missing underlines',
91
+ count: adjacent.total - adjacent.underlined,
91
92
  ordinalSeverity: 1,
92
93
  location: {
93
94
  doc: '',
@@ -203,14 +203,14 @@ exports.reporter = async (page, withItems) => {
203
203
  isCorrect = await testKey(
204
204
  menu, menuItems, currentItem, 'End', 'end', itemCount - 1, isCorrect, itemData
205
205
  );
206
- // Update the menu-item status (Node 14 does not support the ES 2021 &&= operator).
206
+ // Update the menu status (Node 14 does not support the ES 2021 &&= operator).
207
207
  menuIsCorrect = menuIsCorrect && isCorrect;
208
208
  // Increment the data.
209
209
  data.totals.menuItems[isCorrect ? 'correct' : 'incorrect']++;
210
210
  if (withItems) {
211
211
  data.menuItems[isCorrect ? 'correct' : 'incorrect'].push(itemData);
212
212
  }
213
- // Process the next tab element.
213
+ // Process the next menu item.
214
214
  return await testMenuItems(menu, menuItems, index + 1, orientation, menuIsCorrect);
215
215
  }
216
216
  // Otherwise, i.e. if all menu items have been tested:
@@ -271,7 +271,9 @@ exports.reporter = async (page, withItems) => {
271
271
  data.menuItems.incorrect.forEach(item => {
272
272
  standardInstances.push({
273
273
  issueID: 'menuNav',
274
- what: `Element ${item.tagName} is a menu item but has nonstandard navigation`,
274
+ what:
275
+ `Menu item ${item.tagName} responds nonstandardly to ${item.navigationErrors.join(', ')}`,
276
+ count: item.navigationErrors.length,
275
277
  ordinalSeverity: 1,
276
278
  location: {
277
279
  doc: '',
@@ -286,7 +288,8 @@ exports.reporter = async (page, withItems) => {
286
288
  standardInstances.push({
287
289
  issueID: 'menuNav',
288
290
  what: 'Menus and menu items have nonstandard navigation',
289
- ordinalSeverity: 2,
291
+ count: data.totals.navigations.all.incorrect,
292
+ ordinalSeverity: 1,
290
293
  location: {
291
294
  doc: '',
292
295
  type: '',
@@ -62,6 +62,7 @@ exports.reporter = async (page, withItems) => {
62
62
  standardInstances.push({
63
63
  issueID: 'miniText',
64
64
  what: 'Texts have fonts smaller than 11 pixels',
65
+ count: data.total,
65
66
  ordinalSeverity: 2,
66
67
  location: {
67
68
  doc: '',
package/testaro/motion.js CHANGED
@@ -98,6 +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 count = 2 * (meanLocalRatio - 1)
102
+ + maxLocalRatio - 1
103
+ + globalRatio - 1
104
+ + meanPixelChange / 10000
105
+ + maxPixelChange / 25000
106
+ + 3 * changeFrequency
107
+ || 0;
101
108
  return {
102
109
  data: {
103
110
  bytes,
@@ -112,19 +119,14 @@ exports.reporter = async (page, withItems, delay = 2500, interval = 2500, count
112
119
  },
113
120
  totals: [
114
121
  0,
115
- 0,
116
- 2 * (meanLocalRatio - 1)
117
- + maxLocalRatio - 1
118
- + globalRatio - 1
119
- + meanPixelChange / 10000
120
- + maxPixelChange / 25000
121
- + 3 * changeFrequency
122
- || 0,
122
+ 0,
123
+ count,
123
124
  0
124
125
  ],
125
- standardInstances: globalRatio > 1 ? [{
126
+ standardInstances: count ? [{
126
127
  issueID: 'motion',
127
128
  what: 'Content moves or changes without user request',
129
+ count,
128
130
  ordinalSeverity: 2,
129
131
  location: {
130
132
  doc: '',
@@ -81,7 +81,8 @@ exports.reporter = async (page, withItems) => {
81
81
  standardInstances.push({
82
82
  issueID: 'nonTable',
83
83
  what: 'Tables are misused to arrange content',
84
- ordinalSeverity: 2,
84
+ count: data.total,
85
+ ordinalSeverity: 0,
85
86
  location: {
86
87
  doc: '',
87
88
  type: '',
@@ -74,6 +74,7 @@ exports.reporter = async (page, withItems) => {
74
74
  totals.total = allRadios.length;
75
75
  totals.inSet = setRadios.length;
76
76
  totals.percent = totals.total ? Math.floor(100 * totals.inSet / totals.total) : 'N.A.';
77
+ const loneRadios = totals.total - totals.inSet;
77
78
  // If itemization is required:
78
79
  const standardInstances = [];
79
80
  if (withItems) {
@@ -85,7 +86,7 @@ exports.reporter = async (page, withItems) => {
85
86
  items.notInSet.forEach(text => {
86
87
  standardInstances.push({
87
88
  issueID: 'radioSet',
88
- what: 'Radio button and others with its name are not grouped in their own fieldset with a legend',
89
+ what: 'Radio button and its peers are not in a fieldset with a legend',
89
90
  ordinalSeverity: 2,
90
91
  location: {
91
92
  doc: '',
@@ -96,10 +97,11 @@ exports.reporter = async (page, withItems) => {
96
97
  });
97
98
  });
98
99
  }
99
- else if (totals.total - totals.inSet > 0) {
100
+ else if (loneRadios > 0) {
100
101
  standardInstances.push({
101
102
  issueID: 'radioSet',
102
103
  what: 'Radio buttons are not validly grouped in fieldsets with legends',
104
+ count: loneRadios,
103
105
  ordinalSeverity: 2,
104
106
  location: {
105
107
  doc: '',
@@ -111,7 +113,7 @@ exports.reporter = async (page, withItems) => {
111
113
  }
112
114
  return {
113
115
  data,
114
- totals: [0, 0, totals.total - totals.inSet, 0],
116
+ totals: [0, 0, loneRadios, 0],
115
117
  standardInstances
116
118
  };
117
119
  }
package/testaro/role.js CHANGED
@@ -481,11 +481,13 @@ exports.reporter = async page => await page.$eval('body', body => {
481
481
  const standardInstances = [];
482
482
  Object.keys(data.tagNames).forEach(tagName => {
483
483
  Object.keys(data.tagNames[tagName]).forEach(role => {
484
- let count = data.tagNames[tagName][role].redundant;
485
- if (count) {
484
+ const pairTotals = data.tagNames[tagName][role];
485
+ const redCount = pairTotals.redundant;
486
+ if (redCount) {
486
487
  standardInstances.push({
487
- issueID: 'role',
488
- what: `Elements ${tagName} have redundant explicit role ${role} (count: ${count})`,
488
+ issueID: 'role-redundant',
489
+ what: `${tagName} elements have redundant explicit role ${role} (count: ${redCount})`,
490
+ count: redCount,
489
491
  ordinalSeverity: 1,
490
492
  location: {
491
493
  doc: '',
@@ -495,11 +497,13 @@ exports.reporter = async page => await page.$eval('body', body => {
495
497
  excerpt: ''
496
498
  });
497
499
  }
498
- count = data.tagNames[tagName][role].bad;
499
- if (count) {
500
+ const badCount = pairTotals.bad;
501
+ if (badCount) {
500
502
  standardInstances.push({
501
- issueID: 'role',
502
- what: `Elements ${tagName} have invalid or native-replaceable explicit role ${role} (count: ${count})`,
503
+ issueID: 'role-bad',
504
+ what:
505
+ `Elements ${tagName} have invalid or native-replaceable explicit role ${role} (count: ${badCount})`,
506
+ count: badCount,
503
507
  ordinalSeverity: 3,
504
508
  location: {
505
509
  doc: '',
@@ -171,10 +171,12 @@ exports.reporter = async (page, withItems) => {
171
171
  const currentData = elementData[elementName];
172
172
  const severity = currentData[0];
173
173
  const elementSubtotals = elementTotal.subtotals;
174
- totals[severity] += elementSubtotals.length - 1;
174
+ const extraCount = elementSubtotals.length - 1;
175
+ totals[severity] += extraCount;
175
176
  standardInstances.push({
176
177
  issueID: 'styleDiff',
177
178
  what: `${currentData[1]} have ${elementSubtotals.length} different styles`,
179
+ count: extraCount,
178
180
  ordinalSeverity: severity,
179
181
  location: {
180
182
  doc: '',
package/testaro/tabNav.js CHANGED
@@ -335,7 +335,9 @@ exports.reporter = async (page, withItems) => {
335
335
  data.tabElements.incorrect.forEach(item => {
336
336
  standardInstances.push({
337
337
  issueID: 'tabNav',
338
- what: `Element ${item.tagName} has a tab role but has nonstandard navigation`,
338
+ what:
339
+ `${item.tagName} element responds nonstandardly to ${item.navigationErrors.join(', ')}`,
340
+ count: item.navigationErrors.length,
339
341
  ordinalSeverity: 1,
340
342
  location: {
341
343
  doc: '',
@@ -350,7 +352,8 @@ exports.reporter = async (page, withItems) => {
350
352
  standardInstances.push({
351
353
  issueID: 'tabNav',
352
354
  what: 'Tablists have nonstandard navigation',
353
- ordinalSeverity: 2,
355
+ count: data.totals.navigations.all.incorrect,
356
+ ordinalSeverity: 1,
354
357
  location: {
355
358
  doc: '',
356
359
  type: '',
@@ -45,6 +45,7 @@ exports.reporter = async (page, withItems) => {
45
45
  standardInstances.push({
46
46
  issueID: 'titledEl',
47
47
  what: 'Ineligible elements have title attributes',
48
+ count: data.total,
48
49
  ordinalSeverity: 2,
49
50
  location: {
50
51
  doc: '',
package/testaro/zIndex.js CHANGED
@@ -55,7 +55,7 @@ exports.reporter = async (page, withItems) => {
55
55
  const which = `${item.tagName}${itemID}`;
56
56
  standardInstances.push({
57
57
  issueID: 'zIndex',
58
- what: `Element ${item.tagName} has a non-default Z index`,
58
+ what: `${item.tagName} element has a non-default Z index`,
59
59
  ordinalSeverity: 0,
60
60
  location: {
61
61
  doc: '',
@@ -70,6 +70,7 @@ exports.reporter = async (page, withItems) => {
70
70
  standardInstances.push({
71
71
  issueID: 'zIndex',
72
72
  what: 'Elements have non-default Z indexes',
73
+ count: data.totals.total,
73
74
  ordinalSeverity: 0,
74
75
  location: {
75
76
  doc: '',
package/tests/ibm.js CHANGED
@@ -87,7 +87,7 @@ const trimReport = (report, withItems, rules) => {
87
87
  }
88
88
  return data;
89
89
  };
90
- // Performs an IBM test and returns the result.
90
+ // Performs the IBM tests and returns the result.
91
91
  const doTest = async (content, withItems, timeLimit, rules) => {
92
92
  // Conduct the test and get the result.
93
93
  let report;