testaro 64.9.0 → 64.9.2

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.9.0",
3
+ "version": "64.9.2",
4
4
  "description": "Run 1000 web accessibility tests from 11 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -101,3 +101,77 @@ exports.getLocatorData = async loc => {
101
101
  return null;
102
102
  }
103
103
  };
104
+ // Returns location data from the extract of a standard instance.
105
+ exports.getLocationData = async (page, excerpt) => {
106
+ const testaroIDArray = excerpt.match(/data-testaro-id="(\d+)#([^"]*)"/);
107
+ // If the extract contains a Testaro identifier:
108
+ if (testaroIDArray) {
109
+ const testaroID = `${testaroIDArray[1]}#${testaroIDArray[2]}`;
110
+ // Return location data for the element.
111
+ return await page.evaluate(testaroID => {
112
+ const element = document.querySelector(`[data-testaro-id="${testaroID}"]`);
113
+ // If any element has that identifier:
114
+ if (element) {
115
+ // Get a box ID for the element.
116
+ const box = {};
117
+ let boxID = '';
118
+ const boundingBox = element.getBoundingClientRect() || {};
119
+ if (boundingBox.x) {
120
+ ['x', 'y', 'width', 'height'].forEach(coordinate => {
121
+ box[coordinate] = Math.round(boundingBox[coordinate]);
122
+ });
123
+ }
124
+ if (typeof box.x === 'number') {
125
+ boxID = Object.values(box).join(':');
126
+ }
127
+ const oldPathID = testaroID.replace(/^.*?#/, '');
128
+ const newPathID = window.getXPath(element);
129
+ let pathID = '';
130
+ // If the XPath of the element is the same as that in the identifier:
131
+ if (newPathID === oldPathID) {
132
+ // Use it as the path ID.
133
+ pathID = oldPathID;
134
+ }
135
+ // Otherwise, if both paths exist but differ:
136
+ else if (oldPathID && newPathID) {
137
+ // Use both as a path ID.
138
+ pathID = `${newPathID} (originally: ${oldPathID})`;
139
+ }
140
+ // Otherwise, i.e. if only one of them exists:
141
+ else {
142
+ // Use the existing one as the path ID.
143
+ pathID = newPathID || oldPathID;
144
+ }
145
+ // Return the box and path IDs.
146
+ return {
147
+ boxID,
148
+ pathID
149
+ };
150
+ }
151
+ // Otherwise, if no element has it but the identifier includes an XPath:
152
+ else if (testaroIDArray[2]) {
153
+ // Return an empty box ID and that XPath as a path ID.
154
+ return {
155
+ notInDOM: true,
156
+ boxID: '',
157
+ pathID: testaroIDArray[2]
158
+ };
159
+ }
160
+ // Otherwise, return empty location properties.
161
+ return {
162
+ notInDOM: true,
163
+ boxID: '',
164
+ pathID: ''
165
+ };
166
+ }, testaroID);
167
+ }
168
+ // Otherwise, i.e. if the extract contains no Testaro identifier:
169
+ else {
170
+ // Return a non-DOM location.
171
+ return {
172
+ notInDOM: true,
173
+ boxID: '',
174
+ pathID: ''
175
+ };
176
+ }
177
+ };
package/procs/nu.js CHANGED
@@ -15,7 +15,9 @@
15
15
  // ########## IMPORTS
16
16
 
17
17
  // Module to add Testaro IDs to elements.
18
- const {addTestaroIDs, getLocationData} = require('./testaro');
18
+ const {addTestaroIDs} = require('./testaro');
19
+ // Module to get location data from an element.
20
+ const {getLocationData} = require('./getLocatorData');
19
21
  // Module to get the document source.
20
22
  const {getSource} = require('./getSource');
21
23
 
@@ -42,8 +42,8 @@ const getIdentifiers = code => {
42
42
  const tagNameArray = startTagData[1].match(/^[A-Za-z0-9]+/);
43
43
  const tagName = tagNameArray ? tagNameArray[0].toUpperCase() : '';
44
44
  // Get the value of the id attribute, if any.
45
- const idData = startTagData[1].match(/ id="([^"]+)"/);
46
- const id = idData ? idData[1] : '';
45
+ const identifierData = startTagData[1].match(/ id="([^"]+)"/);
46
+ const id = identifierData ? identifierData[1] : '';
47
47
  // Return the tag name and the value of the id attribute, if any.
48
48
  return [tagName, id];
49
49
  }
package/procs/testaro.js CHANGED
@@ -227,54 +227,13 @@ exports.getVisibleCountChange = async (
227
227
  };
