testaro 64.6.0 → 64.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "64.6.0",
3
+ "version": "64.7.0",
4
4
  "description": "Run 1000 web accessibility tests from 11 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -13,7 +13,7 @@
13
13
  Converts test results to the standard format.
14
14
  */
15
15
 
16
- // ########## FUNCTIONS
16
+ // FUNCTIONS
17
17
 
18
18
  // Limits the length of and unilinearizes a string.
19
19
  const cap = rawString => {
@@ -327,11 +327,11 @@ const doWAVE = (result, standardResult, categoryName) => {
327
327
  const {items} = category;
328
328
  if (items) {
329
329
  Object.keys(items).forEach(ruleID => {
330
- items[ruleID].selectors.forEach(selector => {
330
+ items[ruleID].selectors.forEach(violationFacts => {
331
331
  let tagName = '';
332
332
  let id = '';
333
- if (typeof selector === 'string') {
334
- const finalTerm = selector.replace(/^.+\s/, '');
333
+ if (typeof violationFacts[0] === 'string') {
334
+ const finalTerm = violationFacts[0].replace(/^.+\s/, '');
335
335
  if (finalTerm.includes('#')) {
336
336
  const finalArray = finalTerm.split('#');
337
337
  tagName = finalArray[0].replace(/:.*/, '');
@@ -350,9 +350,9 @@ const doWAVE = (result, standardResult, categoryName) => {
350
350
  location: {
351
351
  doc: 'dom',
352
352
  type: 'selector',
353
- spec: selector
353
+ spec: violationFacts[0]
354
354
  },
355
- excerpt: ''
355
+ excerpt: violationFacts[1]
356
356
  };
357
357
  standardResult.instances.push(instance);
358
358
  });
@@ -667,13 +667,18 @@ const convert = (toolName, data, result, standardResult) => {
667
667
  result.violations.forEach(violation => {
668
668
  // Get its standard instance properties.
669
669
  const element = violation.element.replace(/\s+/g, ' ');
670
- const {message, description, severity} = violation;
670
+ const {boxID, description, message, notInDOM, pathID, severity} = violation;
671
671
  const ordinalSeverity = ['Minor', 'Moderate', '', 'Severe'].indexOf(severity);
672
672
  const tagNameCandidate = element.replace(/^<| .*$/g, '');
673
673
  const tagName = /^[a-zA-Z0-9]+$/.test(tagNameCandidate) ? tagNameCandidate.toUpperCase() : '';
674
674
  let id = '';
675
675
  const location = {};
676
- if (tagName) {
676
+ if (notInDOM) {
677
+ location.doc = 'notInDOM';
678
+ location.type = '';
679
+ location.spec = '';
680
+ }
681
+ else if (tagName) {
677
682
  const idTerm = element
678
683
  .replace(/>.*$/, '')
679
684
  .split(' ')
@@ -696,7 +701,9 @@ const convert = (toolName, data, result, standardResult) => {
696
701
  tagName,
697
702
  id,
698
703
  location,
699
- excerpt: element
704
+ excerpt: element,
705
+ boxID,
706
+ pathID
700
707
  };
701
708
  // Add the instance to the standard result.
702
709
  standardResult.instances.push(instance);
package/procs/testaro.js CHANGED
@@ -235,9 +235,9 @@ exports.addTestaroIDs = async page => {
235
235
  });
236
236
  };
237
237
  // Returns location data from the extract of a standard instance.
238
- exports.getLocationData = async (page, extract) => {
239
- const testaroIDArray = extract.match(/data-testaro-id="(\d+)#"/);
240
- // If the extract contains a Testaro identifier:
238
+ exports.getLocationData = async (page, excerpt) => {
239
+ const testaroIDArray = excerpt.match(/data-testaro-id="(\d+)#"/);
240
+ // If the excerpt contains a Testaro identifier:
241
241
  if (testaroIDArray) {
242
242
  const testaroID = testaroIDArray[1];
243
243
  // Return location data for the element.
package/run.js CHANGED
@@ -413,11 +413,10 @@ const launch = exports.launch = async (
413
413
  get: () => ['en-US', 'en']
414
414
  });
415
415
  });
416
- const isTestaroTest = act.type === 'test' && act.which === 'testaro';
417
- const isHTMLCSTest = act.type === 'test' && act.which === 'htmlcs';
418
- const isNuTest = act.type === 'test' && (['nuVal', 'nuVnu'].some(id => act.which === id));
419
- // If the launch is for a testaro,3 htmlcs, or Nu test act:
420
- if (isTestaroTest || isHTMLCSTest || isNuTest) {
416
+ const needsXPath = act.type === 'test'
417
+ && ['testaro', 'htmlcs', 'nuVal', 'nuVnu', 'wax'].includes(act.which);
418
+ // If the launch is for a test act that requires XPaths:
419
+ if (needsXPath) {
421
420
  // Add a script to the page to add a window method to get the XPath of an element.
422
421
  await page.addInitScript(() => {
423
422
  window.getXPath = element => {
@@ -466,7 +465,7 @@ const launch = exports.launch = async (
466
465
  });
467
466
  }
468
467
  // If the launch is for a testaro test act:
469
- if (isTestaroTest) {
468
+ if (act.type === 'test' && act.which === 'testaro') {
470
469
  // Add a script to the page to compute the accessible name of an element.
471
470
  await page.addInitScript({path: require.resolve('./dist/nameComputation.js')});
472
471
  // Add a script to the page to:
@@ -478,7 +477,7 @@ const launch = exports.launch = async (
478
477
  && typeof window.computeAccessibleName === 'function';
479
478
  return nameIsComputable ? window.computeAccessibleName(element) : '';
480
479
  };
481
- // Add a window method to return an instance.
480
+ // Add a window method to return a standard instance.
482
481
  window.getInstance = (
483
482
  element, ruleID, what, count = 1, ordinalSeverity, summaryTagName = ''
484
483
  ) => {
@@ -494,7 +493,7 @@ const launch = exports.launch = async (
494
493
  const rawExcerpt = (element.textContent.trim() || element.outerHTML.trim())
495
494
  .replace(/\s+/g, ' ');
496
495
  const excerpt = rawExcerpt.slice(0, 200);
497
- // Return an itemized instance.
496
+ // Return an itemized standard instance.
498
497
  return {
499
498
  ruleID,
500
499
  what,
package/tests/htmlcs.js CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  // IMPORTS
16
16
 
17
- // Module to add Testaro IDs to elements.
17
+ // Module to add and use unique element IDs.
18
18
  const {addTestaroIDs, getLocationData} = require('../procs/testaro');
19
19
  // Module to handle files.
20
20
  const fs = require('fs/promises');
@@ -81,7 +81,7 @@ exports.reporter = async (page, report, actIndex) => {
81
81
  result.Error = {};
82
82
  result.Warning = {};
83
83
  // For each violation:
84
- messageStrings.forEach(async string => {
84
+ for (const string of messageStrings) {
85
85
  // Split its message into severity class, rule ID, tagname, ID, rule description, and excerpt.
86
86
  const parts = string.split(/\|/, 6);
87
87
  const partCount = parts.length;
@@ -110,7 +110,7 @@ exports.reporter = async (page, report, actIndex) => {
110
110
  pathID
111
111
  });
112
112
  }
113
- });
113
+ }
114
114
  }
115
115
  return {
116
116
  data,
package/tests/wave.js CHANGED
@@ -96,30 +96,55 @@ exports.reporter = async (page, report, actIndex) => {
96
96
  // Add WCAG information from the WAVE documentation.
97
97
  const waveDocJSON = await fs.readFile('procs/wavedoc.json', 'utf8');
98
98
  const waveDoc = JSON.parse(waveDocJSON);
99
- Object.keys(categories).forEach(categoryName => {
99
+ // For each rule category:
100
+ for (const categoryName of Object.keys(categories)) {
100
101
  const category = categories[categoryName];
101
- // If any violations were reported:
102
+ // If any violations were reported in the category:
102
103
  if (
103
104
  category
104
105
  && category.items
105
106
  && Object.keys(category.items).length
106
107
  ) {
107
108
  const {items} = category;
108
- Object.keys(items).forEach(issueName => {
109
- const issueDoc = waveDoc.find((issue => issue.name === issueName));
110
- const {guidelines} = issueDoc;
111
- items[issueName].wcag = guidelines;
112
- });
109
+ // For each rule violated (named item by WAVE):
110
+ for (const ruleName of Object.keys(items)) {
111
+ const ruleDoc = waveDoc.find((rule => rule.name === ruleName));
112
+ const {guidelines} = ruleDoc;
113
+ const rule = items[ruleName];
114
+ // Add WCAG information to the rule data.
115
+ rule.wcag = guidelines;
116
+ // For each violation:
117
+ for (const index in rule.selectors) {
118
+ const selector = rule.selectors[index];
119
+ // Get an excerpt of the element.
120
+ const excerpt = await page.evaluate(selector => {
121
+ const element = document.querySelector(selector);
122
+ // If the selector matches an element:
123
+ if (element) {
124
+ // Get an excerpt of the element.
125
+ const rawExcerpt = element.textContent.trim() || element.outerHTML.trim();
126
+ const normalizedExcerpt = rawExcerpt.replace(/\s+/g, ' ');
127
+ return normalizedExcerpt.slice(0, 300);
128
+ }
129
+ else {
130
+ return '';
131
+ }
132
+ }, selector);
133
+ // Convert the violation selector to a selector-excerpt pair.
134
+ rule.selectors[index] = [selector, excerpt];
135
+ }
136
+ }
113
137
  }
114
- });
138
+ };
115
139
  // Add important data to the result.
116
140
  if (statistics) {
117
141
  data.pageTitle = statistics.pagetitle || '';
118
142
  data.pageURL = statistics.pageurl || '';
119
- data.time = statistics.time || null;
143
+ data.elapsedSeconds = statistics.time || null;
120
144
  data.creditsRemaining = statistics.creditsremaining || null;
121
145
  data.allItemCount = statistics.allitemcount || null;
122
146
  data.totalElements = statistics.totalelements || null;
147
+ data.waveURL = statistics.waveurl || '';
123
148
  }
124
149
  // Return the result.
125
150
  resolve(actResult);
package/tests/wax.js CHANGED
@@ -15,7 +15,9 @@
15
15
 
16
16
  // IMPORTS
17
17
 
18
- // WAX
18
+ // Module to add and use unique element IDs.
19
+ const {addTestaroIDs, getLocationData} = require('../procs/testaro');
20
+ // Modules to run WAX.
19
21
  const runWax = require('@wally-ax/wax-dev');
20
22
  const waxDev = {runWax};
21
23
 
@@ -26,15 +28,17 @@ exports.reporter = async (page, report, actIndex) => {
26
28
  // Initialize the act report.
27
29
  let data = {};
28
30
  let result = {};
29
- // Run WAX.
30
31
  const act = report.acts[actIndex];
31
32
  const rules = act.rules || [];
33
+ // Annotate all elements on the page with unique identifiers.
34
+ await addTestaroIDs(page);
32
35
  const pageCode = await page.content();
33
36
  const waxOptions = {
34
37
  rules,
35
38
  apiKey: process.env.WAX_KEY || ''
36
39
  };
37
40
  try {
41
+ // Run WAX.
38
42
  const actReport = await waxDev.runWax(pageCode, waxOptions);
39
43
  // If WAX failed with a string report:
40
44
  if (typeof actReport === 'string') {
@@ -54,6 +58,12 @@ exports.reporter = async (page, report, actIndex) => {
54
58
  }
55
59
  // Otherwise, i.e. if it is a successful report:
56
60
  else {
61
+ // Add location data to its excerpts.
62
+ for (const violation of actReport) {
63
+ const {element} = violation;
64
+ const elementLocation = await getLocationData(page, element);
65
+ Object.assign(violation, elementLocation);
66
+ }
57
67
  // Populate the act report.
58
68
  result = {
59
69
  violations: actReport
@@ -81,7 +91,6 @@ exports.reporter = async (page, report, actIndex) => {
81
91
  data.error = 'wax failure';
82
92
  }
83
93
  }
84
- // Return the results.
85
94
  try {
86
95
  JSON.stringify(data);
87
96
  }
@@ -92,6 +101,7 @@ exports.reporter = async (page, report, actIndex) => {
92
101
  error: message
93
102
  };
94
103
  }
104
+ // Return the results.
95
105
  return {
96
106
  data,
97
107
  result