testaro 30.0.8 → 32.0.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.
Files changed (212) hide show
  1. package/CONTRIBUTING.md +26 -4
  2. package/LICENSE +1 -1
  3. package/README.md +24 -2
  4. package/aceconfig.js +27 -0
  5. package/actSpecs.js +28 -1
  6. package/call.js +22 -1
  7. package/data/template.js +22 -0
  8. package/dirWatch.js +22 -0
  9. package/package.json +1 -1
  10. package/procs/aslint.js +24 -0
  11. package/procs/getLocatorData.js +29 -1
  12. package/procs/getSource.js +30 -3
  13. package/procs/isInlineLink.js +23 -0
  14. package/procs/operable.js +23 -2
  15. package/procs/sample.js +22 -0
  16. package/procs/standardize.js +28 -7
  17. package/procs/tellServer.js +24 -2
  18. package/procs/testaro.js +26 -1
  19. package/procs/visChange.js +22 -0
  20. package/run.js +373 -83
  21. package/testaro/allCaps.js +22 -0
  22. package/testaro/allHidden.js +22 -0
  23. package/testaro/allSlanted.js +22 -0
  24. package/testaro/attVal.js +22 -0
  25. package/testaro/autocomplete.js +22 -0
  26. package/testaro/bulk.js +22 -0
  27. package/testaro/buttonMenu.js +22 -0
  28. package/testaro/distortion.js +22 -0
  29. package/testaro/docType.js +22 -0
  30. package/testaro/dupAtt.js +22 -0
  31. package/testaro/elements.js +22 -0
  32. package/testaro/embAc.js +22 -0
  33. package/testaro/filter.js +22 -0
  34. package/testaro/focAll.js +22 -0
  35. package/testaro/focInd.js +22 -0
  36. package/testaro/focOp.js +22 -0
  37. package/testaro/focVis.js +22 -0
  38. package/testaro/headEl.js +22 -0
  39. package/testaro/headingAmb.js +22 -0
  40. package/testaro/hovInd.js +21 -24
  41. package/testaro/hover.js +22 -0
  42. package/testaro/labClash.js +22 -0
  43. package/testaro/lineHeight.js +22 -0
  44. package/testaro/linkAmb.js +22 -0
  45. package/testaro/linkTitle.js +22 -0
  46. package/testaro/linkUl.js +22 -0
  47. package/testaro/miniText.js +22 -0
  48. package/testaro/motion.js +22 -0
  49. package/testaro/nonTable.js +22 -0
  50. package/testaro/opFoc.js +22 -0
  51. package/testaro/pseudoP.js +25 -3
  52. package/testaro/radioSet.js +22 -0
  53. package/testaro/role.js +22 -0
  54. package/testaro/styleDiff.js +80 -1
  55. package/testaro/tabNav.js +99 -2
  56. package/testaro/targetSize.js +22 -0
  57. package/testaro/textNodes.js +25 -3
  58. package/testaro/title.js +22 -0
  59. package/testaro/zIndex.js +22 -0
  60. package/tests/alfa.js +34 -12
  61. package/tests/aslint.js +55 -17
  62. package/tests/axe.js +35 -9
  63. package/tests/htmlcs.js +109 -78
  64. package/tests/ibm.js +111 -45
  65. package/tests/nuVal.js +39 -9
  66. package/tests/qualWeb.js +49 -25
  67. package/tests/testaro.js +50 -22
  68. package/tests/wave.js +36 -10
  69. package/validation/executors/run.js +26 -2
  70. package/validation/executors/test.js +27 -3
  71. package/validation/executors/tests.js +26 -2
  72. package/validation/executors/watchDir.js +26 -2
  73. package/validation/executors/watchNet.js +26 -2
  74. package/validation/jobs/todo/README.md +22 -0
  75. package/validation/tests/targets/adbID/index.html +21 -0
  76. package/validation/tests/targets/allCaps/index.html +21 -0
  77. package/validation/tests/targets/allHidden/ariaHiddenBody.html +21 -0
  78. package/validation/tests/targets/allHidden/good.html +21 -0
  79. package/validation/tests/targets/allHidden/hiddenMain.html +21 -0
  80. package/validation/tests/targets/allHidden/mixedHidden.html +22 -1
  81. package/validation/tests/targets/allHidden/noBody.html +21 -0
  82. package/validation/tests/targets/allHidden/noMain.html +21 -0
  83. package/validation/tests/targets/allHidden/noneDoc.html +21 -0
  84. package/validation/tests/targets/allHidden/visHiddenMain.html +21 -0
  85. package/validation/tests/targets/allSlanted/index.html +21 -0
  86. package/validation/tests/targets/altScheme/index.html +21 -0
  87. package/validation/tests/targets/attVal/bad.html +21 -0
  88. package/validation/tests/targets/attVal/good.html +21 -0
  89. package/validation/tests/targets/autocomplete/bad.html +21 -0
  90. package/validation/tests/targets/autocomplete/good.html +21 -0
  91. package/validation/tests/targets/bulk/bad.html +21 -0
  92. package/validation/tests/targets/bulk/good.html +21 -0
  93. package/validation/tests/targets/buttonMenu/bad.html +21 -0
  94. package/validation/tests/targets/buttonMenu/bad.js +27 -0
  95. package/validation/tests/targets/buttonMenu/good.html +21 -0
  96. package/validation/tests/targets/buttonMenu/good.js +27 -0
  97. package/validation/tests/targets/buttonMenu/style.css +27 -0
  98. package/validation/tests/targets/captionLoc/index.html +21 -0
  99. package/validation/tests/targets/datalistRef/index.html +21 -0
  100. package/validation/tests/targets/distortion/index.html +21 -0
  101. package/validation/tests/targets/docType/bad.html +21 -0
  102. package/validation/tests/targets/docType/good.html +21 -0
  103. package/validation/tests/targets/dupAtt/bad.html +21 -0
  104. package/validation/tests/targets/dupAtt/good.html +21 -0
  105. package/validation/tests/targets/elements/index.html +21 -0
  106. package/validation/tests/targets/embAc/bad.html +21 -0
  107. package/validation/tests/targets/embAc/good.html +21 -0
  108. package/validation/tests/targets/filter/bad.html +21 -0
  109. package/validation/tests/targets/filter/good.html +21 -0
  110. package/validation/tests/targets/focAll/good.html +21 -0
  111. package/validation/tests/targets/focAll/less.html +21 -0
  112. package/validation/tests/targets/focAll/more.html +21 -0
  113. package/validation/tests/targets/focInd/bad.html +21 -0
  114. package/validation/tests/targets/focInd/good.html +21 -0
  115. package/validation/tests/targets/focOp/bad.html +21 -0
  116. package/validation/tests/targets/focOp/good.html +21 -0
  117. package/validation/tests/targets/focVis/index.html +21 -0
  118. package/validation/tests/targets/headEl/index.html +21 -0
  119. package/validation/tests/targets/headingAmb/index.html +21 -0
  120. package/validation/tests/targets/hovInd/index.html +21 -0
  121. package/validation/tests/targets/hover/bad.html +21 -0
  122. package/validation/tests/targets/hover/good.html +21 -0
  123. package/validation/tests/targets/hr/index.html +21 -0
  124. package/validation/tests/targets/imageLink/index.html +21 -0
  125. package/validation/tests/targets/labClash/bad.html +21 -0
  126. package/validation/tests/targets/labClash/good.html +21 -0
  127. package/validation/tests/targets/legendLoc/index.html +21 -0
  128. package/validation/tests/targets/lineHeight/index.html +21 -0
  129. package/validation/tests/targets/linkAmb/index.html +21 -0
  130. package/validation/tests/targets/linkExt/index.html +21 -0
  131. package/validation/tests/targets/linkOldAtt/index.html +21 -0
  132. package/validation/tests/targets/linkTitle/index.html +21 -0
  133. package/validation/tests/targets/linkTo/index.html +21 -0
  134. package/validation/tests/targets/linkUl/bad.html +21 -0
  135. package/validation/tests/targets/linkUl/good.html +21 -0
  136. package/validation/tests/targets/linkUl/na.html +21 -0
  137. package/validation/tests/targets/miniText/index.html +21 -0
  138. package/validation/tests/targets/motion/bad.css +27 -0
  139. package/validation/tests/targets/motion/bad.html +21 -0
  140. package/validation/tests/targets/motion/good.html +21 -0
  141. package/validation/tests/targets/nonTable/index.html +21 -0
  142. package/validation/tests/targets/opFoc/bad.html +21 -0
  143. package/validation/tests/targets/opFoc/good.html +21 -0
  144. package/validation/tests/targets/optRoleSel/index.html +21 -0
  145. package/validation/tests/targets/phOnly/index.html +21 -0
  146. package/validation/tests/targets/pseudoP/index.html +21 -0
  147. package/validation/tests/targets/radioSet/bad.html +21 -0
  148. package/validation/tests/targets/radioSet/good.html +21 -0
  149. package/validation/tests/targets/role/bad.html +21 -0
  150. package/validation/tests/targets/role/good.html +21 -0
  151. package/validation/tests/targets/secHeading/index.html +21 -0
  152. package/validation/tests/targets/styleDiff/bad.html +21 -0
  153. package/validation/tests/targets/styleDiff/good.html +21 -0
  154. package/validation/tests/targets/tabNav/bad.html +21 -0
  155. package/validation/tests/targets/tabNav/bad.js +27 -0
  156. package/validation/tests/targets/tabNav/good.html +21 -0
  157. package/validation/tests/targets/tabNav/good.js +27 -0
  158. package/validation/tests/targets/tabNav/style.css +27 -0
  159. package/validation/tests/targets/targetSize/index.html +21 -0
  160. package/validation/tests/targets/textNodes/index.html +21 -0
  161. package/validation/tests/targets/textSem/index.html +21 -0
  162. package/validation/tests/targets/title/bad.html +21 -0
  163. package/validation/tests/targets/title/good.html +21 -0
  164. package/validation/tests/targets/titledEl/index.html +21 -0
  165. package/validation/tests/targets/zIndex/bad.html +21 -0
  166. package/validation/tests/targets/zIndex/good.html +21 -0
  167. package/validation/validateTest.js +39 -3
  168. package/validation/watch/done/README.md +23 -1
  169. package/validation/watch/todo/README.md +23 -1
  170. package/watch.js +32 -7
  171. package/call-old.js +0 -86
  172. package/procs/allText.js +0 -76
  173. package/procs/allVis.js +0 -17
  174. package/procs/getTextNodes.js +0 -39
  175. package/procs/linksByType.js +0 -54
  176. package/procs/nav.js +0 -259
  177. package/procs/textOf.txt +0 -73
  178. package/test copy.js +0 -38
  179. package/validation/tests/old/allCaps.json +0 -102
  180. package/validation/tests/old/allHidden.json +0 -314
  181. package/validation/tests/old/attVal.json +0 -60
  182. package/validation/tests/old/autocomplete.json +0 -51
  183. package/validation/tests/old/bulk.json +0 -48
  184. package/validation/tests/old/docType.json +0 -46
  185. package/validation/tests/old/dupAtt.json +0 -51
  186. package/validation/tests/old/elements.json +0 -140
  187. package/validation/tests/old/embAc.json +0 -54
  188. package/validation/tests/old/filter.json +0 -55
  189. package/validation/tests/old/focAll.json +0 -68
  190. package/validation/tests/old/focInd.json +0 -69
  191. package/validation/tests/old/focOp.json +0 -62
  192. package/validation/tests/old/focVis.json +0 -35
  193. package/validation/tests/old/hover.json +0 -118
  194. package/validation/tests/old/labClash.json +0 -52
  195. package/validation/tests/old/linkTo.json +0 -35
  196. package/validation/tests/old/linkUl.json +0 -71
  197. package/validation/tests/old/menuNav.json +0 -106
  198. package/validation/tests/old/miniText.json +0 -36
  199. package/validation/tests/old/motion.json +0 -62
  200. package/validation/tests/old/nonTable.json +0 -37
  201. package/validation/tests/old/radioSet.json +0 -52
  202. package/validation/tests/old/role.json +0 -60
  203. package/validation/tests/old/styleDiff.json +0 -71
  204. package/validation/tests/old/tabNav.json +0 -106
  205. package/validation/tests/old/temp.js +0 -28
  206. package/validation/tests/old/textNodes.json +0 -98
  207. package/validation/tests/old/title.json +0 -46
  208. package/validation/tests/old/titledEl.json +0 -37
  209. package/validation/tests/old/zIndex.json +0 -49
  210. package/validation/tests/targets/tabNav/goodMoz.js +0 -206
  211. package/watch-old.js +0 -275
  212. package/watch-temp.js +0 -45
