testaro 70.1.0 → 71.0.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/AGENTS.md CHANGED
@@ -13,9 +13,9 @@
13
13
 
14
14
  - **Main dirs**: `/tests` (tool test definitions), `/procs` (shared procedures), `/validation` (test validators), root (core modules)
15
15
  - **Key files**: `run.js` (main executor), `actSpecs.js` (act specifications), `call.js` (CLI entry), `tests/testaro.js` (Testaro tool rules)
16
- - **Tools**: Integrates 12 accessibility tools (Axe, Alfa, IBM Checker, QualWeb, ASLint, WAVE, WallyAX, Ed11y, HTML CodeSniffer, Nu Validator API, Nu Html Checker, Testaro)
16
+ - **Tools**: Integrates these accessibility tools: Axe, Alfa, IBM Checker, QualWeb, ASLint, WAVE, Ed11y, HTML CodeSniffer, Nu Html Checker API, Nu Html Checker, Testaro
17
17
  - **Data flow**: Jobs (JSON) → run.js → tool tests → reports (with standardized results)
18
- - **Env vars**: Required for WallyAX (`WAX_KEY`), WAVE (`WAVE_KEY`); optional `DEBUG`, `WAITS`, `JOBDIR`, `REPORTDIR`, `AGENT`
18
+ - **Env vars**: Required for WAVE (`WAVE_KEY`); optional `DEBUG`, `WAITS`, `JOBDIR`, `REPORTDIR`, `AGENT`
19
19
 
20
20
  ## Code Style
21
21
 
