testaro 64.9.3 → 64.9.5
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 +1 -1
- package/procs/getLocatorData.js +5 -5
- package/procs/identify.js +16 -14
- package/procs/standardize.js +25 -8
- package/run.js +1 -1
- package/tests/aslint.js +23 -4
- package/tests/ed11y.js +7 -5
- package/tests/wax.js +2 -2
package/package.json
CHANGED
package/procs/getLocatorData.js
CHANGED
|
@@ -106,8 +106,8 @@ exports.getLocationData = async (page, excerpt) => {
|
|
|
106
106
|
const testaroIDArray = excerpt.match(/data-testaro-id="(\d+)#([^"]*)"/);
|
|
107
107
|
// If the extract contains a Testaro identifier:
|
|
108
108
|
if (testaroIDArray) {
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
return await page.evaluate(testaroIDArray => {
|
|
110
|
+
const testaroID = `${testaroIDArray[1]}#${testaroIDArray[2]}`;
|
|
111
111
|
const element = document.querySelector(`[data-testaro-id="${testaroID}"]`);
|
|
112
112
|
// If any element has that identifier:
|
|
113
113
|
if (element) {
|
|
@@ -123,8 +123,8 @@ exports.getLocationData = async (page, excerpt) => {
|
|
|
123
123
|
if (typeof box.x === 'number') {
|
|
124
124
|
boxID = Object.values(box).join(':');
|
|
125
125
|
}
|
|
126
|
-
// Get a path ID
|
|
127
|
-
let pathID =
|
|
126
|
+
// Get a path ID from the Testaro identifier or, if necessary, the element.
|
|
127
|
+
let pathID = testaroIDArray[2];
|
|
128
128
|
if (! pathID) {
|
|
129
129
|
pathID = window.getXPath(element);
|
|
130
130
|
}
|
|
@@ -149,7 +149,7 @@ exports.getLocationData = async (page, excerpt) => {
|
|
|
149
149
|
boxID: '',
|
|
150
150
|
pathID: ''
|
|
151
151
|
};
|
|
152
|
-
},
|
|
152
|
+
}, testaroIDArray);
|
|
153
153
|
}
|
|
154
154
|
// Otherwise, i.e. if the extract contains no Testaro identifier:
|
|
155
155
|
else {
|
package/procs/identify.js
CHANGED
|
@@ -54,6 +54,21 @@ const boxToString = exports.boxToString = box => {
|
|
|
54
54
|
return '';
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
|
+
// Normalizes an XPath.
|
|
58
|
+
const getNormalizedXPath = exports.getNormalizedXPath = xPath => {
|
|
59
|
+
xPath = xPath.replace(/^\.\/\//, '/');
|
|
60
|
+
const segments = xPath.split('/');
|
|
61
|
+
const normalizedSegments = [];
|
|
62
|
+
segments.forEach(segment => {
|
|
63
|
+
if (segment === '' || ['html', 'body'].includes(segment) || segment.endsWith(']')) {
|
|
64
|
+
normalizedSegments.push(segment);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
normalizedSegments.push(`${segment}[1]`);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return normalizedSegments.join('/');
|
|
71
|
+
};
|
|
57
72
|
// Adds a box ID and a path ID to an object.
|
|
58
73
|
const addIDs = async (locator, recipient) => {
|
|
59
74
|
const locatorCount = await locator.count();
|
|
@@ -84,20 +99,7 @@ const addIDs = async (locator, recipient) => {
|
|
|
84
99
|
}
|
|
85
100
|
}
|
|
86
101
|
// Normalize the path ID.
|
|
87
|
-
|
|
88
|
-
const normalizedSegments = xPathSegments.map(segment => {
|
|
89
|
-
if (segment === '') {
|
|
90
|
-
return '';
|
|
91
|
-
}
|
|
92
|
-
if (['html', 'body'].includes(segment)) {
|
|
93
|
-
return segment;
|
|
94
|
-
}
|
|
95
|
-
if (segment.endsWith(']')) {
|
|
96
|
-
return segment;
|
|
97
|
-
}
|
|
98
|
-
return `${segment}[1]`;
|
|
99
|
-
});
|
|
100
|
-
recipient.pathID = normalizedSegments.join('/');
|
|
102
|
+
recipient.pathID = getNormalizedXPath(recipient.pathID);
|
|
101
103
|
}
|
|
102
104
|
};
|
|
103
105
|
// Sanitizes a tag name.
|
package/procs/standardize.js
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
Converts test results to the standard format.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
// IMPORTS
|
|
17
|
+
|
|
18
|
+
const {getNormalizedXPath} = require('./identify');
|
|
19
|
+
|
|
16
20
|
// FUNCTIONS
|
|
17
21
|
|
|
18
22
|
// Limits the length of and unilinearizes a string.
|
|
@@ -485,19 +489,30 @@ const convert = (toolName, data, result, standardResult) => {
|
|
|
485
489
|
finalRuleID = changer[changer.length - 1];
|
|
486
490
|
}
|
|
487
491
|
}
|
|
488
|
-
//
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
+
// Initialize the path ID of the violating element as any normalized reported XPath.
|
|
493
|
+
let pathID = getNormalizedXPath(ruleResult.element && ruleResult.element.xpath) || '';
|
|
494
|
+
const {locationData} = ruleResult;
|
|
495
|
+
// If an XPath was obtained from the excerpt:
|
|
496
|
+
if (locationData && locationData.pathID) {
|
|
497
|
+
// Replace the path ID with it, because some ASLint-reported XPaths are abbreviated.
|
|
498
|
+
({pathID} = locationData);
|
|
499
|
+
}
|
|
500
|
+
// Get and normalize the reported excerpt.
|
|
501
|
+
const excerpt = ruleResult.element
|
|
502
|
+
&& ruleResult.element.html
|
|
503
|
+
&& ruleResult.element.html.replace(/\s+/g, ' ')
|
|
492
504
|
|| '';
|
|
505
|
+
// Get the tag name from the XPath, if possible.
|
|
506
|
+
let tagName = pathID && pathID.replace(/[^-\w].*$/, '').toUpperCase() || '';
|
|
493
507
|
if (! tagName && finalRuleID.endsWith('_svg')) {
|
|
494
508
|
tagName = 'SVG';
|
|
495
509
|
}
|
|
496
|
-
|
|
497
|
-
|| '';
|
|
510
|
+
// If that was impossible but there is a tag name in the excerpt:
|
|
498
511
|
if (! tagName && /^<[a-z]+[ >]/.test(excerpt)) {
|
|
512
|
+
// Get it.
|
|
499
513
|
tagName = excerpt.slice(1).replace(/[ >].+/, '').toUpperCase();
|
|
500
514
|
}
|
|
515
|
+
// Get the ID, if any.
|
|
501
516
|
const idDraft = excerpt && excerpt.replace(/^[^[>]+id="/, 'id=').replace(/".*$/, '');
|
|
502
517
|
const idFinal = idDraft && idDraft.length > 3 && idDraft.startsWith('id=')
|
|
503
518
|
? idDraft.slice(3)
|
|
@@ -512,9 +527,11 @@ const convert = (toolName, data, result, standardResult) => {
|
|
|
512
527
|
location: {
|
|
513
528
|
doc: 'dom',
|
|
514
529
|
type: 'xpath',
|
|
515
|
-
spec:
|
|
530
|
+
spec: pathID
|
|
516
531
|
},
|
|
517
|
-
excerpt
|
|
532
|
+
excerpt,
|
|
533
|
+
boxID: '',
|
|
534
|
+
pathID
|
|
518
535
|
};
|
|
519
536
|
standardResult.instances.push(instance);
|
|
520
537
|
}
|
package/run.js
CHANGED
|
@@ -412,7 +412,7 @@ const launch = exports.launch = async (
|
|
|
412
412
|
get: () => ['en-US', 'en']
|
|
413
413
|
});
|
|
414
414
|
});
|
|
415
|
-
const xPathNeeders = ['
|
|
415
|
+
const xPathNeeders = ['aslint', 'htmlcs', 'nuVal', 'nuVnu', 'qualWeb', 'testaro', 'wax'];
|
|
416
416
|
const needsXPath = act.type === 'test' && xPathNeeders.includes(act.which);
|
|
417
417
|
// If the launch is for a test act that requires XPaths:
|
|
418
418
|
if (needsXPath) {
|
package/tests/aslint.js
CHANGED
|
@@ -15,13 +15,19 @@
|
|
|
15
15
|
|
|
16
16
|
// IMPORTS
|
|
17
17
|
|
|
18
|
+
// Function to add unique identifiers to the elements in the page.
|
|
19
|
+
const {addTestaroIDs} = require('../procs/testaro');
|
|
18
20
|
// Module to handle files.
|
|
19
21
|
const fs = require('fs/promises');
|
|
22
|
+
// Function to get location data from an element.
|
|
23
|
+
const {getLocationData} = require('../procs/getLocatorData');
|
|
20
24
|
|
|
21
25
|
// FUNCTIONS
|
|
22
26
|
|
|
23
27
|
// Conducts and reports the ASLint tests.
|
|
24
28
|
exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
29
|
+
// Add unique identifiers to the elements in the page.
|
|
30
|
+
await addTestaroIDs(page);
|
|
25
31
|
// Initialize the act report.
|
|
26
32
|
let data = {};
|
|
27
33
|
let result = {};
|
|
@@ -82,13 +88,11 @@ exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
|
82
88
|
if (! data.prevented) {
|
|
83
89
|
// Get their text.
|
|
84
90
|
const actReport = await reportLoc.textContent();
|
|
85
|
-
// Populate the act report.
|
|
86
91
|
result = JSON.parse(actReport);
|
|
87
92
|
// If any rules were reported violated:
|
|
88
93
|
if (result.rules) {
|
|
89
94
|
// For each such rule:
|
|
90
|
-
Object.keys(result.rules)
|
|
91
|
-
// If the rule was passed or skipped or rules to be tested were specified and exclude it:
|
|
95
|
+
for (const ruleID of Object.keys(result.rules)) {
|
|
92
96
|
const excluded = act.rules && ! act.rules.includes(ruleID);
|
|
93
97
|
const instanceType = result.rules[ruleID].status.type;
|
|
94
98
|
// If rules to be tested were specified and exclude it or the rule was passed or skipped:
|
|
@@ -96,7 +100,22 @@ exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
|
96
100
|
// Delete the rule report.
|
|
97
101
|
delete result.rules[ruleID];
|
|
98
102
|
}
|
|
99
|
-
|
|
103
|
+
// Otherwise, i.e. if the rule was violated:
|
|
104
|
+
else {
|
|
105
|
+
const ruleResults = result.rules[ruleID].results;
|
|
106
|
+
// For each violation:
|
|
107
|
+
for (const ruleResult of ruleResults) {
|
|
108
|
+
const excerpt = ruleResult.element
|
|
109
|
+
&& ruleResult.element.html.replace(/\s+/g, ' ')
|
|
110
|
+
|| '';
|
|
111
|
+
// If an element excerpt was reported:
|
|
112
|
+
if (excerpt) {
|
|
113
|
+
// Use it to add location data to the violation data in the result.
|
|
114
|
+
ruleResult.locationData = await getLocationData(page, excerpt);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
};
|
|
100
119
|
}
|
|
101
120
|
}
|
|
102
121
|
// Return the act report.
|
package/tests/ed11y.js
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
// Module to handle files.
|
|
19
19
|
const fs = require('fs/promises');
|
|
20
|
+
// Module to normalize XPaths.
|
|
21
|
+
const {getNormalizedXPath} = require('../procs/identify');
|
|
20
22
|
// Module to get the XPath of an element.
|
|
21
23
|
const {xPath} = require('playwright-dompath');
|
|
22
24
|
|
|
@@ -109,7 +111,7 @@ exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
|
109
111
|
elText = element.outerHTML;
|
|
110
112
|
}
|
|
111
113
|
if (elText.length > 400) {
|
|
112
|
-
elText = `${elText.slice(0,
|
|
114
|
+
elText = `${elText.slice(0, 300)}…${elText.slice(-200)}`;
|
|
113
115
|
}
|
|
114
116
|
violationFacts.excerpt = elText.replace(/\s+/g, ' ');
|
|
115
117
|
violationFacts.boxID = ['x', 'y', 'width', 'height']
|
|
@@ -165,11 +167,11 @@ exports.reporter = async (page, report, actIndex, timeLimit) => {
|
|
|
165
167
|
const elementJSHandles = await elementsJSHandle.getProperties();
|
|
166
168
|
// For each violation:
|
|
167
169
|
for (const index in violations) {
|
|
168
|
-
// Get its path ID from the identically indexed element.
|
|
170
|
+
// Get its Playwright path ID from the identically indexed element.
|
|
169
171
|
const elementHandle = elementJSHandles.get(index).asElement();
|
|
170
|
-
const
|
|
171
|
-
// Add the path ID to the violation facts of the result.
|
|
172
|
-
violations[index].pathID =
|
|
172
|
+
const pwPathID = await xPath(elementHandle);
|
|
173
|
+
// Add the normalized path ID to the violation facts of the result.
|
|
174
|
+
violations[index].pathID = getNormalizedXPath(pwPathID);
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
// Return the data and result, discarding the separate element data.
|
package/tests/wax.js
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
// IMPORTS
|
|
17
17
|
|
|
18
|
-
//
|
|
18
|
+
// Function to add and use unique element IDs.
|
|
19
19
|
const {addTestaroIDs} = require('../procs/testaro');
|
|
20
|
-
//
|
|
20
|
+
// Function to get location data from an element.
|
|
21
21
|
const {getLocationData} = require('../procs/getLocatorData');
|
|
22
22
|
// Modules to run WAX.
|
|
23
23
|
const runWax = require('@wally-ax/wax-dev');
|