package/tests/aslint.js CHANGED
@@ -1,3 +1,25 @@
1
+ /*
2
+ © 2023 CVS Health and/or one of its affiliates. All rights reserved.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
21
+ */
22
+
1
23
  /*
2
24
  aslint
3
25
  This test implements the ASLint ruleset for accessibility.
@@ -12,15 +34,18 @@ const fs = require('fs/promises');
12
34
 
13
35
  // Conducts and reports an ASLint test.
14
36
  exports.reporter = async (page, options) => {
15
- // Initialize the report.
37
+ // Initialize the act report.
16
38
  let data = {};
39
+ let result = {};
17
40
  // Get the ASLint runner and bundle scripts.
18
41
  const aslintRunner = await fs.readFile(`${__dirname}/../procs/aslint.js`, 'utf8');
19
42
  const aslintBundle = await fs.readFile(
20
43
  `${__dirname}/../node_modules/aslint-testaro/aslint.bundle.js`, 'utf8'
21
44
  );
22
45
  // Get the nonce, if any.
23
- const {scriptNonce} = options;
46
+ const {report} = options;
47
+ const {jobData} = report;
48
+ const scriptNonce = jobData && jobData.lastScriptNonce;
24
49
  // Inject the ASLint bundle and runner into the page.
25
50
  await page.evaluate(args => {
26
51
  const {scriptNonce, aslintBundle, aslintRunner} = args;
@@ -43,41 +68,54 @@ exports.reporter = async (page, options) => {
43
68
  document.body.insertAdjacentElement('beforeend', runnerEl);
44
69
  }, {scriptNonce, aslintBundle, aslintRunner})
45
70
  .catch(error => {
46
- console.log(`ERROR: ASLint injection failed (${error.message.slice(0, 400)})`);
71
+ const message = `ERROR: ASLint injection failed (${error.message.slice(0, 400)})`;
72
+ console.log(message);
47
73
  data.prevented = true;
48
- data.error = 'ERROR: ASLint injection failed';
74
+ data.error = message;
49
75
  });
50
76
  // If the injection succeeded:
77
+ const reportLoc = page.locator('#aslintResult');
51
78
  if (! data.prevented) {
52
79
  // Wait for the test results.
53
- const reportLoc = page.locator('#aslintResult');
54
80
  await reportLoc.waitFor({
55
81
  state: 'attached',
56
- timeout: 10000
82
+ timeout: 30000
83
+ })
84
+ .catch(error => {
85
+ const message = `ERROR: Results timed out (${error.message.slice(0, 400)})`;
86
+ console.log(message);
87
+ data.prevented = true;
88
+ data.error = message;
57
89
  });
90
+ }
91
+ // If the results arrived in time:
92
+ if (! data.prevented) {
58
93
  // Get them.
59
- const report = await reportLoc.textContent();
60
- // Populate the tool report.
61
- data = JSON.parse(report);
94
+ const actReport = await reportLoc.textContent();
95
+ // Populate the act report.
96
+ result = JSON.parse(actReport);
62
97
  // Delete irrelevant properties from the tool report details.
63
- if (data.rules) {
64
- Object.keys(data.rules).forEach(ruleID => {
65
- if (['passed', 'skipped'].includes(data.rules[ruleID].status.type)) {
66
- delete data.rules[ruleID];
98
+ if (result.rules) {
99
+ Object.keys(result.rules).forEach(ruleID => {
100
+ if (['passed', 'skipped'].includes(result.rules[ruleID].status.type)) {
101
+ delete result.rules[ruleID];
67
102
  }
68
103
  });
69
104
  }
70
105
  }
71
- // Return the result.
106
+ // Return the act report.
72
107
  try {
73
108
  JSON.stringify(data);
74
109
  }
75
110
  catch(error) {
76
- console.log(`ERROR: ASLint result cannot be made JSON (${error.message.slice(0, 200)})`);
111
+ const message = `ERROR: ASLint result cannot be made JSON (${error.message.slice(0, 200)})`;
77
112
  data = {
78
113
  prevented: true,
79
- error: `ERROR: ASLint result cannot be made JSON (${error.message.slice(0, 200)})`
114
+ error: message
80
115
  };
81
116
  }
82
- return {result: data};
117
+ return {
118
+ data,
119
+ result
120
+ };
83
121
  };
package/tests/axe.js CHANGED
@@ -1,3 +1,25 @@
1
+ /*
2
+ © 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
21
+ */
22
+
1
23
  /*
2
24
  axe
3
25
  This test implements the axe-core ruleset for accessibility.
@@ -28,8 +50,9 @@ const {injectAxe, getAxeResults} = require('axe-playwright');
28
50
  // Conducts and reports an Axe test.
29
51
  exports.reporter = async (page, options) => {
30
52
  const {detailLevel, rules} = options;
31
- // Initialize the report.
53
+ // Initialize the act report.
32
54
  let data = {};
55
+ let result = {};
33
56
  // Inject axe-core into the page.
34
57
  await injectAxe(page)
35
58
  .catch(error => {
@@ -58,7 +81,7 @@ exports.reporter = async (page, options) => {
58
81
  const {inapplicable, passes, incomplete, violations} = axeReport;
59
82
  if (violations) {
60
83
  // Initialize the result.
61
- data.totals = {
84
+ result.totals = {
62
85
  rulesNA: 0,
63
86
  rulesPassed: 0,
64
87
  rulesWarned: 0,
@@ -76,9 +99,9 @@ exports.reporter = async (page, options) => {
76
99
  critical: 0
77
100
  }
78
101
  };
79
- data.details = axeReport;
102
+ result.details = axeReport;
80
103
  // Populate the totals.
81
- const {totals} = data;
104
+ const {totals} = result;
82
105
  totals.rulesNA = inapplicable.length;
83
106
  totals.rulesPassed = passes.length;
84
107
  incomplete.forEach(rule => {
@@ -104,8 +127,7 @@ exports.reporter = async (page, options) => {
104
127
  else {
105
128
  // Report this.
106
129
  data.prevented = true;
107
- data.error = 'ERROR: axe failed';
108
- console.log('ERROR: axe failed');
130
+ data.error = 'ERROR: Act failed';
109
131
  }
110
132
  }
111
133
  // Return the result.
@@ -113,11 +135,15 @@ exports.reporter = async (page, options) => {
113
135
  JSON.stringify(data);
114
136
  }
115
137
  catch(error) {
116
- console.log(`ERROR: axe result cannot be made JSON (${error.message})`);
138
+ const message = `ERROR: Axe result cannot be made JSON (${error.message})`;
139
+ console.log(message);
117
140
  data = {
118
141
  prevented: true,
119
- error: `ERROR: axe result cannot be made JSON (${error.message})`
142
+ error: message
120
143
  };
121
144
  }
122
- return {result: data};
145
+ return {
146
+ data,
147
+ result
148
+ };
123
149
  };
package/tests/htmlcs.js CHANGED
@@ -1,94 +1,125 @@
1
+ /*
2
+ © 2022–2023 CVS Health and/or one of its affiliates. All rights reserved.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
21
+ */
22
+
1
23
  /*
2
24
  htmlcs
3
25
  This test implements the HTML CodeSniffer ruleset.
4
26
  */