package/README.md CHANGED
@@ -57,12 +57,11 @@ Testaro can perform tests of these _tools_:
57
57
  - [Nu Html Checker](https://github.com/validator/validator) (World Wide Web Consortium)
58
58
  - [QualWeb](https://www.npmjs.com/package/@qualweb/core) (University of Lisbon)
59
59
  - [Testaro](https://www.npmjs.com/package/testaro) (CVS Health)
60
- - [WallyAX](https://www.npmjs.com/package/@wally-ax/wax-dev) (Wally Solutions)
61
60
  - [WAVE](https://wave.webaim.org/api/) (WebAIM)
62
61
 
63
62
  For the tools that are open-source, the identified organizations are their principal or original sponsors.
64
63
 
65
- As shown, Testaro is not only an integrator but also one of the 11 integrated tools. That is because it provides about 50 tests of its own, mostly to complement tests provided by the other 10 tools. Some of those Testaro tests are designed to act as approximate alternatives to tests of vulnerable, restricted, or no longer available tools. In all such cases the Testaro tests are independently designed and implemented, without reference to the code of the tests that inspired them.
64
+ As shown, Testaro is not only an integrator but also one of the integrated tools. That is because it provides about 50 tests of its own, mostly to complement tests provided by the other tools. Some of those Testaro tests are designed to act as approximate alternatives to tests of vulnerable, restricted, or no longer available tools. In all such cases the Testaro tests are independently designed and implemented, without reference to the code of the tests that inspired them.
66
65
 
67
66
  ## Concepts and terms
68
67
 
@@ -121,8 +120,6 @@ PUPPETEER_DISABLE_HEADLESS_WARNING=true
121
120
  WAITS=0
122
121
  # API key to enable the WAVE tool.
123
122
  WAVE_KEY=yourwavekey (get it from [WebAim](https://wave.webaim.org/api/)).
124
- # `proTestKit` API key to enable the `npm Package` of the WallyAX tool.
125
- WAX_KEY=yourwaxkey (get it from [WallyAX](https://account.wallyax.com/?ref_app=Developer&app_type=npm)).
126
123
  #----------------------------
127
124
  # When Testaro listens for new jobs in a directory:
128
125
  # Directory where it listens for them.
@@ -332,7 +329,7 @@ Testaro uses the following techniques to make the tools calculate XPaths:
332
329
  - `alfa` and `aslint`: They report XPaths, so Testaro needs only to normalize them.
333
330
  - `ed11y`: Testaro adds it and a `window.getXPath` method to the page; when the tool reports an element, Testaro computes its XPath.
334
331
  - `wave`: It reports a selector for each element; Testaro finds each element in the page via its selector and executes `window.getXPath` on the element.
335
- - `axe`, `htmlcs`, `ibm`, `nuVal`, `nuVnu`, `qualWeb`, `wax`: Testaro adds `data-xpath` attributes to all elements; the tools include code excerpts, with the `data-expath` attributes, in the reported violations.
332
+ - `axe`, `htmlcs`, `ibm`, `nuVal`, `nuVnu`, `qualWeb`: Testaro adds `data-xpath` attributes to all elements; the tools include code excerpts, with the `data-expath` attributes, in the reported violations.
336
333
  - `testaro`: Testaro designs each of its own tests to report element XPaths.
337
334
 
338
335
  By attaching a catalog entry to each reported element, Testaro allows an application that uses Testaro to tell users, for any particular HTML element, which tools ascribed violations of which rules to that element. An application could, for example, use a screenshot or a text-fragment link or could ask the user to paste the XPath into a browser developer tool.
@@ -507,12 +504,6 @@ Unlike any other tool, the `testaro` tool requires a `stopOnFail` property, whic
507
504
 
508
505
  Tests of the `testaro` tests (i.e. _validation_) can be performed as documented in the `VALIDATION.md` file.
509
506
 
510
- ### WallyAX
511
-
512
- If a `wax` test act is included in the job, an environment variable named `WAX_KEY` must exist, with your WallyAX API key as its value. You can obtain it from [WallyAX](https://account.wallyax.com/?ref_app=Developer&app_type=npm).
513
-
514
- The `wax` tool imposes a limit on the size of a page to be tested. If the page exceeds the limit, Testaro treats the page as preventing `wax` from performing its tests. The limit is less than 500,000 characters.
515
-
516
507
  ### WAVE
517
508
 
518
509
  If a `wave` test act is included in the job, the WAVE tests will be performed either by the subscription API or by the stand-alone API.
package/UPGRADES.md CHANGED
@@ -789,7 +789,7 @@ testaro-monorepo/
789
789
 
790
790
  Comments on the above suggestions:
791
791
 
792
- The `nuVal` tool is one of three (also `wave` and `wax`) that operate as APIs, with the substantial disadvantage that they can test only publicly reachable pages. The `nuVal` tool could be brought into the package (see How to to run your own copy of the [Nu Html Checker](@https://validator.w3.org/nu/about.html)). Until then, it seems to me that it avoids presenting incompatibility problems, so I believe another tool would be better to start with. But that decision could await the start of the upgrade project.
792
+ The `nuVal` tool is one of two (also `wave`) that operate as APIs, with the substantial disadvantage that they can test only publicly reachable pages. The `nuVal` tool could be brought into the package (see How to to run your own copy of the [Nu Html Checker](@https://validator.w3.org/nu/about.html)). Until then, it seems to me that it avoids presenting incompatibility problems, so I believe another tool would be better to start with. But that decision could await the start of the upgrade project.
793
793
 
794
794
  I forgot to mention the modernization of validation. I am using that term in place of unit, integration, and end-to-end testing, because the entire project is a testing project and it gets confusing when the word “test” can refer both to the primary functionality of the project and the verification that the project works correctly. Currently validation is limited to the Testaro tool’s 55 or so tests. The idea behind that is that this project treats the 10 external tools like oracles that make claims, but these claims are inherently suspect, so for any tool there are 10 others that may perform their own version of any test. When tools disagree, Testaro does not try to decide which is correct. Instead, it uses Testilo to find similar tests of other tools and collect the results together so users can experience the disagreements and decide for themselves which tools are correct. Such user judgments can be collected by the UI and lead to deprecations by Testilo so that dubious tests are disregarded. Validation of the Testaro tests is currently exposed in a nonstandard way, and I want to consider converting it to a widely accepted interface.
795
795
 
@@ -809,7 +809,6 @@ You're absolutely right about `nuVal`'s limitations. Since it requires publicly
809
809
 
810
810
  1. **`htmlcs`** - Pure JavaScript, no external dependencies, works on any HTML
811
811
  2. **`wave`** - Also API-based, so same limitations as `nuVal`
812
- 3. **`wax`** - API-based as well
813
812
  4. **`axe`** - Self-contained, works on any page, excellent for establishing patterns
814
813
 
815
814
  **I recommend starting with `axe`** because:
@@ -844,7 +843,7 @@ interface ValidationSuite {
844
843
 
845
844
  // Tool-specific validation
846
845
  interface ToolValidation extends ValidationSuite {
847
- tool: 'axe' | 'wave' | 'htmlcs' | 'nuVal' | 'wax' | 'alfa' | 'qualWeb' | 'ibm' | 'ed11y' | 'aslint';
846
+ tool: 'axe' | 'wave' | 'htmlcs' | 'nuVal' | 'alfa' | 'qualWeb' | 'ibm' | 'ed11y' | 'aslint';
848
847
  rules: RuleDefinition[];
849
848
  }
850
849
  ```
@@ -1050,7 +1049,7 @@ interface ValidationSuite {
1050
1049
 
1051
1050
  // Tool-specific validation
1052
1051
  interface ToolValidation extends ValidationSuite {
1053
- tool: 'axe' | 'wave' | 'htmlcs' | 'nuVal' | 'wax' | 'alfa' | 'qualWeb' | 'ibm' | 'ed11y' | 'aslint';
1052
+ tool: 'axe' | 'wave' | 'htmlcs' | 'nuVal' | 'alfa' | 'qualWeb' | 'ibm' | 'ed11y' | 'aslint';
1054
1053
  rules: RuleDefinition[];
1055
1054
  }
1056
1055
  ```
@@ -1636,7 +1635,6 @@ testaro-monorepo/
1636
1635
  │ │ ├── ed11y/ # Editoria11y package
1637
1636
  │ │ ├── nuval/ # Nu Html Checker package
1638
1637
  │ │ ├── wave/ # WAVE package
1639
- │ │ ├── wax/ # WallyAX package
1640
1638
  │ │ └── testaro-rules/ # Testaro custom rules package
1641
1639
  │ ├── validation/ # Validation framework
1642
1640
  │ └── custom-tools/ # Customer-specific tools
@@ -1936,7 +1934,6 @@ testaro-monorepo/
1936
1934
  │ │ ├── ed11y/ # Editoria11y package
1937
1935
  │ │ ├── nuval/ # Nu Html Checker package
1938
1936
  │ │ ├── wave/ # WAVE package
1939
- │ │ ├── wax/ # WallyAX package
1940
1937
  │ │ └── testaro-rules/ # Testaro custom rules package
1941
1938
  │ ├── validation/ # Validation framework
1942
1939
  │ └── custom-tools/ # Customer-specific tools
@@ -2968,7 +2965,6 @@ One example of the elapsed times (in seconds) for tool execution on a relatively
2968
2965
  "alfa": 13,
2969
2966
  "qualWeb": 13,
2970
2967
  "aslint": 7,
2971
- "wax": 7,
2972
2968
  "axe": 6,
2973
2969
  "ed11y": 5,
2974
2970
  "nuVal": 4,
package/netWatch.js CHANGED
@@ -76,7 +76,7 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
76
76
  // Configure the next check.
77
77
  const logStart = `Requested job from ${jobHost} and got `;
78
78
  // Perform it.
79
- await new Promise(resolve => {
79
+ await new Promise(async resolve => {
80
80
  try {
81
81
  const client = jobURL.protocol === 'https:' ? httpsClient : httpClient;
82
82
  // Request a job.
@@ -116,7 +116,7 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
116
116
  await wait(1000 * intervalInSeconds);
117
117
  resolve(true);
118
118
  }
119
- // Otherwise, if a job was received:
119
+ // Otherwise, if it is a job:
120
120
  else if (id) {
121
121
  // Check it for validity.
122
122
  const jobValidity = isValidJob(contentObj);
@@ -128,6 +128,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
128
128
  error: jobValidity.error
129
129
  }, response);
130
130
  console.log(`${logStart}invalid job (${jobValidity.error})`);
131
+ // Wait for the specified interval.
132
+ await wait(1000 * intervalInSeconds);
131
133
  resolve(true);
132
134
  }
133
135
  // Otherwise, i.e. if it is valid:
@@ -164,8 +166,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
164
166
  .on('error', async error => {
165
167
  // Report this.
166
168
  console.log(`${reportLogStart}error message ${error.message}\n`);
167
- // Stop checking.
168
- abort = true;
169
+ // Wait for the specified interval.
170
+ await wait(1000 * intervalInSeconds);
169
171
  resolve(true);
170
172
  })
171
173
  // If the response delivers data:
@@ -194,6 +196,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
194
196
  // Free the memory used by the job and the report.
195
197
  contentObj = {};
196
198
  responseJSON = '';
199
+ // Wait for the specified interval.
200
+ await wait(1000 * intervalInSeconds);
197
201
  resolve(true);
198
202
  });
199
203
  })
@@ -205,8 +209,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
205
209
  console.log(
206
210
  `ERROR ${error.code} in report submission: ${reportLogStart}error message ${error.message}\n`
207
211
  );
208
- // Stop checking.
209
- abort = true;
212
+ // Wait for the specified interval.
213
+ await wait(1000 * intervalInSeconds);
210
214
  resolve(true);
211
215
  })
212
216
  // Finish submitting the report.
@@ -214,8 +218,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
214
218
  }
215
219
  catch(error) {
216
220
  console.log(`ERROR performing job ${id} (${error.message})`);
217
- // Stop checking.
218
- abort = true;
221
+ // Wait for the specified interval.
222
+ await wait(1000 * intervalInSeconds);
219
223
  resolve(true);
220
224
  }
221
225
  }
@@ -224,6 +228,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
224
228
  else {
225
229
  // Report it.
226
230
  console.log(`${logStart}${JSON.stringify(contentObj, null, 2)}`);
231
+ // Wait for the specified interval.
232
+ await wait(1000 * intervalInSeconds);
227
233
  resolve(true);
228
234
  }
229
235
  }
@@ -231,8 +237,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
231
237
  catch(error) {
232
238
  // Report this.
233
239
  console.log(`ERROR: ${logStart}status ${response.statusCode}, error message ${error.message}, and non-JSON response ${content.slice(0, 1000)}\n`);
234
- // Stop checking.
235
- abort = true;
240
+ // Wait for the specified interval.
241
+ await wait(1000 * intervalInSeconds);
236
242
  resolve(true);
237
243
  };
238
244
  });
@@ -243,30 +249,24 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
243
249
  if (error.code && error.code.includes('ECONNREFUSED')) {
244
250
  // Report this.
245
251
  console.log(`${logStart}no connection`);
246
- // Stop checking.
247
- abort = true;
248
252
  }
249
253
  // Otherwise, if it was a DNS failure:
250
254
  else if (error.code && error.code.includes('ENOTFOUND')) {
251
255
  // Report this.
252
256
  console.log(`${logStart}no domain name resolution`);
253
- // Stop checking.
254
- abort = true;
255
257
  }
256
258
  // Otherwise, if it was any other error with a message:
257
259
  else if (error.message) {
258
260
  // Report this.
259
261
  console.log(`ERROR: ${logStart}got error message ${error.message.slice(0, 200)}`);
260
- // Stop checking.
261
- abort = true;
262
262
  }
263
263
  // Otherwise, i.e. if it was any other error with no message:
264
264
  else {
265
265
  // Report this.
266
266
  console.log(`ERROR: ${logStart}got an error with no message`);
267
- // Stop checking.
268
- abort = true;
269
267
  }
268
+ // Wait for the specified interval.
269
+ await wait(1000 * intervalInSeconds);
270
270
  resolve(true);
271
271
  })
272
272
  // Finish sending the job request.
@@ -278,8 +278,8 @@ exports.netWatch = async (isForever, intervalInSeconds, isCertTolerant = true) =
278
278
  catch(error) {
279
279
  // Report this.
280
280
  console.log(`ERROR requesting a network job (${error.message})`);
281
- // Stop checking.
282
- abort = true;
281
+ // Wait for the specified interval.
282
+ await wait(1000 * intervalInSeconds);
283
283
  resolve(true);
284
284
  }
285
285
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "70.1.0",
3
+ "version": "71.0.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": {
@@ -38,7 +38,6 @@
38
38
  "@siteimprove/alfa-act": "*",
39
39
  "@siteimprove/alfa-playwright": "*",
40
40
  "@siteimprove/alfa-rules": "*",
41
- "@wally-ax/wax-dev": "npm:@jrpool/wax-dev@^1.0.0",
42
41
  "accessibility-checker": "*",
43
42
  "aria-query": "*",
44
43
  "aslint-testaro": "*",
package/procs/doActs.js CHANGED
@@ -56,8 +56,7 @@ const timeLimits = {
56
56
  nuVal: 30,
57
57
  nuVnu: 20,
58
58
  qualWeb: 45,
59
- testaro: 150 + Math.round(6 * waits / 1000),
60
- wax: 35
59
+ testaro: 150 + Math.round(6 * waits / 1000)
61
60
  };
62
61
  // Timeout multiplier.
63
62
  const timeoutMultiplier = Number.parseFloat(process.env.TIMEOUT_MULTIPLIER) || 1;
@@ -54,8 +54,7 @@ const xPathNeeds = {
54
54
  nuVal: 'attribute',
55
55
  nuVnu: 'attribute',
56
56
  qualWeb: 'attribute',
57
- wave: 'script',
58
- wax: 'attribute'
57
+ wave: 'script'
59
58
  };
60
59
  const accessibleNameNeeders = ['testaro'];
61
60
 
package/procs/job.js CHANGED
@@ -35,7 +35,6 @@ const tools = exports.tools = {
35
35
  nuVnu: 'Html Checker',
36
36
  qualWeb: 'QualWeb',
37
37
  testaro: 'Testaro',
38
- wax: 'WallyAX',
39
38
  wave: 'WAVE',
40
39
  };
41
40
 
@@ -1,28 +0,0 @@
1
- diff --git a/node_modules/@wally-ax/wax-dev/src/runnerHtml.js b/node_modules/@wally-ax/wax-dev/src/runnerHtml.js
2
- index 1d84a0b..d9c3fc5 100644
3
- --- a/node_modules/@wally-ax/wax-dev/src/runnerHtml.js
4
- +++ b/node_modules/@wally-ax/wax-dev/src/runnerHtml.js
5
- @@ -34,8 +34,8 @@ const runner = function (code, options) {
6
- description,
7
- severity,
8
- code,
9
- - groupData = {}
10
- } = item;
11
- + const groupData = item.groupData || {};
12
-
13
- const cleanedItem = {};
14
- if (element) cleanedItem.element = element;
15
- diff --git a/node_modules/@wally-ax/wax-dev/src/runnerUrl.js b/node_modules/@wally-ax/wax-dev/src/runnerUrl.js
16
- index 0e020a0..3c6850f 100644
17
- --- a/node_modules/@wally-ax/wax-dev/src/runnerUrl.js
18
- +++ b/node_modules/@wally-ax/wax-dev/src/runnerUrl.js
19
- @@ -33,8 +33,8 @@ const runner = function (code, options) {
20
- selector,
21
- component,
22
- issue_category_name,
23
- - groupData = {}
24
- } = item;
25
- + const groupData = item.groupData || {};
26
-
27
- const cleanedItem = {};
28
-
package/tests/wax.js DELETED
@@ -1,133 +0,0 @@
1
- /*
2
- © 2024 CVS Health and/or one of its affiliates. All rights reserved.
3
- © 2025–2026 Jonathan Robert Pool.
4
-
5
- Licensed under the MIT License. See LICENSE file at the project root or
6
- https://opensource.org/license/mit/ for details.
7
-
8
- SPDX-License-Identifier: MIT
9
- */
10
-
11
- /*
12
- wax
13
- This test implements the WallyAX WAX Dev Testing Framework ruleset.
14
- */
15
-
16
- // IMPORTS
17
-
18
- const {getAttributeXPath, getXPathCatalogIndex} = require('../procs/xPath');
19
- const runWax = require('@wally-ax/wax-dev');
20
- const waxDev = {runWax};
21
-
22
- // FUNCTIONS
23
-
24
- // Conducts and reports the WAX tests.
25
- exports.reporter = async (page, report, actIndex) => {
26
- // Initialize the act report.
27
- const data = {};
28
- const result = {
29
- nativeResult: {},
30
- standardResult: {}
31
- };
32
- const standard = report.standard !== 'no';
33
- // If standard results are to be reported:
34
- if (standard) {
35
- // Initialize the standard result.
36
- result.standardResult = {
37
- prevented: false,
38
- totals: [0, 0, 0, 0],
39
- instances: []
40
- };
41
- }
42
- const act = report.acts[actIndex];
43
- const rules = act.rules || [];
44
- const pageCode = await page.content();
45
- const waxOptions = {
46
- rules,
47
- apiKey: process.env.WAX_KEY || ''
48
- };
49
- try {
50
- // Run WAX.
51
- const actReport = await waxDev.runWax(pageCode, waxOptions);
52
- // If WAX failed with a string report:
53
- if (typeof actReport === 'string') {
54
- // Report this.
55
- data.prevented = true;
56
- data.error = actReport;
57
- }
58
- // Otherwise, if the report is an array:
59
- else if (Array.isArray(actReport)) {
60
- // If it is an error report:
61
- if (actReport.length === 1 && typeof actReport[0] === 'object' && actReport[0].error) {
62
- // Report this.
63
- data.prevented = true;
64
- const {error} = actReport[0];
65
- data.error = error;
66
- console.log(`ERROR running wax: ${error}`);
67
- }
68
- // Otherwise, i.e. if it is a successful report:
69
- else {
70
- // Populate the native result with it.
71
- result.nativeResult = actReport;
72
- // If standard results are to be reported:
73
- if (standard) {
74
- const {standardResult} = result;
75
- const {instances, totals} = standardResult;
76
- actReport.forEach(violation => {
77
- const ordinalSeverity = ['Minor', 'Moderate', '', 'Severe'].indexOf(violation.severity);
78
- // Increment the applicable total of the standard result.
79
- totals[ordinalSeverity]++;
80
- // Initialize a standard instance.
81
- const instance = {
82
- ruleID: violation.message,
83
- what: violation.description || violation.message,
84
- ordinalSeverity,
85
- count: 1
86
- };
87
- const {element} = violation;
88
- // Get the path ID of the element from its data-xpath attribute.
89
- const pathID = getAttributeXPath(element);
90
- // If the acquisition succeeded:
91
- if (pathID) {
92
- // Add the catalog index to the standard instance.
93
- instance.catalogIndex = getXPathCatalogIndex(report.catalog, pathID);
94
- }
95
- // Add the standard instance to the standard result.
96
- instances.push(instance);
97
- });
98
- }
99
- }
100
- }
101
- // Otherwise, if the report is a non-array object:
102
- else if (typeof actReport === 'object') {
103
- // If the response status was a system error:
104
- if(actReport.responseCode === 500) {
105
- // Report this.
106
- data.prevented = true;
107
- data.error = actReport.message || 'response status code 500';
108
- }
109
- // Otherwise, if there was an error:
110
- else if (actReport.error) {
111
- // Report this.
112
- data.prevented = true;
113
- data.error = actReport.error;
114
- }
115
- // In any other case:
116
- else {
117
- // Report a prevention.
118
- data.prevented = true;
119
- data.error = 'wax failure';
120
- }
121
- }
122
- }
123
- catch(error) {
124
- const message = `ERROR running WallyAX (${error.message})`;
125
- data.prevented = true;
126
- data.error = message;
127
- console.log(message);
128
- }
129
- return {
130
- data,
131
- result
132
- };
133
- };