testaro 64.1.0 → 64.3.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/package.json +1 -1
- package/procs/testaro.js +36 -14
- package/testaro/hovInd.js +115 -270
- package/testaro/motion.js +10 -0
- package/tests/testaro.js +14 -4
package/package.json
CHANGED
package/procs/testaro.js
CHANGED
|
@@ -50,9 +50,11 @@ exports.doTest = async (
|
|
|
50
50
|
// Get all candidates.
|
|
51
51
|
const candidates = document.body.querySelectorAll(candidateSelector);
|
|
52
52
|
let violationCount = 0;
|
|
53
|
-
const
|
|
53
|
+
const standardInstances = [];
|
|
54
54
|
// Get a function that returns a violation description, if any, for the candidate.
|
|
55
55
|
const getBadWhat = eval(`(${getBadWhatString})`);
|
|
56
|
+
let data = {};
|
|
57
|
+
const totals = [0, 0, 0, 0];
|
|
56
58
|
// For each candidate:
|
|
57
59
|
for (const candidate of candidates) {
|
|
58
60
|
// Get the violation description, if any.
|
|
@@ -61,35 +63,55 @@ exports.doTest = async (
|
|
|
61
63
|
if (violationWhat) {
|
|
62
64
|
// Increment the violation count.
|
|
63
65
|
violationCount++;
|
|
66
|
+
let ruleWhat;
|
|
67
|
+
const violationType = typeof violationWhat;
|
|
68
|
+
// If data on the violation were provided:
|
|
69
|
+
if (violationType === 'object') {
|
|
70
|
+
// Get the description and add the data to the rule data.
|
|
71
|
+
ruleWhat = violationWhat.description;
|
|
72
|
+
data[violationCount - 1] = violationWhat.data;
|
|
73
|
+
}
|
|
74
|
+
// Otherwise, i.e. if only a description of the violation was provided:
|
|
75
|
+
else if (violationType === 'string') {
|
|
76
|
+
// Get it.
|
|
77
|
+
ruleWhat = violationWhat;
|
|
78
|
+
}
|
|
64
79
|
// If itemization is required:
|
|
65
80
|
if (withItems) {
|
|
66
|
-
const
|
|
67
|
-
let
|
|
68
|
-
let ruleWhat = violationWhat
|
|
81
|
+
const ruleWhatStart = ruleWhat.slice(0, 2);
|
|
82
|
+
let instanceSeverity = severity;
|
|
69
83
|
// If this violation has a custom severity:
|
|
70
|
-
if (/[0-3]:/.test(
|
|
71
|
-
// Get it
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
if (/[0-3]:/.test(ruleWhatStart)) {
|
|
85
|
+
// Get it.
|
|
86
|
+
instanceSeverity = Number(ruleWhat[0]);
|
|
87
|
+
// Remove it from the violation description.
|
|
88
|
+
ruleWhat = ruleWhat.slice(2);
|
|
89
|
+
// Increment the violation totals.
|
|
90
|
+
totals[instanceSeverity]++;
|
|
74
91
|
}
|
|
75
92
|
// Add an instance to the instances.
|
|
76
|
-
|
|
77
|
-
window.getInstance(candidate, ruleID, ruleWhat, 1,
|
|
93
|
+
standardInstances.push(
|
|
94
|
+
window.getInstance(candidate, ruleID, ruleWhat, 1, instanceSeverity)
|
|
78
95
|
);
|
|
79
96
|
}
|
|
97
|
+
// Otherwise, i.e. if itemization is not required:
|
|
98
|
+
else {
|
|
99
|
+
// Increment the violation totals.
|
|
100
|
+
totals[severity]++;
|
|
101
|
+
}
|
|
80
102
|
}
|
|
81
103
|
}
|
|
82
104
|
// If there are any violations and itemization is not required:
|
|
83
105
|
if (violationCount && ! withItems) {
|
|
84
106
|
// Add a summary instance to the instances.
|
|
85
|
-
|
|
107
|
+
standardInstances.push(
|
|
86
108
|
window.getInstance(null, ruleID, whats, violationCount, severity, summaryTagName)
|
|
87
109
|
);
|
|
88
110
|
}
|
|
89
111
|
return {
|
|
90
|
-
data
|
|
91
|
-
totals
|
|
92
|
-
standardInstances
|
|
112
|
+
data,
|
|
113
|
+
totals,
|
|
114
|
+
standardInstances
|
|
93
115
|
}
|
|
94
116
|
}, [
|
|
95
117
|
withItems,
|
package/testaro/hovInd.js
CHANGED
|
@@ -10,290 +10,135 @@
|
|
|
10
10
|
|
|
11
11
|
/*
|
|
12
12
|
hovInd
|
|
13
|
-
This test reports
|
|
13
|
+
This test reports confusing hover indication.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
// IMPORTS
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
const {getLocatorData} = require('../procs/getLocatorData');
|
|
20
|
-
// Module to draw a sample.
|
|
21
|
-
const {getSample} = require('../procs/sample');
|
|
22
|
-
|
|
23
|
-
// CONSTANTS
|
|
24
|
-
|
|
25
|
-
// Standard non-default hover cursors
|
|
26
|
-
const standardCursor = {
|
|
27
|
-
A: 'pointer',
|
|
28
|
-
INPUT: {
|
|
29
|
-
email: 'text',
|
|
30
|
-
image: 'pointer',
|
|
31
|
-
number: 'text',
|
|
32
|
-
password: 'text',
|
|
33
|
-
search: 'text',
|
|
34
|
-
tel: 'text',
|
|
35
|
-
text: 'text',
|
|
36
|
-
url: 'text'
|
|
37
|
-
}
|
|
38
|
-
};
|
|
18
|
+
const {doTest} = require('../procs/testaro');
|
|
39
19
|
|
|
40
20
|
// FUNCTIONS
|
|
41
21
|
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
// Otherwise, if it is a button:
|
|
86
|
-
else if (tagName === 'BUTTON') {
|
|
87
|
-
// Get whether its hover cursor is standard.
|
|
88
|
-
data.ok = ['default', 'auto'].includes(cursor);
|
|
89
|
-
}
|
|
90
|
-
// Otherwise, i.e. if it has another type and a hover listener:
|
|
91
|
-
else {
|
|
92
|
-
// Assume its hover cursor is standard.
|
|
93
|
-
data.ok = true;
|
|
94
|
-
}
|
|
95
|
-
return data;
|
|
96
|
-
};
|
|
97
|
-
// Returns whether two hover styles are effectively identical.
|
|
98
|
-
const areAlike = (styles0, styles1) => {
|
|
99
|
-
// Return whether they are effectively identical.
|
|
100
|
-
const areAlike = ['backgroundColor', 'border', 'color', 'outline']
|
|
101
|
-
.every(style => styles1[style] === styles0[style]);
|
|
102
|
-
return areAlike;
|
|
103
|
-
};
|
|
104
|
-
// Performs the hovInd test and reports results.
|
|
105
|
-
exports.reporter = async (page, withItems, sampleSize = 20) => {
|
|
106
|
-
// Initialize the result.
|
|
107
|
-
const data = {
|
|
108
|
-
typeTotals: {
|
|
109
|
-
badCursor: 0,
|
|
110
|
-
hoverLikeDefault: 0,
|
|
111
|
-
hoverLikeFocus: 0
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
const totals = [0, 0, 0, 0];
|
|
115
|
-
const standardInstances = [];
|
|
116
|
-
// Identify the triggers.
|
|
117
|
-
const selectors = ['a', 'button', 'input', '[onmouseenter]', '[onmouseover]'];
|
|
118
|
-
const selectorString = selectors.map(selector => `body ${selector}:visible`).join(', ');
|
|
119
|
-
const locAll = page.locator(selectorString);
|
|
120
|
-
const locsAll = await locAll.all();
|
|
121
|
-
// Get the population-to-sample ratio.
|
|
122
|
-
const psRatio = Math.max(1, locsAll.length / sampleSize);
|
|
123
|
-
// Get a sample of the triggers.
|
|
124
|
-
const sampleIndexes = getSample(locsAll, sampleSize);
|
|
125
|
-
const sample = locsAll.filter((loc, index) => sampleIndexes.includes(index));
|
|
126
|
-
// For each trigger:
|
|
127
|
-
for (const loc of sample) {
|
|
128
|
-
try {
|
|
129
|
-
// Get its style properties.
|
|
130
|
-
const preStyles = await getHoverStyles(loc);
|
|
131
|
-
// Focus it.
|
|
132
|
-
await loc.focus({timeout: 500});
|
|
133
|
-
// If focusing succeeds, get its style properties.
|
|
134
|
-
const focStyles = await getHoverStyles(loc);
|
|
135
|
-
// Blur it.
|
|
136
|
-
await loc.blur({timeout: 500});
|
|
137
|
-
// If blurring succeeds, try to hover over it.
|
|
138
|
-
await loc.hover({timeout: 600});
|
|
139
|
-
// If hovering succeeds, get its style properties.
|
|
140
|
-
const hovStyles = await getHoverStyles(loc);
|
|
141
|
-
// If all 3 style declarations belong to the same element:
|
|
142
|
-
if ([focStyles, hovStyles].every(style => style.code === preStyles.code)) {
|
|
143
|
-
// Get data on the element if itemization is required.
|
|
144
|
-
const elData = withItems ? await getLocatorData(loc) : null;
|
|
145
|
-
// If the hover cursor is nonstandard:
|
|
146
|
-
const cursorData = getCursorData(hovStyles);
|
|
147
|
-
if (! cursorData.ok) {
|
|
148
|
-
// Add to the totals.
|
|
149
|
-
totals[2] += psRatio;
|
|
150
|
-
data.typeTotals.badCursor += psRatio;
|
|
151
|
-
// If itemization is required:
|
|
152
|
-
if (withItems) {
|
|
153
|
-
// Add an instance to the result.
|
|
154
|
-
standardInstances.push({
|
|
155
|
-
ruleID: 'hovInd',
|
|
156
|
-
what: `Element has a nonstandard hover cursor (${cursorData.cursor})`,
|
|
157
|
-
ordinalSeverity: 2,
|
|
158
|
-
tagName: elData.tagName,
|
|
159
|
-
id: elData.id,
|
|
160
|
-
location: elData.location,
|
|
161
|
-
excerpt: elData.excerpt
|
|
162
|
-
});
|
|
163
|
-
}
|
|
22
|
+
exports.reporter = async (page, withItems) => {
|
|
23
|
+
const getBadWhat = element => {
|
|
24
|
+
const violationTypes = [];
|
|
25
|
+
const isVisible = element.checkVisibility({
|
|
26
|
+
contentVisibilityAuto: true,
|
|
27
|
+
opacityProperty: true,
|
|
28
|
+
visibilityProperty: true
|
|
29
|
+
});
|
|
30
|
+
// If the element is visible:
|
|
31
|
+
if (isVisible) {
|
|
32
|
+
// Get its live style declaration.
|
|
33
|
+
const styleDec = window.getComputedStyle(element);
|
|
34
|
+
// FUNCTION DEFINITIONS START
|
|
35
|
+
// Returns hover-related style data on a trigger.
|
|
36
|
+
const getStyleData = () => {
|
|
37
|
+
const {
|
|
38
|
+
cursor,
|
|
39
|
+
borderColor,
|
|
40
|
+
borderStyle,
|
|
41
|
+
borderWidth,
|
|
42
|
+
outlineColor,
|
|
43
|
+
outlineStyle,
|
|
44
|
+
outlineWidth,
|
|
45
|
+
outlineOffset,
|
|
46
|
+
color,
|
|
47
|
+
backgroundColor
|
|
48
|
+
} = styleDec;
|
|
49
|
+
return {
|
|
50
|
+
tagName: element.tagName,
|
|
51
|
+
inputType: element.tagName === 'INPUT' ? element.getAttribute('type') || 'text' : null,
|
|
52
|
+
cursor: cursor.replace(/^.+, */, ''),
|
|
53
|
+
border: `${borderColor} ${borderStyle} ${borderWidth}`,
|
|
54
|
+
outline: `${outlineColor} ${outlineStyle} ${outlineWidth} ${outlineOffset}`,
|
|
55
|
+
color,
|
|
56
|
+
backgroundColor
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
// Returns whether the cursor is bad when the element is hovered over.
|
|
60
|
+
const cursorIsBad = hoverCursor => {
|
|
61
|
+
const {tagName, type} = element;
|
|
62
|
+
if (tagName === 'A' || tagName === 'INPUT' && type === 'image') {
|
|
63
|
+
return hoverCursor !== 'pointer';
|
|
164
64
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
totals[1] += psRatio;
|
|
169
|
-
data.typeTotals.hoverLikeDefault += psRatio;
|
|
170
|
-
// If itemization is required:
|
|
171
|
-
if (withItems) {
|
|
172
|
-
// Add an instance to the result.
|
|
173
|
-
standardInstances.push({
|
|
174
|
-
ruleID: 'hovInd',
|
|
175
|
-
what: 'Element border, outline, color, and background color do not change when hovered over',
|
|
176
|
-
ordinalSeverity: 1,
|
|
177
|
-
tagName: elData.tagName,
|
|
178
|
-
id: elData.id,
|
|
179
|
-
location: elData.location,
|
|
180
|
-
excerpt: elData.excerpt
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
// If the hover and focus states are indistinct but differ from the default state:
|
|
185
|
-
if (areAlike(hovStyles, focStyles) && ! areAlike(hovStyles, preStyles)) {
|
|
186
|
-
// Add to the totals.
|
|
187
|
-
totals[1] += psRatio;
|
|
188
|
-
data.typeTotals.hoverLikeFocus += psRatio;
|
|
189
|
-
// If itemization is required:
|
|
190
|
-
if (withItems) {
|
|
191
|
-
// Add an instance to the result.
|
|
192
|
-
standardInstances.push({
|
|
193
|
-
ruleID: 'hovInd',
|
|
194
|
-
what: 'Element border, outline, color, and background color are alike on hover and focus',
|
|
195
|
-
ordinalSeverity: 1,
|
|
196
|
-
tagName: elData.tagName,
|
|
197
|
-
id: elData.id,
|
|
198
|
-
location: elData.location,
|
|
199
|
-
excerpt: elData.excerpt
|
|
200
|
-
});
|
|
65
|
+
if (tagName === 'INPUT') {
|
|
66
|
+
if (['button', 'radio', 'reset', 'submit'].some(typeName => type === typeName)) {
|
|
67
|
+
return hoverCursor !== 'default';
|
|
201
68
|
}
|
|
69
|
+
return hoverCursor !== 'text';
|
|
202
70
|
}
|
|
71
|
+
return ! ['auto', 'default'].includes(hoverCursor);
|
|
72
|
+
};
|
|
73
|
+
// Returns whether two hover styles are effectively identical.
|
|
74
|
+
const areAlike = (styles0, styles1) => {
|
|
75
|
+
// Return whether they are effectively identical.
|
|
76
|
+
const areAlike = ['cursor', 'backgroundColor', 'border', 'color', 'outline']
|
|
77
|
+
.every(style => styles1[style] === styles0[style]);
|
|
78
|
+
return areAlike;
|
|
79
|
+
};
|
|
80
|
+
// FUNCTION DEFINITIONS END
|
|
81
|
+
// Get its style data when neither focused nor hovered over.
|
|
82
|
+
const defaultStyleData = getStyleData();
|
|
83
|
+
// Correct the cursor value.
|
|
84
|
+
defaultStyleData.cursor = 'default';
|
|
85
|
+
// Get its style data when only focused.
|
|
86
|
+
element.focus();
|
|
87
|
+
const focusStyleData = getStyleData();
|
|
88
|
+
// Correct the cursor value.
|
|
89
|
+
focusStyleData.cursor = 'default';
|
|
90
|
+
// Get its style data when only hovered over.
|
|
91
|
+
element.blur();
|
|
92
|
+
element.dispatchEvent(new MouseEvent('mouseenter'));
|
|
93
|
+
const hoverStyleData = getStyleData();
|
|
94
|
+
const data = {};
|
|
95
|
+
// If the cursor is confusing when the element is only hovered over:
|
|
96
|
+
if (cursorIsBad(hoverStyleData.cursor)) {
|
|
97
|
+
// Add this to the violation types.
|
|
98
|
+
violationTypes.push(
|
|
99
|
+
`nonstandard mouse cursor (${hoverStyleData.cursor}) when hovered over`
|
|
100
|
+
);
|
|
203
101
|
}
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
102
|
+
// If the neutral and hover styles are indistinguishable:
|
|
103
|
+
if (areAlike(defaultStyleData, hoverStyleData)) {
|
|
104
|
+
// Add this to the violation types.
|
|
105
|
+
violationTypes.push('normal and hover styles are indistinguishable');
|
|
106
|
+
// Add the details to the data.
|
|
107
|
+
data.n_h = {
|
|
108
|
+
neutral: defaultStyleData,
|
|
109
|
+
hover: hoverStyleData
|
|
110
|
+
};
|
|
210
111
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
112
|
+
// If the focus and hoverstyles are indistinguishable:
|
|
113
|
+
if (areAlike(focusStyleData, hoverStyleData)) {
|
|
114
|
+
// Add this to the violation types.
|
|
115
|
+
violationTypes.push('focus and hover styles are indistinguishable');
|
|
116
|
+
// Add the details to the data.
|
|
117
|
+
data.f_h = {
|
|
118
|
+
focus: focusStyleData,
|
|
119
|
+
hover: hoverStyleData
|
|
120
|
+
};
|
|
218
121
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
122
|
+
// If any violations occurred:
|
|
123
|
+
if (violationTypes.length) {
|
|
124
|
+
const description = `Element styles do not clearly indicate hovering: ${violationTypes.join('; ')}`;
|
|
125
|
+
// If there are additional data:
|
|
126
|
+
if (Object.keys(data).length) {
|
|
127
|
+
// Return the violation description and data.
|
|
128
|
+
return {
|
|
129
|
+
description,
|
|
130
|
+
data
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// Otherwise, i.e. if there are no additional data:
|
|
134
|
+
else {
|
|
135
|
+
// Return the violation description.
|
|
136
|
+
return description;
|
|
137
|
+
}
|
|
223
138
|
}
|
|
224
|
-
data.prevented = true;
|
|
225
|
-
// Abort this test.
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
// Round the totals.
|
|
230
|
-
Object.keys(data.typeTotals).forEach(rule => {
|
|
231
|
-
data.typeTotals[rule] = Math.round(data.typeTotals[rule]);
|
|
232
|
-
});
|
|
233
|
-
for (const index in totals) {
|
|
234
|
-
totals[index] = Math.round(totals[index]);
|
|
235
|
-
}
|
|
236
|
-
// If itemization is not required:
|
|
237
|
-
if (! withItems) {
|
|
238
|
-
// If any triggers have nonstandard hover cursors:
|
|
239
|
-
if (data.typeTotals.badCursor) {
|
|
240
|
-
// Add a summary instance to the result.
|
|
241
|
-
standardInstances.push({
|
|
242
|
-
ruleID: 'hovInd',
|
|
243
|
-
what: 'Elements have nonstandard hover cursors',
|
|
244
|
-
ordinalSeverity: 2,
|
|
245
|
-
count: data.typeTotals.badCursor,
|
|
246
|
-
tagName: '',
|
|
247
|
-
id: '',
|
|
248
|
-
location: {
|
|
249
|
-
doc: '',
|
|
250
|
-
type: '',
|
|
251
|
-
spec: ''
|
|
252
|
-
},
|
|
253
|
-
excerpt: ''
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
// If any triggers have hover styles not distinct from their default styles:
|
|
257
|
-
if (data.typeTotals.hoverLikeDefault) {
|
|
258
|
-
// Add a summary instance to the result.
|
|
259
|
-
standardInstances.push({
|
|
260
|
-
ruleID: 'hovInd',
|
|
261
|
-
what: 'Element borders, outlines, and background colors do not change when hovered over',
|
|
262
|
-
ordinalSeverity: 1,
|
|
263
|
-
count: data.typeTotals.hoverLikeDefault,
|
|
264
|
-
tagName: '',
|
|
265
|
-
id: '',
|
|
266
|
-
location: {
|
|
267
|
-
doc: '',
|
|
268
|
-
type: '',
|
|
269
|
-
spec: ''
|
|
270
|
-
},
|
|
271
|
-
excerpt: ''
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
// If any triggers have hover styles not distinct from their focus styles:
|
|
275
|
-
if (data.typeTotals.hoverLikeFocus) {
|
|
276
|
-
// Add a summary instance to the result.
|
|
277
|
-
standardInstances.push({
|
|
278
|
-
ruleID: 'hovInd',
|
|
279
|
-
what: 'Element borders, outlines, and background colors on focus and on hover do not differ',
|
|
280
|
-
ordinalSeverity: 1,
|
|
281
|
-
count: data.typeTotals.hoverLikeFocus,
|
|
282
|
-
tagName: '',
|
|
283
|
-
id: '',
|
|
284
|
-
location: {
|
|
285
|
-
doc: '',
|
|
286
|
-
type: '',
|
|
287
|
-
spec: ''
|
|
288
|
-
},
|
|
289
|
-
excerpt: ''
|
|
290
|
-
});
|
|
291
139
|
}
|
|
292
|
-
}
|
|
293
|
-
// Return the result.
|
|
294
|
-
return {
|
|
295
|
-
data,
|
|
296
|
-
totals,
|
|
297
|
-
standardInstances
|
|
298
140
|
};
|
|
141
|
+
const selector = 'a, button, input, [onmouseenter], [onmouseover]';
|
|
142
|
+
const whats = 'elements have confusing hover indicators';
|
|
143
|
+
return await doTest(page, withItems, 'hovInd', selector, whats, 1, null, getBadWhat.toString());
|
|
299
144
|
};
|
package/testaro/motion.js
CHANGED
|
@@ -51,6 +51,16 @@ exports.reporter = async page => {
|
|
|
51
51
|
// Report this.
|
|
52
52
|
data.prevented = true;
|
|
53
53
|
data.error = 'Screenshot dimensions differ';
|
|
54
|
+
data.dimensions = {
|
|
55
|
+
shoot0: {
|
|
56
|
+
width: shoot0PNG.width,
|
|
57
|
+
height: shoot0PNG.height
|
|
58
|
+
},
|
|
59
|
+
shoot1: {
|
|
60
|
+
width: shoot1PNG.width,
|
|
61
|
+
height: shoot1PNG.height
|
|
62
|
+
}
|
|
63
|
+
}
|
|
54
64
|
}
|
|
55
65
|
// Otherwise, i.e. if their dimensions are identical:
|
|
56
66
|
else {
|
package/tests/testaro.js
CHANGED
|
@@ -443,7 +443,8 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
443
443
|
rulePreventions: [],
|
|
444
444
|
rulePreventionMessages: {},
|
|
445
445
|
rulesInvalid: [],
|
|
446
|
-
ruleTestTimes: {}
|
|
446
|
+
ruleTestTimes: {},
|
|
447
|
+
ruleData: {}
|
|
447
448
|
};
|
|
448
449
|
const result = {};
|
|
449
450
|
const allRuleIDs = allRules.map(rule => rule.id);
|
|
@@ -554,11 +555,11 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
554
555
|
});
|
|
555
556
|
// Perform the test, subject to the time limit.
|
|
556
557
|
const ruleReport = require(`../testaro/${ruleID}`).reporter(... ruleArgs);
|
|
557
|
-
// Get the
|
|
558
|
+
// Get the rule report or a timeout report.
|
|
558
559
|
const ruleOrTimeoutReport = await Promise.race([timer, ruleReport]);
|
|
559
560
|
// If the test was completed:
|
|
560
561
|
if (! ruleOrTimeoutReport.timedOut) {
|
|
561
|
-
// Add data from the
|
|
562
|
+
// Add data from the rule report to the tool result.
|
|
562
563
|
const endTime = Date.now();
|
|
563
564
|
testTimes.push([ruleID, Math.round((endTime - startTime) / 1000)]);
|
|
564
565
|
Object.keys(ruleOrTimeoutReport).forEach(key => {
|
|
@@ -566,7 +567,7 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
566
567
|
});
|
|
567
568
|
// If the test was prevented:
|
|
568
569
|
if (ruleResult.data?.prevented && ruleResult.data.error) {
|
|
569
|
-
// Add this to the result.
|
|
570
|
+
// Add this to the tool result.
|
|
570
571
|
data.rulePreventions.push(ruleID);
|
|
571
572
|
data.rulePreventionMessages[ruleID] = ruleResult.data.error;
|
|
572
573
|
}
|
|
@@ -575,6 +576,15 @@ exports.reporter = async (page, report, actIndex) => {
|
|
|
575
576
|
// Round them.
|
|
576
577
|
ruleResult.totals = ruleResult.totals.map(total => Math.round(total));
|
|
577
578
|
}
|
|
579
|
+
const ruleDataMiscKeys = Object
|
|
580
|
+
.keys(ruleResult.data)
|
|
581
|
+
.filter(key => ! ['prevented', 'error'].includes(key));
|
|
582
|
+
// For any other property of the rule report data object:
|
|
583
|
+
ruleDataMiscKeys.forEach(key => {
|
|
584
|
+
data.ruleData[ruleID] ??= {};
|
|
585
|
+
// Add it to the tool result.
|
|
586
|
+
data.ruleData[ruleID][key] = ruleResult.data[key];
|
|
587
|
+
});
|
|
578
588
|
// Prevent a retry of the test.
|
|
579
589
|
testSuccess = true;
|
|
580
590
|
// If testing is to stop after a failure and the page failed the test:
|