5
27
 
28
+ // IMPORTS
29
+
30
+ // Module to handle files.
31
+ const fs = require('fs/promises');
32
+
6
33
  // FUNCTIONS
7
- // Runs HTML CodeSniffer on the page.
34
+
35
+ // Runs HTML CodeSniffer on the page and returns an act report.
8
36
  exports.reporter = async (page, options) => {
9
- const {rules} = options;
37
+ const {report, rules} = options;
38
+ const data = {};
10
39
  const result = {};
11
- // Add the HTMLCS script to the page.
12
- await page.addScriptTag({
13
- path: `${__dirname}/../htmlcs/HTMLCS.js`
14
- })
15
- .catch(error => {
16
- console.log(`ERROR adding the htmlcs script to the page (${error.message})`);
17
- result.prevented = true;
18
- result.error = 'ERROR adding the htmlcs script to the page';
19
- });
20
- if (! result.prevented) {
21
- let messageStrings = [];
22
- // Define the rules to be employed as those of WCAG 2 level AAA.
23
- for (const standard of ['WCAG2AAA']) {
24
- const nextIssues = await page.evaluate(args => {
25
- const standard = args[0];
26
- const rules = args[1];
27
- // If only some rules are to be employed:
28
- if (rules && Array.isArray(rules) && rules.length) {
29
- // Redefine WCAG 2 AAA as including only them.
30
- if (! window.HTMLCS_WCAG2AAA) {
31
- window.HTMLCS_WCAG2AAA = {};
32
- }
33
- window.HTMLCS_WCAG2AAA.sniffs = rules;
40
+ // Get the HTMLCS script.
41
+ const scriptText = await fs.readFile(`${__dirname}/../htmlcs/HTMLCS.js`, 'utf8');
42
+ const scriptNonce = report.jobData && report.jobData.lastScriptNonce;
43
+ // Define the rules to be employed as those of WCAG 2 level AAA.
44
+ let messageStrings = [];
45
+ for (const actStandard of ['WCAG2AAA']) {
46
+ const nextIssues = await page.evaluate(args => {
47
+ // Add the HTMLCS script to the page.
48
+ const scriptText = args[2];
49
+ const scriptNonce = args[3];
50
+ const script = document.createElement('script');
51
+ script.nonce = scriptNonce;
52
+ script.textContent = scriptText;
53
+ document.head.insertAdjacentElement('beforeend', script);
54
+ // If only some rules are to be employed:
55
+ const actStandard = args[0];
56
+ const rules = args[1];
57
+ if (rules && Array.isArray(rules) && rules.length) {
58
+ // Redefine WCAG 2 AAA as including only them.
59
+ if (! window.HTMLCS_WCAG2AAA) {
60
+ window.HTMLCS_WCAG2AAA = {};
34
61
  }
35
- // Run the tests.
36
- let issues = null;
37
- try {
38
- issues = window.HTMLCS_RUNNER.run(standard);
39
- }
40
- catch(error) {
41
- console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
42
- }
43
- return issues;
44
- }, [standard, rules]);
45
- if (nextIssues && nextIssues.every(issue => typeof issue === 'string')) {
46
- messageStrings.push(... nextIssues);
62
+ window.HTMLCS_WCAG2AAA.sniffs = rules;
47
63
  }
48
- else {
49
- result.prevented = true;
50
- result.error = 'ERROR executing HTMLCS_RUNNER in the page';
51
- break;
64
+ // Run the tests.
65
+ let issues = null;
66
+ try {
67
+ issues = window.HTMLCS_RUNNER.run(actStandard);
52
68
  }
69
+ catch(error) {
70
+ console.log(`ERROR executing HTMLCS_RUNNER on ${document.URL} (${error.message})`);
71
+ }
72
+ return issues;
73
+ }, [actStandard, rules, scriptText, scriptNonce]);
74
+ if (nextIssues && nextIssues.every(issue => typeof issue === 'string')) {
75
+ messageStrings.push(... nextIssues);
76
+ }
77
+ else {
78
+ data.prevented = true;
79
+ data.error = 'ERROR executing HTMLCS_RUNNER in the page';
80
+ break;
53
81
  }
54
- if (! result.prevented) {
55
- // Sort the issues by class and standard.
56
- messageStrings.sort();
57
- // Remove any duplicate issues.
58
- messageStrings = [... new Set(messageStrings)];
59
- // Initialize the result.
60
- result.Error = {};
61
- result.Warning = {};
62
- // For each issue:
63
- messageStrings.forEach(string => {
64
- const parts = string.split(/\|/, 6);
65
- const partCount = parts.length;
66
- if (partCount < 6) {
67
- console.log(`ERROR: Issue string ${string} has too few parts`);
82
+ }
83
+ if (! data.prevented) {
84
+ // Sort the issues by class and standard.
85
+ messageStrings.sort();
86
+ // Remove any duplicate issues.
87
+ messageStrings = [... new Set(messageStrings)];
88
+ // Initialize the result.
89
+ result.Error = {};
90
+ result.Warning = {};
91
+ // For each issue:
92
+ messageStrings.forEach(string => {
93
+ const parts = string.split(/\|/, 6);
94
+ const partCount = parts.length;
95
+ if (partCount < 6) {
96
+ console.log(`ERROR: Issue string ${string} has too few parts`);
97
+ }
98
+ // If it is an error or a warning (not a notice):
99
+ else if (['Error', 'Warning'].includes(parts[0])) {
100
+ /*
101
+ Add the issue to an issueClass.issueCode.description array in the result.
102
+ This saves space, because, although some descriptions are issue-specific, such as
103
+ descriptions that state the contrast ratio of an element, most descriptions are
104
+ generic, so typically many violations share a description.
105
+ */
106
+ const issueCode = parts[1].replace(/^WCAG2|\.Principle\d\.Guideline[\d_]+/g, '');
107
+ if (! result[parts[0]][issueCode]) {
108
+ result[parts[0]][issueCode] = {};
68
109
  }
69
- // If it is an error or a warning (not a notice):
70
- else if (['Error', 'Warning'].includes(parts[0])) {
71
- /*
72
- Add the issue to an issueClass.issueCode.description array in the result.
73
- This saves space, because, although some descriptions are issue-specific, such as
74
- descriptions that state the contrast ratio of an element, most descriptions are
75
- generic, so typically many issues share a description.
76
- */
77
- const issueCode = parts[1].replace(/^WCAG2|\.Principle\d\.Guideline[\d_]+/g, '');
78
- if (! result[parts[0]][issueCode]) {
79
- result[parts[0]][issueCode] = {};
80
- }
81
- if (! result[parts[0]][issueCode][parts[4]]) {
82
- result[parts[0]][issueCode][parts[4]] = [];
83
- }
84
- result[parts[0]][issueCode][parts[4]].push({
85
- tagName: parts[2],
86
- id: parts[3],
87
- code: parts[5]
88
- });
110
+ if (! result[parts[0]][issueCode][parts[4]]) {
111
+ result[parts[0]][issueCode][parts[4]] = [];
89
112
  }
90
- });
91
- }
113
+ result[parts[0]][issueCode][parts[4]].push({
114
+ tagName: parts[2],
115
+ id: parts[3],
116
+ code: parts[5]
117
+ });
118
+ }
119
+ });
92
120
  }
93
- return {result};
121
+ return {
122
+ data,
123
+ result
124
+ };
94
125
  };
package/tests/ibm.js CHANGED
@@ -1,19 +1,46 @@
1
+ /*
2
+ © 2021–2023 CVS Health and/or one of its affiliates. All rights reserved.
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
21
+ */
22
+
1
23
  /*
2
24
  ibm
3
25
  This test implements the IBM Equal Access ruleset for accessibility.
4
26
  The 'withNewContent' argument determines whether the test package should be
5
27
  given the URL of the page to be tested (true) or the page content (false).
6
-
28
+
7
29
  This test depends on aceconfig.js.
8
30
 
9
31
  This tool is compatible with Windows only if the accessibility-checker package
10
32
  is revised. See README.md for details.
11
33
  */
12
- // Import required modules.
34
+
35
+ // IMPORTS
36
+
13
37
  const fs = require('fs').promises;
14
38
  // Scanner. Importing and executing 'close' crashed the Node process.
15
39
  const {getCompliance} = require('accessibility-checker');
16
- // Runs the IBM test.
40
+
41
+ // FUNCTIONS
42
+
43
+ // Runs the IBM test and returns the result.
17
44
  const run = async (content, timeLimit) => {
18
45
  const nowLabel = (new Date()).toISOString().slice(0, 19);
19
46
  // Start the timeout clock.
@@ -37,11 +64,11 @@ const run = async (content, timeLimit) => {
37
64
  return null;
38
65
  }
39
66
  };
40
- // Revises report totals for any rule limitation.
41
- const limitRuleTotals = (report, rules) => {
67
+ // Revises act-report totals for any rule limitation.
68
+ const limitRuleTotals = (actReport, rules) => {
42
69
  if (rules && Array.isArray(rules) && rules.length) {
43
- const totals = report.report.summary.counts;
44
- const items = report.report.results;
70
+ const totals = actReport.summary.counts;
71
+ const items = actReport.results;
45
72
  totals.violation = totals.recommendation = 0;
46
73
  items.forEach(item => {
47
74
  if (rules.includes(item.ruleId)) {
@@ -51,21 +78,24 @@ const limitRuleTotals = (report, rules) => {
51
78
  }
52
79
  };
53
80
  // Trims an IBM report.
54
- const trimReport = (report, withItems, rules) => {
55
- const data = {};
56
- if (report && report.report && report.report.summary) {
57
- limitRuleTotals(report, rules);
58
- const totals = report.report.summary.counts;
81
+ const trimActReport = (data, actReport, withItems, rules) => {
82
+ // If the act report includes a summary:
83
+ if (actReport && actReport.summary) {
84
+ // Remove excluded rules from the act report.
85
+ limitRuleTotals(actReport, rules);
86
+ // If the act report includes totals:
87
+ const totals = actReport.summary.counts;
59
88
  if (totals) {
60
- data.totals = totals;
89
+ // If itemization is required:
61
90
  if (withItems) {
91
+ // Trim the items.
62
92
  if (rules && Array.isArray(rules) && rules.length) {
63
- data.items = report.report.results.filter(item => rules.includes(item.ruleId));
93
+ actReport.items = actReport.results.filter(item => rules.includes(item.ruleId));
64
94
  }
65
95
  else {
66
- data.items = report.report.results;
96
+ actReport.items = actReport.results;
67
97
  }
68
- data.items.forEach(item => {
98
+ actReport.items.forEach(item => {
69
99
  delete item.apiArgs;
70
100
  delete item.category;
71
101
  delete item.ignored;
@@ -75,31 +105,43 @@ const trimReport = (report, withItems, rules) => {
75
105
  delete item.value;
76
106
  });
77
107
  }
108
+ // Return the act report, trimmed.
109
+ return {
110
+ totals,
111
+ items: actReport.items
112
+ };
78
113
  }
114
+ // Otherwise, i.e. if it excludes totals:
79
115
  else {
116
+ // Report this.
80
117
  data.prevented = true;
81
- data.error = 'ERROR: ibm test delivered no totals';
118
+ data.error = 'ERROR: No totals reported';
119
+ // Return an empty act report.
120
+ return {
121
+ totals: {},
122
+ items: []
123
+ };
82
124
  }
83
125
  }
126
+ // Otherwise, i.e. if it excludes a summary:
84
127
  else {
128
+ // Report this.
85
129
  data.prevented = true;
86
- data.error = 'ERROR: ibm test delivered no report summary';
130
+ data.error = 'ERROR: No summary reported';
131
+ // Return an empty act report.
132
+ return {
133
+ totals: {},
134
+ items: []
135
+ };
87
136
  }
88
- return data;
89
137
  };
90
- // Performs the IBM tests and returns the result.
138
+ // Performs the IBM tests and returns an act report.
91
139
  const doTest = async (content, withItems, timeLimit, rules) => {
92
140
  // Conduct the test and get the result.
93
- let report;
141
+ const data = {};
94
142
  try {
95
- report = await run(content, timeLimit);
96
- }
97
- catch(error) {
98
- console.log(`ibm test failed ${error.message.slice(0, 100)}...`);
99
- report = null;
100
- }
101
- // If the test did not crash or time out:
102
- if (report) {
143
+ const runReport = await run(content, timeLimit);
144
+ const actReport = runReport && runReport.report;
103
145
  // Delete any report files.
104
146
  try {
105
147
  const reportNames = await fs.readdir('results');
@@ -108,37 +150,61 @@ const doTest = async (content, withItems, timeLimit, rules) => {
108
150
  }
109
151
  }
110
152
  catch(error) {
111
- console.log('ibm test created no result files.');
153
+ console.log('No result files created');
112
154
  }
113
- // Return the result.
114
- const typeReport = trimReport(report, withItems, rules);
115
- return typeReport;
155
+ // Return a trimmed act report.
156
+ const trimmedReport = trimActReport(data, actReport, withItems, rules);
157
+ return {
158
+ data,
159
+ result: trimmedReport
160
+ };
116
161
  }
117
- else {
162
+ catch(error) {
163
+ const message = `Act failed (${error.message.slice(0, 200)})`;
164
+ console.log(message);
165
+ data.prevented = true;
166
+ data.error = message;
118
167
  return {
119
- prevented: true,
120
- error: 'ERROR: ibm test failed or timed out'
168
+ data,
169
+ result: {}
121
170
  };
122
171
  }
123
172
  };
124
- // Returns results of an IBM test.
173
+ // Performs ibm tests and returns an act report.
125
174
  exports.reporter = async (page, options) => {
126
175
  const {withItems, withNewContent, rules} = options;
127
176
  const contentType = withNewContent ? 'new' : 'existing';
128
177
  console.log(`>>>>>> Content type: ${contentType}`);
129
- let result;
130
178
  const timeLimit = 30;
131
179
  const typeContent = contentType === 'existing' ? await page.content() : await page.url();
132
180
  try {
133
- result = await doTest(typeContent, withItems, timeLimit, rules);
134
- if (result.prevented) {
135
- console.log(`ERROR: Getting ibm test report timed out at ${timeLimit} seconds`);
181
+ const actReport = await doTest(typeContent, withItems, timeLimit, rules);
182
+ const {data, result} = actReport;
183
+ if (data && data.prevented) {
184
+ const message = `ERROR: Act failed or timed out at ${timeLimit} seconds`;
185
+ console.log(message);
186
+ data.error = data.error ? `${data.error}; ${message}` : message;
187
+ return {
188
+ data,
189
+ result: {}
190
+ };
191
+ }
192
+ else {
193
+ return {
194
+ data,
195
+ result
196
+ };
136
197
  }
137
198
  }
138
199
  catch(error) {
139
- result.prevented = true;
140
- console.log(`ERROR: ibm test crashed with error ${error.message.slice(0, 200)}`);
200
+ const message = `ERROR: Act crashed (${error.message.slice(0, 200)})`;
201
+ console.log(message);
202
+ return {
203
+ data: {
204
+ prevented: true,
205
+ error: message
206
+ },
207
+ result: {}
208
+ };
141
209
  }
142
- // Return the result. Execution of close() crashed the Node process.
143
- return {result};
144
210
  };