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.
@@ -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(compact(node.textContent));
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
  }
@@ -62,7 +68,10 @@ exports.reporter = async (page, withItems) => {
62
68
  standardInstances.push({
63
69
  issueID: 'miniText',
64
70
  what: 'Texts have fonts smaller than 11 pixels',
71
+ count: data.total,
65
72
  ordinalSeverity: 2,
73
+ tagName: '',
74
+ id: '',
66
75
  location: {
67
76
  doc: '',
68
77
  type: '',
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 rawCount = 2 * (meanLocalRatio - 1)
102
+ + maxLocalRatio - 1
103
+ + globalRatio - 1
104
+ + meanPixelChange / 10000
105
+ + maxPixelChange / 25000
106
+ + 3 * changeFrequency;
107
+ const count = rawCount ? Math.round(rawCount) : 0;
101
108
  return {
102
109
  data: {
103
110
  bytes,
@@ -112,20 +119,17 @@ 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,
131
+ tagName: '',
132
+ id: '',
129
133
  location: {
130
134
  doc: '',
131
135
  type: '',
@@ -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(compact(table.outerHTML).slice(0, 100));
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(text => {
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
  }
@@ -81,7 +86,10 @@ exports.reporter = async (page, withItems) => {
81
86
  standardInstances.push({
82
87
  issueID: 'nonTable',
83
88
  what: 'Tables are misused to arrange content',
84
- ordinalSeverity: 2,
89
+ count: data.total,
90
+ ordinalSeverity: 0,
91
+ tagName: 'TABLE',
92
+ id: '',
85
93
  location: {
86
94
  doc: '',
87
95
  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) {
@@ -81,26 +82,34 @@ exports.reporter = async (page, withItems) => {
81
82
  const nonSetRadios = allRadios.filter(radio => ! setRadios.includes(radio));
82
83
  const items = data.items;
83
84
  items.inSet = setRadios.map(radio => textOf(radio));
84
- items.notInSet = nonSetRadios.map(radio => textOf(radio));
85
- items.notInSet.forEach(text => {
85
+ items.notInSet = nonSetRadios.map(radio => ({
86
+ id: radio.id,
87
+ text: textOf(radio)
88
+ }));
89
+ items.notInSet.forEach(item => {
86
90
  standardInstances.push({
87
91
  issueID: 'radioSet',
88
- what: 'Radio button and others with its name are not grouped in their own fieldset with a legend',
92
+ what: 'Radio button and its peers are not in a fieldset with a legend',
89
93
  ordinalSeverity: 2,
94
+ tagName: 'INPUT',
95
+ id: item.id,
90
96
  location: {
91
97
  doc: '',
92
98
  type: '',
93
99
  spec: ''
94
100
  },
95
- excerpt: text
101
+ excerpt: item.text
96
102
  });
97
103
  });
98
104
  }
99
- else if (totals.total - totals.inSet > 0) {
105
+ else if (loneRadios > 0) {
100
106
  standardInstances.push({
101
107
  issueID: 'radioSet',
102
108
  what: 'Radio buttons are not validly grouped in fieldsets with legends',
109
+ count: loneRadios,
103
110
  ordinalSeverity: 2,
111
+ tagName: 'INPUT',
112
+ id: '',
104
113
  location: {
105
114
  doc: '',
106
115
  type: '',
@@ -111,7 +120,7 @@ exports.reporter = async (page, withItems) => {
111
120
  }
112
121
  return {
113
122
  data,
114
- totals: [0, 0, totals.total - totals.inSet, 0],
123
+ totals: [0, 0, loneRadios, 0],
115
124
  standardInstances
116
125
  };
117
126
  }
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 deprecated roles from the non-abstract roles.
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);
@@ -481,12 +482,16 @@ exports.reporter = async page => await page.$eval('body', body => {
481
482
  const standardInstances = [];
482
483
  Object.keys(data.tagNames).forEach(tagName => {
483
484
  Object.keys(data.tagNames[tagName]).forEach(role => {
484
- let count = data.tagNames[tagName][role].redundant;
485
- if (count) {
485
+ const pairTotals = data.tagNames[tagName][role];
486
+ const redCount = pairTotals.redundant;
487
+ if (redCount) {
486
488
  standardInstances.push({
487
- issueID: 'role',
488
- what: `Elements ${tagName} have redundant explicit role ${role} (count: ${count})`,
489
+ issueID: 'role-redundant',
490
+ what: `${tagName} elements have redundant explicit role ${role} (count: ${redCount})`,
491
+ count: redCount,
489
492
  ordinalSeverity: 1,
493
+ tagName,
494
+ id: '',
490
495
  location: {
491
496
  doc: '',
492
497
  type: '',
@@ -495,12 +500,16 @@ exports.reporter = async page => await page.$eval('body', body => {
495
500
  excerpt: ''
496
501
  });
497
502
  }
498
- count = data.tagNames[tagName][role].bad;
499
- if (count) {
503
+ const badCount = pairTotals.bad;
504
+ if (badCount) {
500
505
  standardInstances.push({
501
- issueID: 'role',
502
- what: `Elements ${tagName} have invalid or native-replaceable explicit role ${role} (count: ${count})`,
506
+ issueID: 'role-bad',
507
+ what:
508
+ `${tagName} elements have invalid or native-replaceable explicit role ${role} (count: ${badCount})`,
509
+ count: badCount,
503
510
  ordinalSeverity: 3,
511
+ tagName,
512
+ id: '',
504
513
  location: {
505
514
  doc: '',
506
515
  type: '',
@@ -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];
@@ -171,11 +171,15 @@ 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,
181
+ tagName: currentData[2],
182
+ id: '',
179
183
  location: {
180
184
  doc: '',
181
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
- itemData.tagName = await page.evaluate(element => element.tagName, currentTab)
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
  }
@@ -335,14 +340,18 @@ exports.reporter = async (page, withItems) => {
335
340
  data.tabElements.incorrect.forEach(item => {
336
341
  standardInstances.push({
337
342
  issueID: 'tabNav',
338
- what: `Element ${item.tagName} has a tab role but has nonstandard navigation`,
343
+ what:
344
+ `${item.tagName} element responds nonstandardly to ${item.navigationErrors.join(', ')}`,
345
+ count: item.navigationErrors.length,
339
346
  ordinalSeverity: 1,
347
+ tagName: item.tagName,
348
+ id: item.id,
340
349
  location: {
341
350
  doc: '',
342
351
  type: '',
343
352
  spec: ''
344
353
  },
345
- excerpt: `${item.tagName}: ${item.text}`
354
+ excerpt: item.text
346
355
  });
347
356
  });
348
357
  }
@@ -350,7 +359,10 @@ exports.reporter = async (page, withItems) => {
350
359
  standardInstances.push({
351
360
  issueID: 'tabNav',
352
361
  what: 'Tablists have nonstandard navigation',
353
- ordinalSeverity: 2,
362
+ count: data.totals.navigations.all.incorrect,
363
+ ordinalSeverity: 1,
364
+ tagName: '',
365
+ id: '',
354
366
  location: {
355
367
  doc: '',
356
368
  type: '',
@@ -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: `Element ${element.tagName} has a title attribute`,
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: '',
@@ -45,7 +48,10 @@ exports.reporter = async (page, withItems) => {
45
48
  standardInstances.push({
46
49
  issueID: 'titledEl',
47
50
  what: 'Ineligible elements have title attributes',
51
+ count: data.total,
48
52
  ordinalSeverity: 2,
53
+ tagName: '',
54
+ id: '',
49
55
  location: {
50
56
  doc: '',
51
57
  type: '',
package/testaro/zIndex.js CHANGED
@@ -51,18 +51,18 @@ exports.reporter = async (page, withItems) => {
51
51
  const standardInstances = [];
52
52
  if (data.items) {
53
53
  data.items.forEach(item => {
54
- const itemID = item.id ? ` (ID ${item.id})` : '';
55
- const which = `${item.tagName}${itemID}`;
56
54
  standardInstances.push({
57
55
  issueID: 'zIndex',
58
- what: `Element ${item.tagName} has a non-default Z index`,
56
+ what: `${item.tagName} element has a non-default Z index`,
59
57
  ordinalSeverity: 0,
58
+ tagName: item.tagName,
59
+ id: item.id,
60
60
  location: {
61
61
  doc: '',
62
62
  type: '',
63
63
  spec: ''
64
64
  },
65
- excerpt: `${which}: ${item.text}`
65
+ excerpt: item.text
66
66
  });
67
67
  });
68
68
  }
@@ -70,7 +70,10 @@ 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,
75
+ tagName: '',
76
+ id: '',
74
77
  location: {
75
78
  doc: '',
76
79
  type: '',
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;