228
228
  // Annotates every element on a page with a unique identifier.
229
229
  exports.addTestaroIDs = async page => {
230
+ // Wait for the page to be fully loaded.
231
+ await page.waitForLoadState('networkidle');
230
232
  await page.evaluate(() => {
231
233
  let serialID = 0;
232
234
  for (const element of Array.from(document.querySelectorAll('*'))) {
233
- element.setAttribute('data-testaro-id', `${serialID++}#`);
235
+ const xPath = window.getXPath(element);
236
+ element.setAttribute('data-testaro-id', `${serialID++}#${xPath}`);
234
237
  }
235
238
  });
236
239
  };
237
- // Returns location data from the extract of a standard instance.
238
- exports.getLocationData = async (page, excerpt) => {
239
- const testaroIDArray = excerpt.match(/data-testaro-id="(\d+)#"/);
240
- // If the excerpt contains a Testaro identifier:
241
- if (testaroIDArray) {
242
- const testaroID = testaroIDArray[1];
243
- // Return location data for the element.
244
- return await page.evaluate(testaroID => {
245
- const element = document.querySelector(`[data-testaro-id="${testaroID}#"]`);
246
- // If any element has that identifier:
247
- if (element) {
248
- // Get box and path IDs for the element.
249
- const box = {};
250
- let boxID = '';
251
- const boundingBox = element.getBoundingClientRect() || {};
252
- if (boundingBox.x) {
253
- ['x', 'y', 'width', 'height'].forEach(coordinate => {
254
- box[coordinate] = Math.round(boundingBox[coordinate]);
255
- });
256
- }
257
- if (typeof box.x === 'number') {
258
- boxID = Object.values(box).join(':');
259
- }
260
- const pathID = window.getXPath(element) || '';
261
- // Return them.
262
- return {
263
- boxID,
264
- pathID
265
- };
266
- }
267
- // Otherwise, i.e. if no element has it, return empty location data.
268
- return {};
269
- }, testaroID);
270
- }
271
- // Otherwise, i.e. if the extract contains no Testaro identifier:
272
- else {
273
- // Return a non-DOM location.
274
- return {
275
- notInDOM: true,
276
- boxID: '',
277
- pathID: ''
278
- };
279
- }
280
- };
package/run.js CHANGED
@@ -374,7 +374,6 @@ const launch = exports.launch = async (
374
374
  // If the page emits a message:
375
375
  page.on('console', msg => {
376
376
  const msgText = msg.text();
377
- let indentedMsg = '';
378
377
  // If debugging is on:
379
378
  if (debug) {
380
379
  // Log the start of the message on the console.
@@ -917,7 +916,7 @@ const doActs = async (report, opts = {}) => {
917
916
  child.on('close', code => {
918
917
  if (! closed) {
919
918
  closed = true;
920
- resolve(code);
919
+ resolve(`Page closed with code ${code}`);
921
920
  }
922
921
  });
923
922
  });
@@ -1648,16 +1647,19 @@ const doActs = async (report, opts = {}) => {
1648
1647
  standardize(act);
1649
1648
  // For each of its standard instances:
1650
1649
  for (const instance of act.standardResult.instances) {
1651
- const elementID = await identify(instance, page);
1652
- // If a box ID is missing:
1653
- if (! instance.boxID) {
1654
- // Add one.
1655
- instance.boxID = elementID ? elementID.boxID : '';
1656
- }
1657
- // If a path ID is missing or different:
1658
- if (instance.pathID !== elementID.pathID) {
1659
- // Add a box ID and a path ID to each of its standard instances if missing.
1660
- instance.pathID = elementID.pathID;
1650
+ // If the instance does not have both a box ID and a path ID:
1651
+ if (! (instance.boxID && instance.pathID)) {
1652
+ const elementID = await identify(instance, page);
1653
+ // If it has no box ID but the element has a bounding box:
1654
+ if (elementID.boxID && ! instance.boxID) {
1655
+ // Add a box ID.
1656
+ instance.boxID = elementID.boxID;
1657
+ }
1658
+ // If it has no path ID but the element has one:
1659
+ if (elementID.pathID && ! instance.pathID) {
1660
+ // Add a path ID.
1661
+ instance.pathID = elementID.pathID;
1662
+ }
1661
1663
  }
1662
1664
  };
1663
1665
  // If the original-format result is not to be included in the report:
@@ -1677,9 +1679,12 @@ const doActs = async (report, opts = {}) => {
1677
1679
  console.log('Standardization completed');
1678
1680
  const {acts} = report;
1679
1681
  const idData = {};
1682
+ // For each act:
1680
1683
  for (const act of acts) {
1684
+ // If it is a test act:
1681
1685
  if (act.type === 'test') {
1682
1686
  const {which} = act;
1687
+ // Initialize an idData property for the tool if necessary.
1683
1688
  idData[which] ??= {
1684
1689
  instanceCount: 0,
1685
1690
  boxIDCount: 0,
@@ -1690,18 +1695,26 @@ const doActs = async (report, opts = {}) => {
1690
1695
  const actIDData = idData[which];
1691
1696
  const {standardResult} = act;
1692
1697
  const {instances} = standardResult;
1698
+ // For each standard instance in the act:
1693
1699
  for (const instance of instances) {
1694
1700
  const {boxID, pathID} = instance;
1701
+ // Increment the instance count.
1695
1702
  actIDData.instanceCount++;
1703
+ // If the instance has a box ID:
1696
1704
  if (boxID) {
1705
+ // Increment the box ID count.
1697
1706
  actIDData.boxIDCount++;
1698
1707
  }
1708
+ // If the instance has a path ID:
1699
1709
  if (pathID) {
1710
+ // Increment the path ID count.
1700
1711
  actIDData.pathIDCount++;
1701
1712
  }
1702
1713
  }
1703
1714
  const {instanceCount, boxIDCount, pathIDCount} = actIDData;
1715
+ // If there are any instances:
1704
1716
  if (instanceCount) {
1717
+ // Add the box ID and path ID percentages to the iData property.
1705
1718
  actIDData.boxIDPercent = Math.round(100 * boxIDCount / instanceCount);
1706
1719
  actIDData.pathIDPercent = Math.round(100 * pathIDCount / instanceCount);
1707
1720
  }
package/tests/htmlcs.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /*
2
2
  © 2022–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
+ © 2025 Jonathan Robert Pool.
3
4
 
4
5
  Licensed under the MIT License. See LICENSE file at the project root or
5
6
  https://opensource.org/license/mit/ for details.
@@ -15,7 +16,9 @@
15
16
  // IMPORTS
16
17
 
17
18
  // Module to add and use unique element IDs.
18
- const {addTestaroIDs, getLocationData} = require('../procs/testaro');
19
+ const {addTestaroIDs} = require('../procs/testaro');
20
+ // Module to get location data from an element.
21
+ const {getLocationData} = require('../procs/getLocatorData');
19
22
  // Module to handle files.
20
23
  const fs = require('fs/promises');
21
24
 
package/tests/nuVnu.js CHANGED
@@ -33,7 +33,7 @@ const tmpDir = os.tmpdir();
33
33
 
34
34
  // Conducts and reports the Nu Html Checker tests.
35
35
  exports.reporter = async (page, report, actIndex) => {
36
- // Get the vuVal act, if it exists.
36
+ // Get the nuVal act, if it exists.
37
37
  const nuValAct = report.acts.find(act => act.type === 'test' && act.which === 'nuVal');
38
38
  // If it does not exist or it exists but was prevented:
39
39
  if (! nuValAct || nuValAct.data?.prevented) {
@@ -70,6 +70,10 @@ exports.reporter = async (page, report, actIndex) => {
70
70
  await fs.unlink(pagePath);
71
71
  // Postprocess the result.
72
72
  result = await curate(page, data, nuData, rules);
73
+ return {
74
+ data,
75
+ result
76
+ };
73
77
  }
74
78
  // Otherwise, i.e. if the content was not obtained:
75
79
  else {
@@ -77,10 +81,6 @@ exports.reporter = async (page, report, actIndex) => {
77
81
  data.prevented = true;
78
82
  data.error = 'Content not obtained';
79
83
  }
80
- return {
81
- data,
82
- result
83
- };
84
84
  }
85
85
  // Otherwise, i.e. if the nuVal act exists and succeeded:
86
86
  else {
package/tests/wax.js CHANGED
@@ -16,7 +16,9 @@
16
16
  // IMPORTS
17
17
 
18
18
  // Module to add and use unique element IDs.
19
- const {addTestaroIDs, getLocationData} = require('../procs/testaro');
19
+ const {addTestaroIDs} = require('../procs/testaro');
20
+ // Module to get location data from an element.
21
+ const {getLocationData} = require('../procs/getLocatorData');
20
22
  // Modules to run WAX.
21
23
  const runWax = require('@wally-ax/wax-dev');
22
24
  const waxDev = {runWax};