testaro 74.2.3 → 75.1.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/LICENSE +2 -0
- package/README.md +68 -61
- package/actSpecs-doc.md +25 -1
- package/actSpecs.js +6 -4
- package/package.json +2 -2
- package/procs/catalog.js +12 -1
- package/procs/dateTime.js +4 -2
- package/procs/doActs.js +15 -8
- package/procs/launch.js +0 -1
- package/procs/shoot.js +48 -43
- package/run.js +3 -1
- package/testaro/adbID.js +2 -2
- package/testaro/allCapStyle.js +2 -2
- package/testaro/allCaps.js +3 -3
- package/testaro/allHidden.js +2 -2
- package/testaro/allSlanted.js +2 -2
- package/testaro/altScheme.js +2 -2
- package/testaro/attVal.js +2 -2
- package/testaro/autocomplete.js +3 -2
- package/testaro/bulk.js +2 -2
- package/testaro/buttonMenu.js +3 -3
- package/testaro/captionLoc.js +2 -2
- package/testaro/datalistRef.js +2 -2
- package/testaro/distortion.js +2 -2
- package/testaro/docType.js +1 -1
- package/testaro/dupAtt.js +2 -2
- package/testaro/embAc.js +2 -2
- package/testaro/focAll.js +2 -2
- package/testaro/focAndOp.js +2 -2
- package/testaro/focInd.js +2 -2
- package/testaro/focVis.js +2 -2
- package/testaro/headEl.js +2 -2
- package/testaro/headingAmb.js +2 -2
- package/testaro/hovInd.js +2 -2
- package/testaro/hover.js +2 -2
- package/testaro/hr.js +2 -2
- package/testaro/imageLink.js +2 -2
- package/testaro/labClash.js +2 -2
- package/testaro/legendLoc.js +2 -2
- package/testaro/lineHeight.js +2 -2
- package/testaro/linkAmb.js +2 -2
- package/testaro/linkExt.js +2 -2
- package/testaro/linkOldAtt.js +2 -2
- package/testaro/linkTo.js +2 -2
- package/testaro/linkUl.js +2 -2
- package/testaro/miniText.js +2 -2
- package/testaro/motion.js +55 -40
- package/testaro/nonTable.js +2 -2
- package/testaro/optRoleSel.js +2 -2
- package/testaro/phOnly.js +2 -2
- package/testaro/pseudoP.js +2 -2
- package/testaro/radioSet.js +2 -2
- package/testaro/role.js +2 -2
- package/testaro/secHeading.js +2 -2
- package/testaro/styleDiff.js +2 -2
- package/testaro/tabNav.js +2 -2
- package/testaro/targetsNear.js +2 -2
- package/testaro/textNodes.js +1 -1
- package/testaro/textSem.js +2 -2
- package/testaro/titledEl.js +2 -2
- package/testaro/zIndex.js +2 -2
- package/tests/testaro.js +3 -30
- package/testaro/shoot0.js +0 -27
- package/testaro/shoot1.js +0 -33
package/testaro/legendLoc.js
CHANGED
|
@@ -22,7 +22,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
22
22
|
// FUNCTIONS
|
|
23
23
|
|
|
24
24
|
// Runs the test and returns the result.
|
|
25
|
-
exports.reporter = async (page,
|
|
25
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
26
26
|
const getBadWhat = element => {
|
|
27
27
|
const parent = element.parentElement;
|
|
28
28
|
// If the element violates the rule:
|
|
@@ -33,6 +33,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
33
33
|
};
|
|
34
34
|
const whats = 'Legend elements are not the first children of fieldset elements';
|
|
35
35
|
return await doTest(
|
|
36
|
-
page, catalog, withItems, 'legendLoc', 'body legend', whats, 3, getBadWhat.toString()
|
|
36
|
+
page, report.catalog, withItems, 'legendLoc', 'body legend', whats, 3, getBadWhat.toString()
|
|
37
37
|
);
|
|
38
38
|
};
|
package/testaro/lineHeight.js
CHANGED
|
@@ -21,7 +21,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
21
21
|
// FUNCTIONS
|
|
22
22
|
|
|
23
23
|
// Runs the test and returns the result.
|
|
24
|
-
exports.reporter = async (page,
|
|
24
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
25
25
|
const getBadWhat = element => {
|
|
26
26
|
// Get whether the element has a non-spacing child text node.
|
|
27
27
|
const hasText = Array.from(element.childNodes).some(child =>
|
|
@@ -61,6 +61,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
61
61
|
};
|
|
62
62
|
const whats = 'Element line heights are less than 1.5 times their font sizes';
|
|
63
63
|
return await doTest(
|
|
64
|
-
page, catalog, withItems, 'lineHeight', 'body, body *', whats, 1, getBadWhat.toString()
|
|
64
|
+
page, report.catalog, withItems, 'lineHeight', 'body, body *', whats, 1, getBadWhat.toString()
|
|
65
65
|
);
|
|
66
66
|
};
|
package/testaro/linkAmb.js
CHANGED
|
@@ -21,8 +21,8 @@ const {getXPathCatalogIndex} = require('../procs/xPath');
|
|
|
21
21
|
// FUNCTIONS
|
|
22
22
|
|
|
23
23
|
// Runs the test and returns the result.
|
|
24
|
-
exports.reporter = async (page,
|
|
25
|
-
const catalogIndex = getXPathCatalogIndex(catalog, '/html/body');
|
|
24
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
25
|
+
const catalogIndex = getXPathCatalogIndex(report.catalog, '/html/body');
|
|
26
26
|
return await page.evaluate(args => {
|
|
27
27
|
const [withItems, catalogIndex] = args;
|
|
28
28
|
// Get all links.
|
package/testaro/linkExt.js
CHANGED
|
@@ -19,13 +19,13 @@ const {doTest} = require('../procs/testaro');
|
|
|
19
19
|
// FUNCTIONS
|
|
20
20
|
|
|
21
21
|
// Runs the test and returns the result.
|
|
22
|
-
exports.reporter = async (page,
|
|
22
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
23
23
|
const getBadWhat = element => {
|
|
24
24
|
// Return a violation description.
|
|
25
25
|
return `Link has a target=_blank attribute`;
|
|
26
26
|
};
|
|
27
27
|
const whats = 'Links have target=_blank attributes';
|
|
28
28
|
return await doTest(
|
|
29
|
-
page, catalog, withItems, 'linkExt', 'body a[target=_blank]', whats, 0, getBadWhat.toString()
|
|
29
|
+
page, report.catalog, withItems, 'linkExt', 'body a[target=_blank]', whats, 0, getBadWhat.toString()
|
|
30
30
|
);
|
|
31
31
|
};
|
package/testaro/linkOldAtt.js
CHANGED
|
@@ -20,7 +20,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
20
20
|
// FUNCTIONS
|
|
21
21
|
|
|
22
22
|
// Runs the test and returns the result.
|
|
23
|
-
exports.reporter = async (page,
|
|
23
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
24
24
|
const getBadWhat = element => {
|
|
25
25
|
const attNames = element.getAttributeNames();
|
|
26
26
|
const allBadAttNames = ['charset', 'coords', 'name', 'rev', 'shape'];
|
|
@@ -39,6 +39,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
39
39
|
const selector = 'body a[charset], body a[coords], body a[name], body a[rev], body a[shape]';
|
|
40
40
|
const whats = 'Links have deprecated attributes';
|
|
41
41
|
return await doTest(
|
|
42
|
-
page, catalog, withItems, 'linkOldAtt', selector, whats, 1, getBadWhat.toString()
|
|
42
|
+
page, report.catalog, withItems, 'linkOldAtt', selector, whats, 1, getBadWhat.toString()
|
|
43
43
|
);
|
|
44
44
|
};
|
package/testaro/linkTo.js
CHANGED
|
@@ -18,7 +18,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
18
18
|
// FUNCTIONS
|
|
19
19
|
|
|
20
20
|
// Runs the test and returns the result.
|
|
21
|
-
exports.reporter = async (page,
|
|
21
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
22
22
|
const getBadWhat = element => {
|
|
23
23
|
const isVisible = element.checkVisibility({
|
|
24
24
|
contentVisibilityAuto: true,
|
|
@@ -33,6 +33,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
33
33
|
};
|
|
34
34
|
const whats = 'Links are missing href attributes';
|
|
35
35
|
return await doTest(
|
|
36
|
-
page, catalog, withItems, 'linkTo', 'body a:not([href]', whats, 2, getBadWhat.toString()
|
|
36
|
+
page, report.catalog, withItems, 'linkTo', 'body a:not([href]', whats, 2, getBadWhat.toString()
|
|
37
37
|
);
|
|
38
38
|
};
|
package/testaro/linkUl.js
CHANGED
|
@@ -19,7 +19,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
19
19
|
// FUNCTIONS
|
|
20
20
|
|
|
21
21
|
// Runs the test and returns the result.
|
|
22
|
-
exports.reporter = async (page,
|
|
22
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
23
23
|
const getBadWhat = element => {
|
|
24
24
|
let {display, textDecorationLine} = window.getComputedStyle(element);
|
|
25
25
|
// If the element is not underlined:
|
|
@@ -44,6 +44,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
44
44
|
};
|
|
45
45
|
const whats = 'Links with adjacent text are not underlined';
|
|
46
46
|
return await doTest(
|
|
47
|
-
page, catalog, withItems, 'linkUl', 'body a', whats, 1, getBadWhat.toString()
|
|
47
|
+
page, report.catalog, withItems, 'linkUl', 'body a', whats, 1, getBadWhat.toString()
|
|
48
48
|
);
|
|
49
49
|
};
|
package/testaro/miniText.js
CHANGED
|
@@ -22,7 +22,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
22
22
|
// FUNCTIONS
|
|
23
23
|
|
|
24
24
|
// Runs the test and returns the result.
|
|
25
|
-
exports.reporter = async (page,
|
|
25
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
26
26
|
const getBadWhat = element => {
|
|
27
27
|
const rawText = element.textContent || '';
|
|
28
28
|
// If the element has text content with any non-whitespace:
|
|
@@ -59,6 +59,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
59
59
|
};
|
|
60
60
|
const whats = 'Visible elements have font sizes smaller than 11 pixels';
|
|
61
61
|
return await doTest(
|
|
62
|
-
page, catalog, withItems, 'miniText', 'body, body *:not(script, style)', whats, 2, getBadWhat.toString()
|
|
62
|
+
page, report.catalog, withItems, 'miniText', 'body, body *:not(script, style)', whats, 2, getBadWhat.toString()
|
|
63
63
|
);
|
|
64
64
|
};
|
package/testaro/motion.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
/*
|
|
7
7
|
motion
|
|
8
|
-
This test reports motion in a page by
|
|
8
|
+
This test reports motion in a page by making a page image and comparing it with the initial one, i.e. the one made by the catalog proc.
|
|
9
9
|
|
|
10
10
|
For minimal accessibility, standards require motion to be brief, or else stoppable by the user. But stopping motion can be difficult or impossible, and, by the time a user manages to stop motion, the motion may have caused annoyance or harm. For superior accessibility, a page contains no motion until and unless the user authorizes it. The test reports a rule violation if any pixels differ between the screenshots. The larger the change fraction, the greater the ordinal severity.
|
|
11
11
|
|
|
@@ -15,54 +15,69 @@
|
|
|
15
15
|
// IMPORTS
|
|
16
16
|
|
|
17
17
|
const {getXPathCatalogIndex} = require('../procs/xPath');
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
const {shoot} = require('../procs/shoot');
|
|
19
|
+
const pixelmatch = require('pixelmatch').default;
|
|
20
20
|
const {PNG} = require('pngjs');
|
|
21
21
|
|
|
22
22
|
// FUNCTIONS
|
|
23
23
|
|
|
24
24
|
// Runs the test and returns the result.
|
|
25
|
-
exports.reporter = async (
|
|
25
|
+
exports.reporter = async (page, report) => {
|
|
26
26
|
// Initialize the totals and standard instances.
|
|
27
27
|
const data = {};
|
|
28
28
|
const totals = [0, 0, 0, 0];
|
|
29
29
|
const standardInstances = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
30
|
+
// If the initial image exists:
|
|
31
|
+
if (report.images?.length) {
|
|
32
|
+
let violationWhat = '';
|
|
33
|
+
let ordinalSeverity = 0;
|
|
34
|
+
// Make an image with the same color type as the initial one and get its base64 encoding.
|
|
35
|
+
const png = await shoot(page, report, {
|
|
36
|
+
exclusionSelector: null,
|
|
37
|
+
colorType: report.imageColor,
|
|
38
|
+
action: 'return'
|
|
39
|
+
});
|
|
40
|
+
// If this succeeded:
|
|
41
|
+
if (png) {
|
|
42
|
+
// Parse both base64 encodings into PNG objects.
|
|
43
|
+
const initialPNG = PNG.sync.read(Buffer.from(report.images[0], 'base64'));
|
|
44
|
+
const finalPNG = PNG.sync.read(Buffer.from(png, 'base64'));
|
|
45
45
|
// If their dimensions differ:
|
|
46
|
-
if (
|
|
47
|
-
const fromSize = `${width}×${height}`;
|
|
48
|
-
const toSize = `${
|
|
46
|
+
if (finalPNG.width !== initialPNG.width || finalPNG.height !== initialPNG.height) {
|
|
47
|
+
const fromSize = `${initialPNG.width}×${initialPNG.height}`;
|
|
48
|
+
const toSize = `${finalPNG.width}×${finalPNG.height}`;
|
|
49
49
|
// Describe the violation.
|
|
50
50
|
violationWhat = `Page size changes spontaneously (from ${fromSize} to ${toSize})`;
|
|
51
51
|
}
|
|
52
52
|
// Otherwise, i.e. if their dimensions are identical:
|
|
53
53
|
else {
|
|
54
|
-
// Get the count of differing pixels between the
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
// Get the count of differing pixels between the images, using the default sensitivity.
|
|
55
|
+
try {
|
|
56
|
+
const pixelChanges = pixelmatch(
|
|
57
|
+
initialPNG.data,
|
|
58
|
+
finalPNG.data,
|
|
59
|
+
null,
|
|
60
|
+
initialPNG.width,
|
|
61
|
+
initialPNG.height,
|
|
62
|
+
{
|
|
63
|
+
threshold: 0.1
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
// Get the ratio of differing to all pixels as a percentage.
|
|
67
|
+
const changePercent = Math.round(
|
|
68
|
+
100 * pixelChanges / (initialPNG.width * initialPNG.height)
|
|
69
|
+
);
|
|
70
|
+
// If any pixels were changed:
|
|
71
|
+
if (pixelChanges) {
|
|
72
|
+
// Describe the violation.
|
|
73
|
+
violationWhat = `Content changes spontaneously (${changePercent}% of pixels changed)`;
|
|
74
|
+
// Get the ordinal severity from the fractional pixel change.
|
|
75
|
+
ordinalSeverity = Math.floor(Math.min(3, 0.4 * Math.sqrt(changePercent)));
|
|
76
|
+
}
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.log(`pixelmatch error: ${err.message}, ${err.stack}`);
|
|
79
|
+
data.prevented = true;
|
|
80
|
+
data.error = `Pixel comparison failed: ${err.message}`;
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
83
|
// If there was a violation:
|
|
@@ -75,22 +90,22 @@ exports.reporter = async (_0, catalog, _1, tmpDir) => {
|
|
|
75
90
|
what: violationWhat,
|
|
76
91
|
ordinalSeverity,
|
|
77
92
|
count: 1,
|
|
78
|
-
catalogIndex: getXPathCatalogIndex(catalog, '/html/body')
|
|
93
|
+
catalogIndex: getXPathCatalogIndex(report.catalog, '/html/body')
|
|
79
94
|
});
|
|
80
95
|
}
|
|
81
96
|
}
|
|
82
|
-
// Otherwise, i.e. if
|
|
97
|
+
// Otherwise, i.e. if it failed:
|
|
83
98
|
else {
|
|
84
99
|
// Report this.
|
|
85
100
|
data.prevented = true;
|
|
86
|
-
data.error = '
|
|
101
|
+
data.error = 'Image creation failed';
|
|
87
102
|
}
|
|
88
103
|
}
|
|
89
|
-
//
|
|
90
|
-
|
|
104
|
+
// Otherwise, i.e. if the initial image does not exist:
|
|
105
|
+
else {
|
|
91
106
|
// Report this.
|
|
92
107
|
data.prevented = true;
|
|
93
|
-
data.error =
|
|
108
|
+
data.error = 'Initial image missing';
|
|
94
109
|
}
|
|
95
110
|
// Return the result.
|
|
96
111
|
return {
|
package/testaro/nonTable.js
CHANGED
|
@@ -20,7 +20,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
20
20
|
// FUNCTIONS
|
|
21
21
|
|
|
22
22
|
// Runs the test and returns the result.
|
|
23
|
-
exports.reporter = async (page,
|
|
23
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
24
24
|
const getBadWhat = element => {
|
|
25
25
|
// If the element contains another table:
|
|
26
26
|
if (element.querySelector('table')) {
|
|
@@ -56,6 +56,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
56
56
|
};
|
|
57
57
|
const whats = 'table elements are misused for non-table content';
|
|
58
58
|
return await doTest(
|
|
59
|
-
page, catalog, withItems, 'nonTable', 'body table', whats, 2, getBadWhat.toString()
|
|
59
|
+
page, report.catalog, withItems, 'nonTable', 'body table', whats, 2, getBadWhat.toString()
|
|
60
60
|
);
|
|
61
61
|
};
|
package/testaro/optRoleSel.js
CHANGED
|
@@ -22,7 +22,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
22
22
|
// FUNCTIONS
|
|
23
23
|
|
|
24
24
|
// Runs the test and returns the result.
|
|
25
|
-
exports.reporter = async (page,
|
|
25
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
26
26
|
const getBadWhat = element => {
|
|
27
27
|
// If the element has no aria-selected attribute:
|
|
28
28
|
if (! element.hasAttribute('aria-selected')) {
|
|
@@ -32,6 +32,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
32
32
|
};
|
|
33
33
|
const whats = 'Elements with role=option have no aria-selected attributes';
|
|
34
34
|
return await doTest(
|
|
35
|
-
page, catalog, withItems, 'optRoleSel', 'body [role="option"]', whats, 1, getBadWhat.toString()
|
|
35
|
+
page, report.catalog, withItems, 'optRoleSel', 'body [role="option"]', whats, 1, getBadWhat.toString()
|
|
36
36
|
);
|
|
37
37
|
};
|
package/testaro/phOnly.js
CHANGED
|
@@ -22,7 +22,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
22
22
|
// FUNCTIONS
|
|
23
23
|
|
|
24
24
|
// Runs the test and returns the result.
|
|
25
|
-
exports.reporter = async (page,
|
|
25
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
26
26
|
const getBadWhat = element => {
|
|
27
27
|
// Get the accessible name of the element.
|
|
28
28
|
const accessibleName = window.getAccessibleName(element);
|
|
@@ -34,6 +34,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
34
34
|
};
|
|
35
35
|
const whats = 'input elements have placeholders but no accessible names';
|
|
36
36
|
return await doTest(
|
|
37
|
-
page, catalog, withItems, 'phOnly', 'body input[placeholder]', whats, 2, getBadWhat.toString()
|
|
37
|
+
page, report.catalog, withItems, 'phOnly', 'body input[placeholder]', whats, 2, getBadWhat.toString()
|
|
38
38
|
);
|
|
39
39
|
};
|
package/testaro/pseudoP.js
CHANGED
|
@@ -18,7 +18,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
18
18
|
// FUNCTIONS
|
|
19
19
|
|
|
20
20
|
// Runs the test and returns the result.
|
|
21
|
-
exports.reporter = async (page,
|
|
21
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
22
22
|
const getBadWhat = element => {
|
|
23
23
|
// Get the node before the element node.
|
|
24
24
|
const previousNode = element.previousSibling;
|
|
@@ -49,6 +49,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
49
49
|
};
|
|
50
50
|
const whats = 'br elements follow other br elements, possibly constituting pseudo-paragraphs';
|
|
51
51
|
return await doTest(
|
|
52
|
-
page, catalog, withItems, 'pseudoP', 'body br', whats, 0, getBadWhat.toString()
|
|
52
|
+
page, report.catalog, withItems, 'pseudoP', 'body br', whats, 0, getBadWhat.toString()
|
|
53
53
|
);
|
|
54
54
|
};
|
package/testaro/radioSet.js
CHANGED
|
@@ -19,7 +19,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
19
19
|
// FUNCTIONS
|
|
20
20
|
|
|
21
21
|
// Runs the test and returns the result.
|
|
22
|
-
exports.reporter = async (page,
|
|
22
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
23
23
|
const getBadWhat = element => {
|
|
24
24
|
// Get the name of the element.
|
|
25
25
|
const elName = element.name;
|
|
@@ -69,6 +69,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
69
69
|
};
|
|
70
70
|
const whats = 'Radio buttons are not validly grouped in fieldsets with legends';
|
|
71
71
|
return await doTest(
|
|
72
|
-
page, catalog, withItems, 'radioSet', 'body input[type=radio]', whats, 2, getBadWhat.toString()
|
|
72
|
+
page, report.catalog, withItems, 'radioSet', 'body input[type=radio]', whats, 2, getBadWhat.toString()
|
|
73
73
|
);
|
|
74
74
|
};
|
package/testaro/role.js
CHANGED
|
@@ -25,7 +25,7 @@ const implicitRoles = new Set(Array.from(elementRoles.values()).flat());
|
|
|
25
25
|
// FUNCTIONS
|
|
26
26
|
|
|
27
27
|
// Runs the test and returns the result.
|
|
28
|
-
exports.reporter = async (page,
|
|
28
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
29
29
|
// Get locators for the elements with explicit roles.
|
|
30
30
|
const loc = page.locator('[role]');
|
|
31
31
|
const locs = await loc.all();
|
|
@@ -44,5 +44,5 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
44
44
|
}
|
|
45
45
|
// Get and return a result.
|
|
46
46
|
const whats = 'Elements have roles assigned that are also implicit HTML element roles';
|
|
47
|
-
return await getBasicResult(catalog, withItems, 'role', 0, whats, {}, violations);
|
|
47
|
+
return await getBasicResult(report.catalog, withItems, 'role', 0, whats, {}, violations);
|
|
48
48
|
};
|
package/testaro/secHeading.js
CHANGED
|
@@ -20,7 +20,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
20
20
|
// FUNCTIONS
|
|
21
21
|
|
|
22
22
|
// Runs the test and returns the result.
|
|
23
|
-
exports.reporter = async (page,
|
|
23
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
24
24
|
const getBadWhat = element => {
|
|
25
25
|
// Get the children of the element.
|
|
26
26
|
const children = Array.from(element.children);
|
|
@@ -44,6 +44,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
44
44
|
const selector = 'body section, body article, body nav, body aside, body main';
|
|
45
45
|
const whats = 'First child headings of sectioning containers are deeper than others';
|
|
46
46
|
return await doTest(
|
|
47
|
-
page, catalog, withItems, 'secHeading', selector, whats, 0, getBadWhat.toString()
|
|
47
|
+
page, report.catalog, withItems, 'secHeading', selector, whats, 0, getBadWhat.toString()
|
|
48
48
|
);
|
|
49
49
|
};
|
package/testaro/styleDiff.js
CHANGED
|
@@ -81,10 +81,10 @@ const linksByType = async page => await page.evaluateHandle(() => {
|
|
|
81
81
|
};
|
|
82
82
|
});
|
|
83
83
|
// Runs the test and returns the result.
|
|
84
|
-
exports.reporter = async (page,
|
|
84
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
85
85
|
// Get an object with arrays of list links and adjacent links as properties.
|
|
86
86
|
const linkTypes = await linksByType(page);
|
|
87
|
-
const catalogIndex = getXPathCatalogIndex(catalog, '/html/body');
|
|
87
|
+
const catalogIndex = getXPathCatalogIndex(report.catalog, '/html/body');
|
|
88
88
|
return await page.evaluate(args => {
|
|
89
89
|
const [linkTypes, withItems, catalogIndex] = args;
|
|
90
90
|
const {body} = document;
|
package/testaro/tabNav.js
CHANGED
|
@@ -286,7 +286,7 @@ const testTabLists = async (tabLists, withItems, page) => {
|
|
|
286
286
|
}
|
|
287
287
|
};
|
|
288
288
|
// Runs the test and returns the result.
|
|
289
|
-
exports.reporter = async (page,
|
|
289
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
290
290
|
// Initialize the results.
|
|
291
291
|
data.totals = {
|
|
292
292
|
navigations: {
|
|
@@ -374,7 +374,7 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
374
374
|
what: `Tab responds nonstandardly to ${item.navigationErrors.join(', ')}`,
|
|
375
375
|
ordinalSeverity: 1,
|
|
376
376
|
count: 1,
|
|
377
|
-
catalogIndex: getXPathCatalogIndex(catalog, item.xPath)
|
|
377
|
+
catalogIndex: getXPathCatalogIndex(report.catalog, item.xPath)
|
|
378
378
|
});
|
|
379
379
|
});
|
|
380
380
|
}
|
package/testaro/targetsNear.js
CHANGED
|
@@ -20,7 +20,7 @@ const {getXPathCatalogIndex} = require('../procs/xPath');
|
|
|
20
20
|
// FUNCTIONS
|
|
21
21
|
|
|
22
22
|
// Runs the test and returns the result.
|
|
23
|
-
exports.reporter = async (page,
|
|
23
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
24
24
|
// Return totals and standard instances for the rule.
|
|
25
25
|
const protoResult = await page.evaluate(withItems => {
|
|
26
26
|
// Get all pointer targets.
|
|
@@ -142,7 +142,7 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
142
142
|
}, withItems);
|
|
143
143
|
// Convert the XPaths of the proto-instances to catalog indexes.
|
|
144
144
|
protoResult.standardInstances = protoResult.standardInstances.map(instance => {
|
|
145
|
-
instance.catalogIndex = getXPathCatalogIndex(catalog, instance.xPath);
|
|
145
|
+
instance.catalogIndex = getXPathCatalogIndex(report.catalog, instance.xPath);
|
|
146
146
|
delete instance.xPath;
|
|
147
147
|
return instance;
|
|
148
148
|
});
|
package/testaro/textNodes.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// FUNCTIONS
|
|
19
19
|
|
|
20
20
|
// Runs the test and returns the result.
|
|
21
|
-
exports.reporter = async (page,
|
|
21
|
+
exports.reporter = async (page, _0, _1, _2, detailLevel, text = '') => {
|
|
22
22
|
let data = {};
|
|
23
23
|
// Get the data on the text nodes.
|
|
24
24
|
try {
|
package/testaro/textSem.js
CHANGED
|
@@ -19,7 +19,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
19
19
|
// FUNCTIONS
|
|
20
20
|
|
|
21
21
|
// Runs the test and returns the result.
|
|
22
|
-
exports.reporter = async (page,
|
|
22
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
23
23
|
const getBadWhat = element => {
|
|
24
24
|
const isVisible = element.checkVisibility({
|
|
25
25
|
contentVisibilityAuto: true,
|
|
@@ -38,6 +38,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
38
38
|
const selector = 'body i, body b, body small';
|
|
39
39
|
const whats = 'Semantically vague elements i, b, and/or small are used';
|
|
40
40
|
return await doTest(
|
|
41
|
-
page, catalog, withItems, 'textSem', selector, whats, 0, getBadWhat.toString()
|
|
41
|
+
page, report.catalog, withItems, 'textSem', selector, whats, 0, getBadWhat.toString()
|
|
42
42
|
);
|
|
43
43
|
};
|
package/testaro/titledEl.js
CHANGED
|
@@ -20,7 +20,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
20
20
|
// FUNCTIONS
|
|
21
21
|
|
|
22
22
|
// Runs the test and returns the result.
|
|
23
|
-
exports.reporter = async (page,
|
|
23
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
24
24
|
const getBadWhat = element => {
|
|
25
25
|
const elementType = element.tagName.toLowerCase();
|
|
26
26
|
// Return a violation description.
|
|
@@ -29,6 +29,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
29
29
|
const selector = 'body [title]:not(iframe, link, style)';
|
|
30
30
|
const whats = 'title attributes are used on elements they are likely ineffective on';
|
|
31
31
|
return await doTest(
|
|
32
|
-
page, catalog, withItems, 'titledEl', selector, whats, 0, getBadWhat.toString()
|
|
32
|
+
page, report.catalog, withItems, 'titledEl', selector, whats, 0, getBadWhat.toString()
|
|
33
33
|
);
|
|
34
34
|
};
|
package/testaro/zIndex.js
CHANGED
|
@@ -20,7 +20,7 @@ const {doTest} = require('../procs/testaro');
|
|
|
20
20
|
// FUNCTIONS
|
|
21
21
|
|
|
22
22
|
// Runs the test and returns the result.
|
|
23
|
-
exports.reporter = async (page,
|
|
23
|
+
exports.reporter = async (page, report, _, withItems) => {
|
|
24
24
|
const getBadWhat = element => {
|
|
25
25
|
// Get whether the element violates the rule.
|
|
26
26
|
const styleDec = window.getComputedStyle(element);
|
|
@@ -33,6 +33,6 @@ exports.reporter = async (page, catalog, withItems) => {
|
|
|
33
33
|
};
|
|
34
34
|
const whats = 'Elements have non-default Z indexes';
|
|
35
35
|
return await doTest(
|
|
36
|
-
page, catalog, withItems, 'zIndex', 'body, body *', whats, 0, getBadWhat.toString()
|
|
36
|
+
page, report.catalog, withItems, 'zIndex', 'body, body *', whats, 0, getBadWhat.toString()
|
|
37
37
|
);
|
|
38
38
|
};
|
package/tests/testaro.js
CHANGED
|
@@ -23,15 +23,6 @@ const {launch} = require('../procs/launch');
|
|
|
23
23
|
|
|
24
24
|
// Metadata of all rules in default execution order.
|
|
25
25
|
const allRules = [
|
|
26
|
-
{
|
|
27
|
-
id: 'shoot0',
|
|
28
|
-
what: 'first page screenshot',
|
|
29
|
-
contaminates: false,
|
|
30
|
-
needsAccessibleName: false,
|
|
31
|
-
needsTmpDir: true,
|
|
32
|
-
timeOut: 5,
|
|
33
|
-
defaultOn: true
|
|
34
|
-
},
|
|
35
26
|
{
|
|
36
27
|
id: 'adbID',
|
|
37
28
|
what: 'elements with ambiguous or missing referenced descriptions',
|
|
@@ -328,21 +319,11 @@ const allRules = [
|
|
|
328
319
|
timeOut: 5,
|
|
329
320
|
defaultOn: true
|
|
330
321
|
},
|
|
331
|
-
{
|
|
332
|
-
id: 'shoot1',
|
|
333
|
-
what: 'second page screenshot',
|
|
334
|
-
contaminates: false,
|
|
335
|
-
needsAccessibleName: false,
|
|
336
|
-
needsTmpDir: true,
|
|
337
|
-
timeOut: 5,
|
|
338
|
-
defaultOn: true
|
|
339
|
-
},
|
|
340
322
|
{
|
|
341
323
|
id: 'motion',
|
|
342
|
-
what: 'motion without user request
|
|
324
|
+
what: 'motion without user request',
|
|
343
325
|
contaminates: false,
|
|
344
326
|
needsAccessibleName: false,
|
|
345
|
-
needsTmpDir: true,
|
|
346
327
|
timeOut: 5,
|
|
347
328
|
defaultOn: true
|
|
348
329
|
},
|
|
@@ -459,14 +440,6 @@ process.on('unhandledRejection', reason => {
|
|
|
459
440
|
|
|
460
441
|
// FUNCTIONS
|
|
461
442
|
|
|
462
|
-
// Waits.
|
|
463
|
-
const wait = ms => {
|
|
464
|
-
return new Promise(resolve => {
|
|
465
|
-
setTimeout(() => {
|
|
466
|
-
resolve('');
|
|
467
|
-
}, ms);
|
|
468
|
-
});
|
|
469
|
-
};
|
|
470
443
|
// Conducts and reports Testaro tests.
|
|
471
444
|
exports.reporter = async (page, report, actIndex) => {
|
|
472
445
|
const act = report.acts[actIndex];
|
|
@@ -578,13 +551,13 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
578
551
|
browser.on('disconnected', disconnectHandler);
|
|
579
552
|
}
|
|
580
553
|
// Initialize an argument array for the reporter.
|
|
581
|
-
const ruleArgs = [page, report
|
|
554
|
+
const ruleArgs = [page, report, actIndex, withItems];
|
|
582
555
|
// If the rule needs a temporary directory:
|
|
583
556
|
if (rule.needsTmpDir) {
|
|
584
557
|
// Add its path to the argument array.
|
|
585
558
|
ruleArgs.push(report.jobData.tmpDir);
|
|
586
559
|
}
|
|
587
|
-
// If the
|
|
560
|
+
// If the testaro test act specifies extra arguments for this rule:
|
|
588
561
|
if (argRules?.includes(ruleResult.id)) {
|
|
589
562
|
// Add them to the argument array.
|
|
590
563
|
ruleArgs.push(... args[ruleResult.id]);
|
package/testaro/shoot0.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
© 2025–2026 Jonathan Robert Pool.
|
|
3
|
-
Licensed under the MIT License. See LICENSE file for details.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/*
|
|
7
|
-
shoot0
|
|
8
|
-
This test makes and saves the first of two screenshots.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
// IMPORTS
|
|
12
|
-
|
|
13
|
-
const {shoot} = require('../procs/shoot');
|
|
14
|
-
|
|
15
|
-
// FUNCTIONS
|
|
16
|
-
|
|
17
|
-
// Makes and saves the first screenshot.
|
|
18
|
-
exports.reporter = async (page, _, __, tmpDir) => {
|
|
19
|
-
// Make and save the screenshot.
|
|
20
|
-
const pngPath = await shoot(page, 0, tmpDir);
|
|
21
|
-
// Return whether the screenshot was prevented.
|
|
22
|
-
return {
|
|
23
|
-
data: {
|
|
24
|
-
prevented: ! pngPath
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
};
|
package/testaro/shoot1.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
© 2025–2026 Jonathan Robert Pool.
|
|
3
|
-
Licensed under the MIT License. See LICENSE file for details.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/*
|
|
7
|
-
shoot1
|
|
8
|
-
This test makes and saves the second of two screenshots. It aborts if the first screenshot was prevented.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
// IMPORTS
|
|
12
|
-
|
|
13
|
-
const fs = require('fs/promises');
|
|
14
|
-
const {shoot} = require('../procs/shoot');
|
|
15
|
-
|
|
16
|
-
// FUNCTIONS
|
|
17
|
-
|
|
18
|
-
// Make and save the second screenshot.
|
|
19
|
-
exports.reporter = async (page, _0, _1, tmpDir) => {
|
|
20
|
-
const tempFileNames = await fs.readdir(tmpDir);
|
|
21
|
-
let pngPath = '';
|
|
22
|
-
// If there is a shoot0 file:
|
|
23
|
-
if (tempFileNames.includes('testaro-shoot-0.png')) {
|
|
24
|
-
// Make and save the screenshot.
|
|
25
|
-
pngPath = await shoot(page, 1, tmpDir);
|
|
26
|
-
}
|
|
27
|
-
// Return whether the screenshot was prevented.
|
|
28
|
-
return {
|
|
29
|
-
data: {
|
|
30
|
-
prevented: ! pngPath
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
};
|