testaro 4.6.0 → 4.6.1

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": "4.6.0",
3
+ "version": "4.6.1",
4
4
  "description": "Automation of accessibility testing",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,90 +1,54 @@
1
1
  // Returns an object classifying the links in a page by layout.
2
2
  exports.linksByType = async page => await page.evaluateHandle(() => {
3
3
  // FUNCTION DEFINITIONS START
4
- // Returns whether an element has fluid display.
5
- const hasFluidDisplay = element => {
6
- const display = window.getComputedStyle(element).display;
7
- return display.startsWith('inline') || display.startsWith('flex');
8
- };
9
- // Returns whether an element and its children have fluid display.
10
- const isFluid = element => {
11
- if (hasFluidDisplay(element)) {
12
- return Array.from(element.children).every(child => hasFluidDisplay(child));
13
- }
14
- else {
15
- return false;
16
- }
17
- };
18
- // Returns whether all siblings of an element have fluid display.
19
- const hasFluidSiblings = element => {
20
- const preSib = element.previousElementSibling;
21
- if (preSib) {
22
- const postSib = element.nextElementSibling;
23
- if (postSib) {
24
- return isFluid(preSib) && isFluid(postSib);
25
- }
26
- else {
27
- return isFluid(preSib);
28
- }
29
- }
30
- else {
31
- const postSib = element.nextElementSibling;
32
- if (postSib) {
33
- return isFluid(postSib);
34
- }
35
- else {
36
- return true;
37
- }
38
- }
39
- };
40
4
  // Removes spacing characters from a text.
41
5
  const despace = text => text.replace(/\s/g, '');
42
- // Returns whether an element has text that is less than its nearest nonfluid ancestor’s.
43
- const hasAdjacentText = element => {
44
- // Recursively returns the first ancestor element with nonfluid display.
45
- const blockOf = node => {
46
- const parentElement = node.parentElement;
47
- if (hasFluidDisplay(parentElement)) {
48
- return blockOf(parentElement);
49
- }
50
- else {
51
- return parentElement;
52
- }
53
- };
54
- // Identify the text of the element.
55
- const elementText = despace(element.textContent);
56
- // Identify the text of its nearest nonfluid ancestor.
57
- const blockText = despace(blockOf(element).textContent);
58
- // If the element has any text:
59
- if (elementText) {
60
- // Return whether it is less than its nearest nonfluid ancestor’s.
61
- return despace(blockText).length > elementText.length;
6
+ // Returns whether a list is a list entirely of links.
7
+ const isLinkList = list => {
8
+ const listItems = Array.from(list.children);
9
+ if (listItems.length > 1) {
10
+ return listItems.length > 1 && listItems.every(item => {
11
+ if (item.tagName === 'LI') {
12
+ const {children} = item;
13
+ if (children.length === 1) {
14
+ const link = children[0];
15
+ if (link.tagName === 'A') {
16
+ const itemText = despace(item.textContent);
17
+ const linkText = despace(link.textContent);
18
+ return itemText.length === linkText.length;
19
+ }
20
+ else {
21
+ return false;
22
+ }
23
+ }
24
+ else {
25
+ return false;
26
+ }
27
+ }
28
+ else {
29
+ return false;
30
+ }
31
+ });
62
32
  }
63
- // Otherwise, i.e. if the element has no text:
64
33
  else {
65
- // Return no.
66
34
  return false;
67
35
  }
68
36
  };
69
37
  // FUNCTION DEFINITIONS END
70
- // Get the links in the page.
71
- const links = Array
72
- .from(document.body.getElementsByTagName('a'))
73
- .filter(element => ! element.hasAttribute('role'));
74
- // Initialize an object classifying the links.
75
- const linkTypes = {
76
- inline: [],
77
- block: []
78
- };
79
- // Populate it.
80
- links.forEach(link => {
81
- if (isFluid(link) && hasFluidSiblings(link) && hasAdjacentText(link)) {
82
- linkTypes.inline.push(link);
83
- }
84
- else {
85
- linkTypes.block.push(link);
38
+ // Identify the list links in the page.
39
+ const lists = Array.from(document.body.querySelectorAll('ul, ol'));
40
+ const listLinks = [];
41
+ lists.forEach(list => {
42
+ if (isLinkList(list)) {
43
+ listLinks.push(... Array.from(list.querySelectorAll('a')));
86
44
  }
87
45
  });
88
- // Return it.
89
- return linkTypes;
46
+ // Identify the adjacent links in the page.
47
+ const allLinks = Array.from(document.body.querySelectorAll('a'));
48
+ const adjacentLinks = allLinks.filter(link => ! listLinks.includes(link));
49
+ // Return the data.
50
+ return {
51
+ adjacent: adjacentLinks,
52
+ list: listLinks
53
+ };
90
54
  });
package/run.js CHANGED
@@ -36,7 +36,7 @@ const tests = {
36
36
  hover: 'hover-caused content additions',
37
37
  ibm: 'IBM Accessibility Checker',
38
38
  labClash: 'labeling inconsistencies',
39
- linkUl: 'inline-link underlining',
39
+ linkUl: 'adjacent-link underlining',
40
40
  menuNav: 'keyboard navigation between focusable menu items',
41
41
  motion: 'motion',
42
42
  radioSet: 'fieldset grouping of radio buttons',
package/tests/linkUl.js CHANGED
@@ -1,11 +1,12 @@
1
1
  /*
2
2
  linkUl
3
- This test reports failures to underline inline links. Underlining and color are the
4
- traditional style properties that identify links. Collections of links in blocks can be
5
- recognized without underlines, but inline links are difficult or impossible to distinguish
6
- visually from surrounding text if not underlined. Underlining inline links only on hover
7
- provides an indicator valuable only to mouse users, and even they must traverse the text with
8
- a mouse merely to discover which passages are links.
3
+ This test reports failures to underline links that are adjacent to nonlink text. Underlining
4
+ and color are the traditional style properties that identify links. Lists of links containing
5
+ only links can be recognized without underlines, but other links are difficult or impossible to
6
+ distinguish visually from surrounding text if not underlined. Underlining adjacent links only on
7
+ hover provides an indicator valuable only to mouse users, and even they must traverse the text
8
+ with a mouse merely to discover which passages are links. This tests treats links as adjacent
9
+ unless they are in an ordered or unordered list of at least 2 links with no other text.
9
10
  */
10
11
  exports.reporter = async (page, withItems) => {
11
12
  // Identify the links in the page, by type.
@@ -17,14 +18,14 @@ exports.reporter = async (page, withItems) => {
17
18
  // Returns a space-minimized copy of a string.
18
19
  const compact = string => string.replace(/[\t\n]/g, '').replace(/\s{2,}/g, ' ').trim();
19
20
  // FUNCTION DEFINITION END
20
- // Identify the inline links.
21
- const inLinks = linkTypes.inline;
22
- const inLinkCount = inLinks.length;
21
+ // Identify the adjacent links.
22
+ const adjacentLinks = linkTypes.adjacent;
23
+ const adjacentLinkCount = adjacentLinks.length;
23
24
  let underlined = 0;
24
- const ulInLinkTexts = [];
25
- const nulInLinkTexts = [];
25
+ const ulAdjacentLinkTexts = [];
26
+ const nulAdjacentLinkTexts = [];
26
27
  // For each of them:
27
- inLinks.forEach(link => {
28
+ adjacentLinks.forEach(link => {
28
29
  // Identify the text of the link if itemization is required.
29
30
  const text = withItems ? compact(link.textContent) : '';
30
31
  // If it is underlined:
@@ -33,22 +34,24 @@ exports.reporter = async (page, withItems) => {
33
34
  underlined++;
34
35
  // If required, add its text to the array of their texts.
35
36
  if (withItems) {
36
- ulInLinkTexts.push(text);
37
+ ulAdjacentLinkTexts.push(text);
37
38
  }
38
39
  }
39
40
  // Otherwise, if it is not underlined and itemization is required:
40
41
  else if (withItems) {
41
42
  // Add its text to the array of texts of non-underlined inline links.
42
- nulInLinkTexts.push(text);
43
+ nulAdjacentLinkTexts.push(text);
43
44
  }
44
45
  });
45
46
  // Get the percentage of underlined links among all inline links.
46
- const underlinedPercent = inLinkCount ? Math.floor(100 * underlined / inLinkCount) : 'N/A';
47
+ const underlinedPercent = adjacentLinkCount
48
+ ? Math.floor(100 * underlined / adjacentLinkCount)
49
+ : 'N/A';
47
50
  const data = {
48
51
  totals: {
49
- links: inLinks.length + linkTypes.block.length,
50
- inline: {
51
- total: inLinkCount,
52
+ links: adjacentLinks.length + linkTypes.list.length,
53
+ adjacent: {
54
+ total: adjacentLinkCount,
52
55
  underlined,
53
56
  underlinedPercent
54
57
  }
@@ -56,8 +59,8 @@ exports.reporter = async (page, withItems) => {
56
59
  };
57
60
  if (withItems) {
58
61
  data.items = {
59
- underlined: ulInLinkTexts,
60
- notUnderlined: nulInLinkTexts
62
+ underlined: ulAdjacentLinkTexts,
63
+ notUnderlined: nulAdjacentLinkTexts
61
64
  };
62
65
  }
63
66
  return {result: data};
@@ -1,12 +1,12 @@
1
1
  /*
2
2
  styleDiff
3
3
  This test reports style differences among links, buttons, and headings. It assumes
4
- that an accessible page employs few or only one style for inline links, and likewise
5
- for non-inline links, buttons, and headings at each level. The test considers only
4
+ that an accessible page employs few or only one style for adjacent links, and likewise
5
+ for list links, buttons, and headings at each level. The test considers only
6
6
  particular style properties, listed in the 'mainStyles' and 'headingStyles' arrays.
7
7
  */
8
8
  exports.reporter = async (page, withItems) => {
9
- // Get an object with arrays of block and inline links as properties.
9
+ // Get an object with arrays of list and adjacent links as properties.
10
10
  const linkTypes = await require('../procs/linksByType').linksByType(page);
11
11
  return await page.$eval('body', (body, args) => {
12
12
  const withItems = args[0];
@@ -51,8 +51,8 @@ exports.reporter = async (page, withItems) => {
51
51
  const elementClasses = {
52
52
  headings: {},
53
53
  other: {
54
- aInline: linkTypes.inline,
55
- aBlock: linkTypes.block
54
+ aAdjacent: linkTypes.adjacent,
55
+ aList: linkTypes.list
56
56
  }
57
57
  };
58
58
  // For each heading tag name:
package/tests/tabNav.js CHANGED
@@ -4,70 +4,69 @@
4
4
  Standards are based on https://www.w3.org/TR/wai-aria-practices-1.1/#tabpanel.
5
5
  */
6
6
 
7
- // CONSTANTS
7
+ // FUNCTIONS
8
8
 
9
- const data = {
10
- totals: {
11
- navigations: {
12
- all: {
13
- total: 0,
14
- correct: 0,
15
- incorrect: 0
16
- },
17
- specific: {
18
- tab: {
19
- total: 0,
20
- correct: 0,
21
- incorrect: 0
22
- },
23
- left: {
24
- total: 0,
25
- correct: 0,
26
- incorrect: 0
27
- },
28
- right: {
29
- total: 0,
30
- correct: 0,
31
- incorrect: 0
32
- },
33
- up: {
34
- total: 0,
35
- correct: 0,
36
- incorrect: 0
37
- },
38
- down: {
39
- total: 0,
40
- correct: 0,
41
- incorrect: 0
42
- },
43
- home: {
9
+ // Tests tab-list navigation and reports results.
10
+ exports.reporter = async (page, withItems) => {
11
+ // Initialize the results.
12
+ const data = {
13
+ totals: {
14
+ navigations: {
15
+ all: {
44
16
  total: 0,
45
17
  correct: 0,
46
18
  incorrect: 0
47
19
  },
48
- end: {
49
- total: 0,
50
- correct: 0,
51
- incorrect: 0
20
+ specific: {
21
+ tab: {
22
+ total: 0,
23
+ correct: 0,
24
+ incorrect: 0
25
+ },
26
+ left: {
27
+ total: 0,
28
+ correct: 0,
29
+ incorrect: 0
30
+ },
31
+ right: {
32
+ total: 0,
33
+ correct: 0,
34
+ incorrect: 0
35
+ },
36
+ up: {
37
+ total: 0,
38
+ correct: 0,
39
+ incorrect: 0
40
+ },
41
+ down: {
42
+ total: 0,
43
+ correct: 0,
44
+ incorrect: 0
45
+ },
46
+ home: {
47
+ total: 0,
48
+ correct: 0,
49
+ incorrect: 0
50
+ },
51
+ end: {
52
+ total: 0,
53
+ correct: 0,
54
+ incorrect: 0
55
+ }
52
56
  }
57
+ },
58
+ tabElements: {
59
+ total: 0,
60
+ correct: 0,
61
+ incorrect: 0
62
+ },
63
+ tabLists: {
64
+ total: 0,
65
+ correct: 0,
66
+ incorrect: 0
53
67
  }
54
- },
55
- tabElements: {
56
- total: 0,
57
- correct: 0,
58
- incorrect: 0
59
- },
60
- tabLists: {
61
- total: 0,
62
- correct: 0,
63
- incorrect: 0
64
68
  }
65
- }
66
- };
67
-
68
- // FUNCTIONS
69
-
70
- exports.reporter = async (page, withItems) => {
69
+ };
71
70
  if (withItems) {
72
71
  data.tabElements = {
73
72
  incorrect: [],
@@ -10,52 +10,52 @@
10
10
  {
11
11
  "type": "url",
12
12
  "which": "__targets__/linkUl/good.html",
13
- "what": "page with underlined inline links"
13
+ "what": "page with underlined adjacent links"
14
14
  },
15
15
  {
16
16
  "type": "test",
17
17
  "which": "linkUl",
18
- "what": "link underlining",
18
+ "what": "adjacent-link underlining",
19
19
  "withItems": false,
20
20
  "expect": [
21
21
  ["totals.links", "=", 6],
22
- ["totals.inline.total", "=", 2],
23
- ["totals.inline.underlined", "=", 2],
24
- ["totals.inline.underlinedPercent", "=", 100]
22
+ ["totals.adjacent.total", "=", 2],
23
+ ["totals.adjacent.underlined", "=", 2],
24
+ ["totals.adjacent.underlinedPercent", "=", 100]
25
25
  ]
26
26
  },
27
27
  {
28
28
  "type": "url",
29
29
  "which": "__targets__/linkUl/bad.html",
30
- "what": "page without underlined inline links"
30
+ "what": "page with nonunderlined adjacent links"
31
31
  },
32
32
  {
33
33
  "type": "test",
34
34
  "which": "linkUl",
35
- "what": "link underlining",
35
+ "what": "adjacent-link underlining",
36
36
  "withItems": false,
37
37
  "expect": [
38
- ["totals.links", "=", 2],
39
- ["totals.inline.total", "=", 2],
40
- ["totals.inline.underlined", "=", 0],
41
- ["totals.inline.underlinedPercent", "=", 0]
38
+ ["totals.links", "=", 6],
39
+ ["totals.adjacent.total", "=", 6],
40
+ ["totals.adjacent.underlined", "=", 0],
41
+ ["totals.adjacent.underlinedPercent", "=", 0]
42
42
  ]
43
43
  },
44
44
  {
45
45
  "type": "url",
46
46
  "which": "__targets__/linkUl/na.html",
47
- "what": "page without inline links"
47
+ "what": "page without adjacent links"
48
48
  },
49
49
  {
50
50
  "type": "test",
51
51
  "which": "linkUl",
52
- "what": "link underlining",
52
+ "what": "adjacent-link underlining",
53
53
  "withItems": false,
54
54
  "expect": [
55
55
  ["totals.links", "=", 2],
56
- ["totals.inline.total", "=", 0],
57
- ["totals.inline.underlined", "=", 0],
58
- ["totals.inline.underlinedPercent", "=", "N/A"]
56
+ ["totals.adjacent.total", "=", 0],
57
+ ["totals.adjacent.underlined", "=", 0],
58
+ ["totals.adjacent.underlinedPercent", "=", "N/A"]
59
59
  ]
60
60
  }
61
61
  ]
@@ -18,13 +18,13 @@
18
18
  "what": "styleDiff",
19
19
  "withItems": false,
20
20
  "expect": [
21
- ["totals.aInline.total", "=", 2],
22
- ["totals.aBlock.total", "=", 2],
21
+ ["totals.aAdjacent.total", "=", 2],
22
+ ["totals.aList.total", "=", 2],
23
23
  ["totals.button.total", "=", 2],
24
24
  ["totals.h1.total", "=", 1],
25
25
  ["totals.h2.total", "=", 4],
26
- ["totals.aInline.subtotals"],
27
- ["totals.aBlock.subtotals"],
26
+ ["totals.aAdjacent.subtotals"],
27
+ ["totals.aList.subtotals"],
28
28
  ["totals.button.subtotals"],
29
29
  ["totals.h1.subtotals"],
30
30
  ["totals.h2.subtotals"]
@@ -41,15 +41,15 @@
41
41
  "what": "styleDiff",
42
42
  "withItems": false,
43
43
  "expect": [
44
- ["totals.aInline.total", "=", 2],
45
- ["totals.aBlock.total", "=", 2],
44
+ ["totals.aAdjacent.total", "=", 2],
45
+ ["totals.aList.total", "=", 2],
46
46
  ["totals.button.total", "=", 2],
47
47
  ["totals.h1.total", "=", 1],
48
48
  ["totals.h2.total", "=", 4],
49
- ["totals.aInline.subtotals.0", "=", 1],
50
- ["totals.aInline.subtotals.1", "=", 1],
51
- ["totals.aBlock.subtotals.0", "=", 1],
52
- ["totals.aBlock.subtotals.1", "=", 1],
49
+ ["totals.aAdjacent.subtotals.0", "=", 1],
50
+ ["totals.aAdjacent.subtotals.1", "=", 1],
51
+ ["totals.aList.subtotals.0", "=", 1],
52
+ ["totals.aList.subtotals.1", "=", 1],
53
53
  ["totals.button.subtotals.0", "=", 1],
54
54
  ["totals.button.subtotals.1", "=", 1],
55
55
  ["totals.h1.subtotals"],
@@ -2,15 +2,34 @@
2
2
  <html lang="en-US">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Page without underlined inline links</title>
5
+ <title>Page without underlined adjacent links</title>
6
6
  <meta name="description" content="tester">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <style>
9
+ .nude > li > a {
10
+ text-decoration: none;
11
+ }
12
+ </style>
8
13
  </head>
9
14
  <body>
10
15
  <main>
11
- <h1>Page without underlined inline links</h1>
12
- <p>This paragraph contains an inline link to <a style="text-decoration: overline" href="https://en.wikipedia.org">English information</a> that has an overline instead of an underline.</p>
13
- <p>This paragraph contains an inline link to <a style="text-decoration: none" href="https://fr.wikipedia.org">French information</a> without any underline.</p>
16
+ <h1>Page without underlined adjacent links</h1>
17
+ <p>This paragraph contains an adjacent link to <a style="text-decoration: overline" href="https://en.wikipedia.org">English information</a> that has an overline instead of an underline.</p>
18
+ <p>This paragraph contains an adjacent link to <a style="text-decoration: none" href="https://fr.wikipedia.org">French information</a> without any underline.</p>
19
+ <p>This paragraph introduces a list of nonunderlined links, but it contains only 1 link, so that link fails to be classified as a list link.</p>
20
+ <ul class="nude"</ul>
21
+ <li><a href="https://eus.wikipedia.org">Basque information</a></li>
22
+ </ul>
23
+ <p>This paragraph introduces a list of nonunderlined links, but it contains an item that is not a link, so its link fails to be classified as a list link.</p>
24
+ <ul class="nude">
25
+ <li><span>Spanish information is not available</span></li>
26
+ <li><a href="https://eo.wikipedia.org">Esperanto information</a></li>
27
+ </ul>
28
+ <p>This paragraph introduces a list of nonunderlined links, but it contains additional text, so its links fail to be classified as a list link.</p>
29
+ <ul class="nude">
30
+ <li><a href="https://fr.wikipedia.org">French information</a> is available, as well as</li>
31
+ <li><a href="https://tr.wikipedia.org">Turkish information</a></li>
32
+ </ul>
14
33
  </main>
15
34
  </body>
16
35
  </html>
@@ -2,7 +2,7 @@
2
2
  <html lang="en-US">
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Page with underlined inline links</title>
5
+ <title>Page with underlined adjacent links</title>
6
6
  <meta name="description" content="tester">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1">
8
8
  <style>
@@ -13,14 +13,14 @@
13
13
  </head>
14
14
  <body>
15
15
  <main>
16
- <h1>Page with underlined inline links</h1>
17
- <p>This page contains inline links to <a href="https://en.wikipedia.org">English information</a> and <a style="text-decoration: underline wavy 2px" href="https://fr.wikipedia.org">French information</a>. The latter is weird, but still an underline.</p>
18
- <p>The following links, however, are not inline, so can be (and are) devoid of underlines.</p>
16
+ <h1>Page with underlined adjacent links</h1>
17
+ <p>This page contains adjacent links to <a href="https://en.wikipedia.org">English information</a> and <a style="text-decoration: underline wavy 2px" href="https://fr.wikipedia.org">French information</a>. The latter is weird, but still an underline.</p>
18
+ <p>The following links, however, are not adjacent, so can be (and are) devoid of underlines.</p>
19
19
  <ul class="nude">
20
20
  <li><a href="https://sp.wikipedia.org">Spanish information</a></li>
21
21
  <li><a href="https://eo.wikipedia.org">Esperanto information</a></li>
22
22
  </ul>
23
- <p>The following links are not inline, so can be devoid of underlines, but still have them.</p>
23
+ <p>The following links are not adjacent, so are permitted to be devoid of underlines, but still have them.</p>
24
24
  <ul>
25
25
  <li><a href="https://eus.wikipedia.org">Basque information</a></li>
26
26
  <li><a href="https://tr.wikipedia.org">Turkish information</a></li>
@@ -8,9 +8,9 @@
8
8
  </head>
9
9
  <body>
10
10
  <main>
11
- <h1>Page without inline links</h1>
12
- <p>This page contains no inline links.</p>
13
- <p>The following links are not inline.</p>
11
+ <h1>Page without adjacent links</h1>
12
+ <p>This page contains list links but no adjacent links.</p>
13
+ <p>The following links are list links.</p>
14
14
  <ul>
15
15
  <li><a href="https://eus.wikipedia.org">Basque information</a></li>
16
16
  <li><a href="https://tr.wikipedia.org">Turkish information</a></li>