testaro 5.9.0 → 5.9.3

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
@@ -6,7 +6,7 @@ Federated accessibility test automation
6
6
 
7
7
  Testaro is a collection of collections of web accessibility tests.
8
8
 
9
- The purpose of Testaro is to provide programmatic access to 1228 accessibility tests defined in several test packages and in Testaro itself.
9
+ The purpose of Testaro is to provide programmatic access to 1230 accessibility tests defined in several test packages and in Testaro itself.
10
10
 
11
11
  ## System requirements
12
12
 
@@ -40,8 +40,8 @@ As of this version, the counts of tests in the packages referenced above were:
40
40
  - WAVE: 110
41
41
  - Nu Html Checker: 147
42
42
  - subtotal: 612
43
- - Testaro tests: 22
44
- - grand total: 1228
43
+ - Testaro tests: 24
44
+ - grand total: 1230
45
45
 
46
46
  ## Code organization
47
47
 
@@ -234,6 +234,14 @@ This command causes Testaro to alter the `display` and `visibility` style proper
234
234
 
235
235
  The possible commands of type `test` are enumerated in the `tests` object defined in the `index.js` file.
236
236
 
237
+ A test performs operations and reports results. The results may or may not directly indicate that a page passes or fails requirements. Typically, accessibility tests report successes and failures. But a test in Testaro is defined less restrictively, so it can report any results. As one example, the Testaro `elements` test reports facts about certain elements on a page, without asserting that those facts are successes or failures.
238
+
239
+ The term “test” has two meanings for Testaro:
240
+ - A command is a test (test command) if its `type` property has the value `test`.
241
+ - A package, such as Continuum, performs multiple tests (packaged tests).
242
+
243
+ Thus, if a command of type `test` runs Continuum, Continuum performs multiple tests and reports their results.
244
+
237
245
  ###### Examples
238
246
 
239
247
  An example of a **packaged test** is:
@@ -266,7 +274,7 @@ In this case, Testaro runs the `motion` test with the specified parameters.
266
274
 
267
275
  ###### Tenon
268
276
 
269
- The `tenon` test requires two commands:
277
+ Most packaged tests require only one command, but the `tenon` test requires two commands:
270
278
  - A command of type `tenonRequest`.
271
279
  - A command of type `test` with `tenon` as the value of `which`.
272
280
 
@@ -342,7 +350,7 @@ The changes in `htmlcs/HTMLCS.js` are:
342
350
 
343
351
  ###### BBC Accessibility Standards Checker
344
352
 
345
- The BBC Accessibility Standards Checker has obsolete dependencies with security vulnerabilities. Therefore, it is not used as a dependency of Testaro. Instead, 6 of its tests are reimplemented, in some case with revisions, as Testaro tests. They are drawn from the 18 automated tests of the Checker. The other 12 tests were found too duplicative of other tests to justify reimplementation.
353
+ The BBC Accessibility Standards Checker has obsolete dependencies with security vulnerabilities. Therefore, it is not used as a dependency of Testaro. Instead, 6 of its tests are reimplemented, in some cases with revisions, as Testaro tests. They are drawn from the 18 automated tests of the Checker. The other 12 tests were found too duplicative of other tests to justify reimplementation.
346
354
 
347
355
  ##### Branching
348
356
 
package/commands.js CHANGED
@@ -153,7 +153,7 @@ exports.commands = {
153
153
  elements: [
154
154
  'Perform an elements test',
155
155
  {
156
- detailLevel: [true, 'number', '', '0 = counts, 1 = selves, 2 = also sibling nodes'],
156
+ detailLevel: [true, 'number', '', '0 to 3, to specify the level of detail'],
157
157
  tagName: [false, 'string', '', 'tag name of elements'],
158
158
  onlyVisible: [false, 'boolean', '', 'whether to exclude invisible elements'],
159
159
  attribute: [false, 'string', 'hasLength', 'required attribute or attribute=value']
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "5.9.0",
3
+ "version": "5.9.3",
4
4
  "description": "Automation of accessibility testing",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/run.js CHANGED
@@ -56,6 +56,7 @@ const tests = {
56
56
  styleDiff: 'style inconsistencies',
57
57
  tabNav: 'keyboard navigation between tab elements',
58
58
  tenon: 'Tenon',
59
+ title: 'page title',
59
60
  titledEl: 'title attributes on inappropriate elements',
60
61
  wave: 'WAVE',
61
62
  zIndex: 'z indexes'
package/tests/elements.js CHANGED
@@ -1,6 +1,11 @@
1
1
  /*
2
2
  elements
3
3
  This test reports data about specified elements.
4
+ Meanings of detailLevel values:
5
+ 0. Only total element count; no detail.
6
+ 1. Also data on each specified element.
7
+ 2. Data on each specified element also include the text content of the parent element.
8
+ 3. Data on each specified element also include data on its sibling nodes.
4
9
  */
5
10
  exports.reporter = async (page, detailLevel, tagName, onlyVisible, attribute) => {
6
11
  // Determine a selector of the specified elements.
@@ -11,118 +16,135 @@ exports.reporter = async (page, detailLevel, tagName, onlyVisible, attribute) =>
11
16
  if (onlyVisible) {
12
17
  selector += ':visible';
13
18
  }
19
+ let data = {};
14
20
  // Get the data on the elements.
15
- const data = await page.$$eval(selector, (elements, detailLevel) => {
16
- // FUNCTION DEFINITIONS START
17
- // Compacts a string.
18
- const compact = string => string.replace(/\s+/g, ' ').trim();
19
- // Gets data on the sibling nodes of an element.
20
- const getSibInfo = (node, nodeType, text) => {
21
- const sibInfo = {
22
- type: nodeType
23
- };
24
- if (nodeType === 1) {
25
- sibInfo.tagName = node.tagName;
26
- }
27
- else if (nodeType === 3) {
28
- sibInfo.text = compact(text);
29
- }
30
- return sibInfo;
31
- };
32
- // FUNCTION DEFINITIONS END
33
- // Initialize the data with the count of the specified elements.
34
- const data = {
35
- total: elements.length
36
- };
37
- // If no itemization is required:
38
- if (detailLevel === 0) {
39
- // Return the element count.
40
- return data;
41
- }
42
- // Otherwise, i.e. if itemization is required:
43
- else {
44
- // Initialize the item data.
45
- data.items = [];
46
- // For each specified element:
47
- elements.forEach(element => {
48
- // Initialize data on it.
49
- const datum = {
50
- tagName: element.tagName,
51
- code: compact(element.outerHTML),
52
- attributes: [],
53
- textContent: compact(element.textContent)
21
+ try {
22
+ data = await page.$$eval(selector, (elements, detailLevel) => {
23
+ // FUNCTION DEFINITIONS START
24
+ // Compacts a string.
25
+ const compact = string => string.replace(/\s+/g, ' ').trim();
26
+ // Gets data on the sibling nodes of an element.
27
+ const getSibInfo = (node, nodeType, text) => {
28
+ const sibInfo = {
29
+ type: nodeType
54
30
  };
55
- // For each of its attributes:
56
- for (const attribute of element.attributes) {
57
- // Add data on the attribute to the element data.
58
- const {name, value} = attribute;
59
- datum.attributes.push({
60
- name,
61
- value
62
- });
63
- // If the element has reference labels:
64
- if (name === 'aria-labelledby') {
65
- // Add their texts to the element data.
66
- const labelerIDs = value.split(/\s+/);
67
- const labelers = [];
68
- labelerIDs.forEach(id => {
69
- const labeler = document.getElementById(id);
70
- if (labeler) {
71
- labelers.push(compact(labeler.textContent));
72
- }
73
- });
74
- if (labelers.length) {
75
- datum.labelers = labelers;
76
- }
77
- }
31
+ if (nodeType === 1) {
32
+ sibInfo.tagName = node.tagName;
78
33
  }
79
- // If the element has text content:
80
- const {labels, textContent} = element;
81
- const compactContent = compact(textContent);
82
- if (compactContent) {
83
- // Add it to the element data.
84
- datum.textContent = compactContent;
34
+ else if (nodeType === 3) {
35
+ sibInfo.text = compact(text);
85
36
  }
86
- // If the element has labels:
87
- if (labels && labels.length) {
88
- // Add their texts to the element data.
89
- datum.labels = Array.from(labels).map(label => compact(label.textContent));
90
- }
91
- // If sibling itemization is required:
92
- if (detailLevel === 2) {
93
- // Add the sibling data to the element data.
94
- datum.siblings = {
95
- before: [],
96
- after: []
37
+ return sibInfo;
38
+ };
39
+ // FUNCTION DEFINITIONS END
40
+ // Initialize the data with the count of the specified elements.
41
+ const data = {
42
+ total: elements.length
43
+ };
44
+ // If no itemization is required:
45
+ if (detailLevel === 0) {
46
+ // Return the element count.
47
+ return data;
48
+ }
49
+ // Otherwise, i.e. if itemization is required:
50
+ else {
51
+ // Initialize the item data.
52
+ data.items = [];
53
+ // For each specified element:
54
+ elements.forEach(element => {
55
+ // Initialize data on it.
56
+ const parent = element.parentElement;
57
+ const datum = {
58
+ tagName: element.tagName,
59
+ parentTagName: parent ? parent.tagName : '',
60
+ code: compact(element.outerHTML),
61
+ attributes: [],
62
+ textContent: compact(element.textContent)
97
63
  };
98
- let more = element;
99
- while (more) {
100
- more = more.previousSibling;
101
- if (more) {
102
- const {nodeType, nodeValue} = more;
103
- if (! (nodeType === 3 && nodeValue === '')) {
104
- const sibInfo = getSibInfo(more, nodeType, nodeValue);
105
- datum.siblings.before.unshift(sibInfo);
64
+ // For each of its attributes:
65
+ for (const attribute of element.attributes) {
66
+ // Add data on the attribute to the element data.
67
+ const {name, value} = attribute;
68
+ datum.attributes.push({
69
+ name,
70
+ value
71
+ });
72
+ // If the element has reference labels:
73
+ if (name === 'aria-labelledby') {
74
+ // Add their texts to the element data.
75
+ const labelerIDs = value.split(/\s+/);
76
+ const labelers = [];
77
+ labelerIDs.forEach(id => {
78
+ const labeler = document.getElementById(id);
79
+ if (labeler) {
80
+ labelers.push(compact(labeler.textContent));
81
+ }
82
+ });
83
+ if (labelers.length) {
84
+ datum.labelers = labelers;
106
85
  }
107
86
  }
108
87
  }
109
- more = element;
110
- while (more) {
111
- more = more.nextSibling;
112
- if (more) {
113
- const {nodeType, textContent} = more;
114
- if (! (nodeType === 3 && textContent === '')) {
115
- const sibInfo = getSibInfo(more, nodeType, compact(textContent));
116
- datum.siblings.after.push(sibInfo);
88
+ // If the element has text content:
89
+ const {labels, textContent} = element;
90
+ const compactContent = compact(textContent);
91
+ if (compactContent) {
92
+ // Add it to the element data.
93
+ datum.textContent = compactContent;
94
+ }
95
+ // If the element has labels:
96
+ if (labels && labels.length) {
97
+ // Add their texts to the element data.
98
+ datum.labels = Array.from(labels).map(label => compact(label.textContent));
99
+ }
100
+ // If the parental text content is required:
101
+ if (detailLevel > 1) {
102
+ // Add it to the element data.
103
+ datum.parentTextContent = parent ? parent.textContent : '';
104
+ }
105
+ // If sibling itemization is required:
106
+ if (detailLevel === 3) {
107
+ // Add the sibling data to the element data.
108
+ datum.siblings = {
109
+ before: [],
110
+ after: []
111
+ };
112
+ let more = element;
113
+ while (more) {
114
+ more = more.previousSibling;
115
+ if (more) {
116
+ const {nodeType, nodeValue} = more;
117
+ if (! (nodeType === 3 && nodeValue === '')) {
118
+ const sibInfo = getSibInfo(more, nodeType, nodeValue);
119
+ datum.siblings.before.unshift(sibInfo);
120
+ }
121
+ }
122
+ }
123
+ more = element;
124
+ while (more) {
125
+ more = more.nextSibling;
126
+ if (more) {
127
+ const {nodeType, textContent} = more;
128
+ if (! (nodeType === 3 && textContent === '')) {
129
+ const sibInfo = getSibInfo(more, nodeType, compact(textContent));
130
+ datum.siblings.after.push(sibInfo);
131
+ }
117
132
  }
118
133
  }
119
134
  }
120
- }
121
- data.items.push(datum);
122
- });
123
- return data;
124
- }
125
- }, detailLevel);
135
+ data.items.push(datum);
136
+ });
137
+ return data;
138
+ }
139
+ }, detailLevel);
140
+ }
141
+ catch(error) {
142
+ console.log(`ERROR performing test (${error.message})`);
143
+ data = {
144
+ prevented: true,
145
+ error: 'ERROR performing test'
146
+ };
147
+ }
126
148
  // Return the result.
127
149
  return {result: data};
128
150
  };
package/tests/title.js ADDED
@@ -0,0 +1,8 @@
1
+ /*
2
+ title
3
+ This test reports the page title.
4
+ */
5
+ exports.reporter = async page => {
6
+ const title = await page.title();
7
+ return {result: title};
8
+ };