testaro 2.1.3 → 2.2.1
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/README.md +18 -9
- package/package.json +1 -1
- package/tests/hover.js +203 -165
- package/tests/radioSet.js +1 -1
- package/validation/executors/appBatch.js +87 -0
- package/validation/executors/appNoBatch.js +67 -0
- package/validation/executors/tests.js +53 -0
- package/validation/{scripts/test → tests/scripts}/bulk.json +2 -2
- package/validation/{scripts/test → tests/scripts}/embAc.json +2 -2
- package/validation/{scripts/test → tests/scripts}/focAll.json +3 -3
- package/validation/{scripts/test → tests/scripts}/focInd.json +2 -2
- package/validation/{scripts/test → tests/scripts}/focOp.json +2 -2
- package/validation/{scripts/test → tests/scripts}/hover.json +2 -2
- package/validation/{scripts/test → tests/scripts}/labClash.json +2 -2
- package/validation/{scripts/test → tests/scripts}/linkUl.json +3 -3
- package/validation/{scripts/test → tests/scripts}/menuNav.json +2 -2
- package/validation/{scripts/test → tests/scripts}/motion.json +2 -2
- package/validation/{scripts/test → tests/scripts}/radioSet.json +2 -2
- package/validation/{scripts/test → tests/scripts}/role.json +2 -2
- package/validation/{scripts/test → tests/scripts}/styleDiff.json +2 -2
- package/validation/{scripts/test → tests/scripts}/tabNav.json +2 -2
- package/validation/{scripts/test → tests/scripts}/zIndex.json +2 -2
- package/validation/{targets → tests/targets}/bulk/bad.html +0 -0
- package/validation/{targets → tests/targets}/bulk/good.html +0 -0
- package/validation/{targets → tests/targets}/embAc/bad.html +0 -0
- package/validation/{targets → tests/targets}/embAc/good.html +0 -0
- package/validation/{targets → tests/targets}/focAll/good.html +0 -0
- package/validation/{targets → tests/targets}/focAll/less.html +0 -0
- package/validation/{targets → tests/targets}/focAll/more.html +0 -0
- package/validation/{targets → tests/targets}/focInd/bad.html +0 -0
- package/validation/{targets → tests/targets}/focInd/good.html +0 -0
- package/validation/{targets → tests/targets}/focOp/bad.html +0 -0
- package/validation/{targets → tests/targets}/focOp/good.html +0 -0
- package/validation/{targets → tests/targets}/hover/bad.html +0 -0
- package/validation/{targets → tests/targets}/hover/good.html +0 -0
- package/validation/{targets → tests/targets}/labClash/bad.html +0 -0
- package/validation/{targets → tests/targets}/labClash/good.html +0 -0
- package/validation/{targets → tests/targets}/linkUl/bad.html +0 -0
- package/validation/{targets → tests/targets}/linkUl/good.html +0 -0
- package/validation/{targets → tests/targets}/linkUl/na.html +0 -0
- package/validation/{targets → tests/targets}/menuNav/bad.html +0 -0
- package/validation/{targets → tests/targets}/menuNav/bad.js +0 -0
- package/validation/{targets → tests/targets}/menuNav/good.html +0 -0
- package/validation/{targets → tests/targets}/menuNav/good.js +0 -0
- package/validation/{targets → tests/targets}/menuNav/style.css +0 -0
- package/validation/{targets → tests/targets}/motion/bad.css +0 -0
- package/validation/{targets → tests/targets}/motion/bad.html +0 -0
- package/validation/{targets → tests/targets}/motion/good.html +0 -0
- package/validation/{targets → tests/targets}/radioSet/bad.html +0 -0
- package/validation/{targets → tests/targets}/radioSet/good.html +0 -0
- package/validation/{targets → tests/targets}/role/bad.html +0 -0
- package/validation/{targets → tests/targets}/role/good.html +0 -0
- package/validation/{targets → tests/targets}/styleDiff/bad.html +0 -0
- package/validation/{targets → tests/targets}/styleDiff/good.html +0 -0
- package/validation/{targets → tests/targets}/tabNav/bad.html +0 -0
- package/validation/{targets → tests/targets}/tabNav/bad.js +0 -0
- package/validation/{targets → tests/targets}/tabNav/good.html +0 -0
- package/validation/{targets → tests/targets}/tabNav/good.js +0 -0
- package/validation/{targets → tests/targets}/tabNav/goodMoz.js +0 -0
- package/validation/{targets → tests/targets}/tabNav/style.css +0 -0
- package/validation/{targets → tests/targets}/zIndex/bad.html +0 -0
- package/validation/{targets → tests/targets}/zIndex/good.html +0 -0
- package/validation/batches/sample.json +0 -13
- package/validation/executors/sample.js +0 -11
- package/validation/scripts/app/sample.json +0 -21
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@ Testaro is a collection of web accessibility tests.
|
|
|
8
8
|
|
|
9
9
|
The purpose of Testaro is to provide programmatic access to over 600 accessibility tests defined in several test packages and in Testaro itself.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Running Testaro requires telling it which operations (including tests) to perform and which URLs to perform them on, and giving Testaro an object to put its output into.
|
|
12
12
|
|
|
13
|
-
Testaro outputs progress messages
|
|
13
|
+
Testaro outputs progress messages to the standard output. It populates the object with log information and test reports.
|
|
14
14
|
|
|
15
15
|
## System requirements
|
|
16
16
|
|
|
@@ -47,7 +47,7 @@ The main directories containing code files are:
|
|
|
47
47
|
- package root: main code files
|
|
48
48
|
- `tests`: files containing the code defining particular tests
|
|
49
49
|
- `procs`: shared procedures
|
|
50
|
-
- `validation`: code and artifacts for the validation of
|
|
50
|
+
- `validation`: code and artifacts for the validation of Testaro
|
|
51
51
|
|
|
52
52
|
## Installation
|
|
53
53
|
|
|
@@ -256,12 +256,6 @@ An example of a **Testaro-defined** test is:
|
|
|
256
256
|
|
|
257
257
|
In this case, Testaro runs the `motion` test with the specified parameters.
|
|
258
258
|
|
|
259
|
-
###### Validation
|
|
260
|
-
|
|
261
|
-
For each of the non-package tests defined in Testaro, a validating script and some files tested by it are also provided. They are in the `validation` directory. A module that you can use to execute those scripts is also there, named `validator.js`.
|
|
262
|
-
|
|
263
|
-
For example, to execute the `focOp.json` validation script, you can enter `node validation/validator focOp`. The `validator.js` module outputs the report to the console.
|
|
264
|
-
|
|
265
259
|
##### Scoring
|
|
266
260
|
|
|
267
261
|
An example of a **scoring** command is:
|
|
@@ -383,6 +377,8 @@ The second item in each array, if there are 3 items in the array, is an operator
|
|
|
383
377
|
- `>`: greater than
|
|
384
378
|
- `!`: unequal to
|
|
385
379
|
|
|
380
|
+
A typical use for an `expect` property is checking the correctness of a Testaro test. Thus, the validation scripts in the `validation/tests/scripts` directory all contain `test` commands with `expect` properties. See the “Validation” section below.
|
|
381
|
+
|
|
386
382
|
## Batches
|
|
387
383
|
|
|
388
384
|
There are two ways to use a script to give instructions to Testaro:
|
|
@@ -442,6 +438,19 @@ If a `wave` test is included in the script, an environment variable named `TESTA
|
|
|
442
438
|
|
|
443
439
|
Before executing a Testaro script, you can optionally also set the environment variables `TESTARO_DEBUG` (to `'true'` or anything else) and/or `TESTARO_WAITS` (to a non-negative integer). The effects of these variables are described in the `index.js` file.
|
|
444
440
|
|
|
441
|
+
## Validation
|
|
442
|
+
|
|
443
|
+
Three _executors_ for Testaro validation are located in the `validation` directory. An executor is a commonJS JavaScript module that runs Testaro and reports whether the results are correct.
|
|
444
|
+
|
|
445
|
+
The executors are:
|
|
446
|
+
- `appNoBatch.js`: Reports whether Testaro runs correctly with a no-batch script.
|
|
447
|
+
- `appBatch.js`: Reports whether Testaro runs correctly with a script and a batch.
|
|
448
|
+
- `tests.js`: Runs Testaro with each custom test and reports whether the results are correct.
|
|
449
|
+
|
|
450
|
+
To execute any executor `xyz.js`, call it with the statement `node validation/executors/xyz`. The results will appear in the standard output.
|
|
451
|
+
|
|
452
|
+
The `tests.js` executor makes use of the scripts in the `validation/tests/scripts` directory, and they, in turn, run tests on HTML files in the `validation/tests/targets` directory.
|
|
453
|
+
|
|
445
454
|
## Contribution
|
|
446
455
|
|
|
447
456
|
You can define additional Testaro commands and functionality. Contributions are welcome.
|
package/package.json
CHANGED
package/tests/hover.js
CHANGED
|
@@ -8,188 +8,226 @@
|
|
|
8
8
|
examined are the descendants of the grandparent of the element hovered over if that element
|
|
9
9
|
has the tag name 'A' or 'BUTTON' or otherwise the descendants of the element. The only
|
|
10
10
|
elements counted as being made visible by hovering are those with tag names 'A', 'BUTTON',
|
|
11
|
-
'INPUT', and 'SPAN', and those with 'role="menuitem"' attributes.
|
|
11
|
+
'INPUT', and 'SPAN', and those with 'role="menuitem"' attributes. The test waits 700 ms after
|
|
12
|
+
each hover in case of delayed effects. Despite this delay, the test makes the execution time
|
|
13
|
+
practical by randomly sampling targets instead of hovering over all of them. Therefore, the
|
|
14
|
+
results may vary from one execution to another.
|
|
12
15
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
16
|
+
|
|
17
|
+
// CONSTANTS
|
|
18
|
+
|
|
19
|
+
// Selectors of active elements likely to be disclosed by a hover.
|
|
20
|
+
const targetSelectors = ['a', 'button', 'input', '[role=menuitem]', 'span']
|
|
21
|
+
.map(selector => `${selector}:visible`)
|
|
22
|
+
.join(', ');
|
|
23
|
+
// Initialize the result.
|
|
24
|
+
const data = {
|
|
25
|
+
totals: {
|
|
26
|
+
triggers: 0,
|
|
27
|
+
madeVisible: 0,
|
|
28
|
+
opacityChanged: 0,
|
|
29
|
+
opacityAffected: 0,
|
|
30
|
+
unhoverables: 0
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// VARIABLES
|
|
35
|
+
|
|
36
|
+
// Counter.
|
|
37
|
+
let elementsChecked = 0;
|
|
38
|
+
|
|
39
|
+
// FUNCTIONS
|
|
40
|
+
|
|
41
|
+
// Samples a population and returns the sample.
|
|
42
|
+
const getSample = (population, sampleSize) => {
|
|
43
|
+
const popSize = population.length;
|
|
44
|
+
if (sampleSize > 0 && sampleSize < popSize) {
|
|
45
|
+
const sample = new Set();
|
|
46
|
+
while (sample.size < sampleSize) {
|
|
47
|
+
const index = Math.floor(popSize * Math.random());
|
|
48
|
+
sample.add(population[index]);
|
|
36
49
|
}
|
|
37
|
-
|
|
50
|
+
return Array.from(sample);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
// Recursively finds and reports triggers and targets.
|
|
57
|
+
const find = async (withItems, page, triggers) => {
|
|
38
58
|
if (withItems) {
|
|
39
59
|
data.items = {
|
|
40
60
|
triggers: [],
|
|
41
61
|
unhoverables: []
|
|
42
62
|
};
|
|
43
63
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
firstTrigger => {
|
|
64
|
-
const parent = firstTrigger.parentElement;
|
|
65
|
-
if (parent) {
|
|
66
|
-
return parent.parentElement || parent;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
return firstTrigger;
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
firstTrigger
|
|
73
|
-
);
|
|
74
|
-
root = rootJSHandle.asElement();
|
|
75
|
-
}
|
|
76
|
-
// Identify the visible active descendants of the root before the hover.
|
|
77
|
-
const preVisibles = await root.$$(targetSelectors);
|
|
78
|
-
// Identify all the descendants of the root.
|
|
79
|
-
const descendants = await root.$$('*');
|
|
80
|
-
// Identify their opacities before the hover.
|
|
81
|
-
const preOpacities = await page.evaluate(
|
|
82
|
-
elements => elements.map(el => window.getComputedStyle(el).opacity), descendants
|
|
83
|
-
);
|
|
84
|
-
try {
|
|
85
|
-
// Hover over the potential trigger.
|
|
86
|
-
await firstTrigger.hover({timeout: 700});
|
|
87
|
-
// Identify whether it controls other elements.
|
|
88
|
-
const isController = await page.evaluate(
|
|
89
|
-
element => element.ariaHasPopup || element.hasAttribute('aria-controls'), firstTrigger
|
|
90
|
-
);
|
|
91
|
-
// Wait for any delayed and/or slowed hover reaction if likely.
|
|
92
|
-
await page.waitForTimeout(
|
|
93
|
-
elementsChecked++ < 10 || tagName !== triggerTag || isController ? 1200 : 200
|
|
94
|
-
);
|
|
95
|
-
await root.waitForElementState('stable');
|
|
96
|
-
// Identify the visible active descendants of the root during the hover.
|
|
97
|
-
const postVisibles = await root.$$(targetSelectors);
|
|
98
|
-
// Identify the opacities of the descendants of the root during the hover.
|
|
99
|
-
const postOpacities = await page.evaluate(
|
|
100
|
-
elements => elements.map(el => window.getComputedStyle(el).opacity), descendants
|
|
101
|
-
);
|
|
102
|
-
// Identify the elements with opacity changes.
|
|
103
|
-
const opacityTargets = descendants
|
|
104
|
-
.filter((descendant, index) => postOpacities[index] !== preOpacities[index]);
|
|
105
|
-
// Count them and their descendants.
|
|
106
|
-
const opacityAffected = opacityTargets.length
|
|
107
|
-
? await page.evaluate(elements => elements.reduce(
|
|
108
|
-
(total, current) => total + 1 + current.querySelectorAll('*').length, 0
|
|
109
|
-
), opacityTargets)
|
|
110
|
-
: 0;
|
|
111
|
-
// If hovering disclosed any element or changed any opacity:
|
|
112
|
-
if (postVisibles.length > preVisibles.length || opacityAffected) {
|
|
113
|
-
// Preserve the lengthened reaction wait, if any, for the next 5 tries.
|
|
114
|
-
if (elementsChecked < 11) {
|
|
115
|
-
elementsChecked = 5;
|
|
64
|
+
// If any potential disclosure triggers remain:
|
|
65
|
+
if (triggers.length) {
|
|
66
|
+
// Identify the first of them.
|
|
67
|
+
const firstTrigger = triggers[0];
|
|
68
|
+
const tagNameJSHandle = await firstTrigger.getProperty('tagName')
|
|
69
|
+
.catch(error => {
|
|
70
|
+
console.log(`ERROR getting trigger tag name (${error.message})`);
|
|
71
|
+
return '';
|
|
72
|
+
});
|
|
73
|
+
if (tagNameJSHandle) {
|
|
74
|
+
const tagName = await tagNameJSHandle.jsonValue();
|
|
75
|
+
// Identify the root of a subtree likely to contain disclosed elements.
|
|
76
|
+
let root = firstTrigger;
|
|
77
|
+
if (['A', 'BUTTON'].includes(tagName)) {
|
|
78
|
+
const rootJSHandle = await page.evaluateHandle(
|
|
79
|
+
firstTrigger => {
|
|
80
|
+
const parent = firstTrigger.parentElement;
|
|
81
|
+
if (parent) {
|
|
82
|
+
return parent.parentElement || parent;
|
|
116
83
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
position: {
|
|
120
|
-
x: 0,
|
|
121
|
-
y: 0
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
// Wait for any delayed and/or slowed hover reaction.
|
|
125
|
-
await page.waitForTimeout(200);
|
|
126
|
-
await root.waitForElementState('stable');
|
|
127
|
-
// Increment the counts of triggers and targets.
|
|
128
|
-
data.totals.triggers++;
|
|
129
|
-
const madeVisible = Math.max(0, postVisibles.length - preVisibles.length);
|
|
130
|
-
data.totals.madeVisible += madeVisible;
|
|
131
|
-
data.totals.opacityChanged += opacityTargets.length;
|
|
132
|
-
data.totals.opacityAffected += opacityAffected;
|
|
133
|
-
// If details are to be reported:
|
|
134
|
-
if (withItems) {
|
|
135
|
-
// Report them.
|
|
136
|
-
const triggerDataJSHandle = await page.evaluateHandle(args => {
|
|
137
|
-
// Returns the text of an element.
|
|
138
|
-
const textOf = (element, limit) => {
|
|
139
|
-
const text = element.textContent.trim() || element.outerHTML.trim();
|
|
140
|
-
return text.replace(/\s{2,}/sg, ' ').slice(0, limit);
|
|
141
|
-
};
|
|
142
|
-
const trigger = args[0];
|
|
143
|
-
const preVisibles = args[1];
|
|
144
|
-
const postVisibles = args[2];
|
|
145
|
-
const madeVisible = postVisibles
|
|
146
|
-
.filter(el => ! preVisibles.includes(el))
|
|
147
|
-
.map(el => ({
|
|
148
|
-
tagName: el.tagName,
|
|
149
|
-
text: textOf(el, 50)
|
|
150
|
-
}));
|
|
151
|
-
const opacityChanged = args[3].map(el => ({
|
|
152
|
-
tagName: el.tagName,
|
|
153
|
-
text: textOf(el, 50)
|
|
154
|
-
}));
|
|
155
|
-
return {
|
|
156
|
-
tagName: trigger.tagName,
|
|
157
|
-
id: trigger.id || '',
|
|
158
|
-
text: textOf(trigger, 50),
|
|
159
|
-
madeVisible,
|
|
160
|
-
opacityChanged
|
|
161
|
-
};
|
|
162
|
-
}, [firstTrigger, preVisibles, postVisibles, opacityTargets]);
|
|
163
|
-
const triggerData = await triggerDataJSHandle.jsonValue();
|
|
164
|
-
data.items.triggers.push(triggerData);
|
|
84
|
+
else {
|
|
85
|
+
return firstTrigger;
|
|
165
86
|
}
|
|
87
|
+
},
|
|
88
|
+
firstTrigger
|
|
89
|
+
);
|
|
90
|
+
root = rootJSHandle.asElement();
|
|
91
|
+
}
|
|
92
|
+
// Identify the visible active descendants of the root before the hover.
|
|
93
|
+
const preVisibles = await root.$$(targetSelectors);
|
|
94
|
+
// Identify all the descendants of the root.
|
|
95
|
+
const descendants = await root.$$('*');
|
|
96
|
+
// Identify their opacities before the hover.
|
|
97
|
+
const preOpacities = await page.evaluate(
|
|
98
|
+
elements => elements.map(el => window.getComputedStyle(el).opacity), descendants
|
|
99
|
+
);
|
|
100
|
+
try {
|
|
101
|
+
// Hover over the potential trigger.
|
|
102
|
+
await firstTrigger.hover({timeout: 700});
|
|
103
|
+
// Identify whether it is coded as controlling other elements.
|
|
104
|
+
const isController = await page.evaluate(
|
|
105
|
+
element => element.ariaHasPopup || element.hasAttribute('aria-controls'), firstTrigger
|
|
106
|
+
);
|
|
107
|
+
// Wait for any delayed and/or slowed hover reaction, longer if coded as a controller.
|
|
108
|
+
await page.waitForTimeout(isController ? 1200 : 600);
|
|
109
|
+
await root.waitForElementState('stable');
|
|
110
|
+
// Identify the visible active descendants of the root during the hover.
|
|
111
|
+
const postVisibles = await root.$$(targetSelectors);
|
|
112
|
+
// Identify the opacities of the descendants of the root during the hover.
|
|
113
|
+
const postOpacities = await page.evaluate(
|
|
114
|
+
elements => elements.map(el => window.getComputedStyle(el).opacity), descendants
|
|
115
|
+
);
|
|
116
|
+
// Identify the elements with opacity changes.
|
|
117
|
+
const opacityTargets = descendants
|
|
118
|
+
.filter((descendant, index) => postOpacities[index] !== preOpacities[index]);
|
|
119
|
+
// Count them and their descendants.
|
|
120
|
+
const opacityAffected = opacityTargets.length
|
|
121
|
+
? await page.evaluate(elements => elements.reduce(
|
|
122
|
+
(total, current) => total + 1 + current.querySelectorAll('*').length, 0
|
|
123
|
+
), opacityTargets)
|
|
124
|
+
: 0;
|
|
125
|
+
// If hovering disclosed any element or changed any opacity:
|
|
126
|
+
if (postVisibles.length > preVisibles.length || opacityAffected) {
|
|
127
|
+
// Preserve the lengthened reaction wait, if any, for the next 5 tries.
|
|
128
|
+
if (elementsChecked < 11) {
|
|
129
|
+
elementsChecked = 5;
|
|
166
130
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
131
|
+
// Hover over the upper-left corner of the page, to undo any hover reactions.
|
|
132
|
+
await page.hover('body', {
|
|
133
|
+
position: {
|
|
134
|
+
x: 0,
|
|
135
|
+
y: 0
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
// Wait for any delayed and/or slowed hover reaction.
|
|
139
|
+
await page.waitForTimeout(200);
|
|
140
|
+
await root.waitForElementState('stable');
|
|
141
|
+
// Increment the counts of triggers and targets.
|
|
142
|
+
data.totals.triggers++;
|
|
143
|
+
const madeVisible = Math.max(0, postVisibles.length - preVisibles.length);
|
|
144
|
+
data.totals.madeVisible += madeVisible;
|
|
145
|
+
data.totals.opacityChanged += opacityTargets.length;
|
|
146
|
+
data.totals.opacityAffected += opacityAffected;
|
|
147
|
+
// If details are to be reported:
|
|
177
148
|
if (withItems) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
149
|
+
// Report them.
|
|
150
|
+
const triggerDataJSHandle = await page.evaluateHandle(args => {
|
|
151
|
+
// Returns the text of an element.
|
|
152
|
+
const textOf = (element, limit) => {
|
|
153
|
+
const text = element.textContent.trim() || element.outerHTML.trim();
|
|
154
|
+
return text.replace(/\s{2,}/sg, ' ').slice(0, limit);
|
|
155
|
+
};
|
|
156
|
+
const trigger = args[0];
|
|
157
|
+
const preVisibles = args[1];
|
|
158
|
+
const postVisibles = args[2];
|
|
159
|
+
const madeVisible = postVisibles
|
|
160
|
+
.filter(el => ! preVisibles.includes(el))
|
|
161
|
+
.map(el => ({
|
|
162
|
+
tagName: el.tagName,
|
|
163
|
+
text: textOf(el, 50)
|
|
164
|
+
}));
|
|
165
|
+
const opacityChanged = args[3].map(el => ({
|
|
166
|
+
tagName: el.tagName,
|
|
167
|
+
text: textOf(el, 50)
|
|
168
|
+
}));
|
|
169
|
+
return {
|
|
170
|
+
tagName: trigger.tagName,
|
|
171
|
+
id: trigger.id || '',
|
|
172
|
+
text: textOf(trigger, 50),
|
|
173
|
+
madeVisible,
|
|
174
|
+
opacityChanged
|
|
175
|
+
};
|
|
176
|
+
}, [firstTrigger, preVisibles, postVisibles, opacityTargets]);
|
|
177
|
+
const triggerData = await triggerDataJSHandle.jsonValue();
|
|
178
|
+
data.items.triggers.push(triggerData);
|
|
183
179
|
}
|
|
184
180
|
}
|
|
185
|
-
triggerTag = tagName;
|
|
186
181
|
}
|
|
187
|
-
|
|
188
|
-
|
|
182
|
+
catch (error) {
|
|
183
|
+
console.log('ERROR hovering');
|
|
184
|
+
// Returns the text of an element.
|
|
185
|
+
const textOf = async (element, limit) => {
|
|
186
|
+
let text = await element.textContent();
|
|
187
|
+
text = text.trim() || await element.innerHTML();
|
|
188
|
+
return text.trim().replace(/\s*/sg, '').slice(0, limit);
|
|
189
|
+
};
|
|
190
|
+
data.totals.unhoverables++;
|
|
191
|
+
if (withItems) {
|
|
192
|
+
data.items.unhoverables.push({
|
|
193
|
+
tagName: tagName,
|
|
194
|
+
id: firstTrigger.id || '',
|
|
195
|
+
text: await textOf(firstTrigger, 50)
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
189
199
|
}
|
|
190
|
-
|
|
200
|
+
// Process the remaining potential triggers.
|
|
201
|
+
await find(withItems, page, triggers.slice(1));
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
exports.reporter = async (page, withItems) => {
|
|
205
|
+
// Identify the triggers.
|
|
206
|
+
const selectors = [
|
|
207
|
+
'body a:visible',
|
|
208
|
+
'body button:visible',
|
|
209
|
+
'body li:visible, body [onmouseenter]:visible',
|
|
210
|
+
'body [onmouseover]:visible'
|
|
211
|
+
];
|
|
212
|
+
const triggers = await page.$$(selectors.join(', '))
|
|
213
|
+
.catch(error => {
|
|
214
|
+
console.log(`ERROR getting hover triggers (${error.message})`);
|
|
215
|
+
return [];
|
|
216
|
+
});
|
|
217
|
+
// If they number more than the sample size limit, sample them.
|
|
218
|
+
const triggerCount = triggers.length;
|
|
219
|
+
const sampleSize = 15;
|
|
220
|
+
const triggerSample = triggerCount > sampleSize ? getSample(triggers, 15) : triggers;
|
|
191
221
|
// Find and document the hover-triggered disclosures.
|
|
192
|
-
await find(
|
|
222
|
+
await find(withItems, page, triggerSample);
|
|
223
|
+
// If the triggers were sampled:
|
|
224
|
+
if (triggerCount > sampleSize) {
|
|
225
|
+
// Change the totals to population estimates.
|
|
226
|
+
const multiplier = triggerCount / sampleSize;
|
|
227
|
+
Object.keys(data.totals).forEach(key => {
|
|
228
|
+
data.totals[key] = Math.round(multiplier * data.totals[key]);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
193
231
|
// Return the result.
|
|
194
232
|
return {result: data};
|
|
195
233
|
};
|
package/tests/radioSet.js
CHANGED
|
@@ -12,7 +12,7 @@ exports.reporter = async (page, withItems) => {
|
|
|
12
12
|
// If itemization is required:
|
|
13
13
|
if (withItems) {
|
|
14
14
|
// Add the body of the textOf function as a string to the array.
|
|
15
|
-
const textOfBody = await fs.readFile(`${__dirname}
|
|
15
|
+
const textOfBody = await fs.readFile(`${__dirname}/../procs/test/textOf.txt`, 'utf8');
|
|
16
16
|
args.push(textOfBody);
|
|
17
17
|
}
|
|
18
18
|
// Get the result data.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// app.js
|
|
2
|
+
// Validator for Testaro application with a script and a batch.
|
|
3
|
+
|
|
4
|
+
const options = {
|
|
5
|
+
script: {
|
|
6
|
+
what: 'Sample Testaro executor with 1 test',
|
|
7
|
+
strict: true,
|
|
8
|
+
commands: [
|
|
9
|
+
{
|
|
10
|
+
type: 'launch',
|
|
11
|
+
which: 'chromium',
|
|
12
|
+
what: 'Chromium browser'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: 'url',
|
|
16
|
+
which: 'https://*',
|
|
17
|
+
what: 'URL to be replaced with URLs in the batch'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'test',
|
|
21
|
+
which: 'bulk',
|
|
22
|
+
what: 'bulk'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: 'test',
|
|
26
|
+
which: 'noSuchTest',
|
|
27
|
+
what: 'test that does not exist'
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
batch: {
|
|
32
|
+
what: 'Two websites',
|
|
33
|
+
hosts: [
|
|
34
|
+
{
|
|
35
|
+
which: 'https://www.w3.org/',
|
|
36
|
+
what: 'W3C'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
which: 'https://www.wikimedia.org/',
|
|
40
|
+
what: 'Wikimedia'
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
log: [],
|
|
45
|
+
reports: []
|
|
46
|
+
};
|
|
47
|
+
const {handleRequest} = require(`${__dirname}/../../index`);
|
|
48
|
+
const isValidReport = (reports, index) => {
|
|
49
|
+
const isValid = reports[index].acts
|
|
50
|
+
&& reports[index].acts.length === 4
|
|
51
|
+
&& reports[index].acts[2].result
|
|
52
|
+
&& reports[index].acts[2].result.visibleElements
|
|
53
|
+
&& typeof reports[index].acts[2].result.visibleElements === 'number'
|
|
54
|
+
&& reports[index].acts[3].result
|
|
55
|
+
&& typeof reports[index].acts[3].result === 'string'
|
|
56
|
+
&& reports[index].acts[3].result.startsWith('ERROR');
|
|
57
|
+
return isValid;
|
|
58
|
+
};
|
|
59
|
+
handleRequest(options)
|
|
60
|
+
.then(
|
|
61
|
+
() => {
|
|
62
|
+
const {log, reports} = options;
|
|
63
|
+
if (
|
|
64
|
+
log.length === 4
|
|
65
|
+
&& log[1].event === 'timeStamp'
|
|
66
|
+
&& /^[a-z0-9]+$/.test(log[1].value)
|
|
67
|
+
&& log[2].event === 'batchSize'
|
|
68
|
+
&& log[2].value === 2
|
|
69
|
+
) {
|
|
70
|
+
console.log('Success: Log has been correctly populated');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log('Failure: Log empty or invalid');
|
|
74
|
+
console.log(JSON.stringify(log, null, 2));
|
|
75
|
+
}
|
|
76
|
+
if (reports.length === 2 && isValidReport(reports, 0) && isValidReport(reports, 1)) {
|
|
77
|
+
console.log('Success: Reports have been correctly populated');
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.log('Failure: Reports empty or invalid');
|
|
81
|
+
console.log(JSON.stringify(reports, null, 2));
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
rejection => {
|
|
85
|
+
console.log(`Failure: ${rejection}`);
|
|
86
|
+
}
|
|
87
|
+
);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// app.js
|
|
2
|
+
// Validator for Testaro application with a no-batch script.
|
|
3
|
+
|
|
4
|
+
const options = {
|
|
5
|
+
script: {
|
|
6
|
+
what: 'Sample Testaro executor with 1 test',
|
|
7
|
+
strict: true,
|
|
8
|
+
commands: [
|
|
9
|
+
{
|
|
10
|
+
type: 'launch',
|
|
11
|
+
which: 'chromium',
|
|
12
|
+
what: 'Chromium browser'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: 'url',
|
|
16
|
+
which: 'https://example.com/',
|
|
17
|
+
what: 'simple page, replaced if there is a batch'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'test',
|
|
21
|
+
which: 'bulk',
|
|
22
|
+
what: 'bulk'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: 'test',
|
|
26
|
+
which: 'noSuchTest',
|
|
27
|
+
what: 'test that does not exist'
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
log: [],
|
|
32
|
+
reports: []
|
|
33
|
+
};
|
|
34
|
+
const {handleRequest} = require(`${__dirname}/../../index`);
|
|
35
|
+
handleRequest(options)
|
|
36
|
+
.then(
|
|
37
|
+
() => {
|
|
38
|
+
const {log, reports} = options;
|
|
39
|
+
if (log.length === 3 && log[1].event === 'timeStamp' && /^[a-z0-9]+$/.test(log[1].value)) {
|
|
40
|
+
console.log('Success: Log has been correctly populated');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log('Failure: Log empty or invalid');
|
|
44
|
+
console.log(JSON.stringify(log, null, 2));
|
|
45
|
+
}
|
|
46
|
+
if (
|
|
47
|
+
reports.length === 1
|
|
48
|
+
&& reports[0].acts
|
|
49
|
+
&& reports[0].acts.length === 4
|
|
50
|
+
&& reports[0].acts[2].result
|
|
51
|
+
&& reports[0].acts[2].result.visibleElements
|
|
52
|
+
&& typeof reports[0].acts[2].result.visibleElements === 'number'
|
|
53
|
+
&& reports[0].acts[3].result
|
|
54
|
+
&& typeof reports[0].acts[3].result === 'string'
|
|
55
|
+
&& reports[0].acts[3].result.startsWith('ERROR')
|
|
56
|
+
) {
|
|
57
|
+
console.log('Success: Reports have been correctly populated');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.log('Failure: Reports empty or invalid');
|
|
61
|
+
console.log(JSON.stringify(reports, null, 2));
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
rejection => {
|
|
65
|
+
console.log(`Failure: ${rejection}`);
|
|
66
|
+
}
|
|
67
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// app.js
|
|
2
|
+
// Validator for Testaro tests.
|
|
3
|
+
|
|
4
|
+
const fs = require('fs').promises;
|
|
5
|
+
const {handleRequest} = require(`${__dirname}/../../index`);
|
|
6
|
+
const validateTests = async () => {
|
|
7
|
+
const scriptFileNames = await fs.readdir(`${__dirname}/../tests/scripts`);
|
|
8
|
+
for (const scriptFileName of scriptFileNames) {
|
|
9
|
+
const rawScriptJSON = await fs
|
|
10
|
+
.readFile(`${__dirname}/../tests/scripts/${scriptFileName}`, 'utf8');
|
|
11
|
+
const scriptJSON = rawScriptJSON
|
|
12
|
+
.replace(/__targets__/g, `file://${__dirname}/../tests/targets`);
|
|
13
|
+
const script = JSON.parse(scriptJSON);
|
|
14
|
+
const options = {script};
|
|
15
|
+
options.log = [];
|
|
16
|
+
options.reports = [];
|
|
17
|
+
await handleRequest(options);
|
|
18
|
+
const {log, reports} = options;
|
|
19
|
+
if (log.length === 3 && log[1].event === 'timeStamp' && /^[a-z0-9]+$/.test(log[1].value)) {
|
|
20
|
+
console.log('Success: Log has been correctly populated');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.log('Failure: Log empty or invalid');
|
|
24
|
+
console.log(JSON.stringify(log, null, 2));
|
|
25
|
+
}
|
|
26
|
+
if (
|
|
27
|
+
reports.length === 1
|
|
28
|
+
&& reports[0].acts
|
|
29
|
+
&& reports[0].acts.length === script.commands.length
|
|
30
|
+
&& reports[0].acts.every(
|
|
31
|
+
act => act.type && act.type === 'test'
|
|
32
|
+
? act.result && act.result.failureCount !== undefined
|
|
33
|
+
: true
|
|
34
|
+
)
|
|
35
|
+
) {
|
|
36
|
+
console.log('Success: Reports have been correctly populated');
|
|
37
|
+
if (reports[0].acts.every(
|
|
38
|
+
act => act.type === 'test' ? act.result.failureCount === 0 : true
|
|
39
|
+
)) {
|
|
40
|
+
console.log('Success: No failures');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log('Failure: At least one test has at least one failure');
|
|
44
|
+
console.log(JSON.stringify(reports, null, 2));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.log('Failure: Reports empty or invalid');
|
|
49
|
+
console.log(JSON.stringify(reports, null, 2));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
validateTests();
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/bulk/good.html",
|
|
13
13
|
"what": "small page"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"type": "url",
|
|
26
|
-
"which": "
|
|
26
|
+
"which": "__targets__/bulk/bad.html",
|
|
27
27
|
"what": "large page"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/embAc/good.html",
|
|
13
13
|
"what": "page without embedding in links or buttons"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"type": "url",
|
|
29
|
-
"which": "
|
|
29
|
+
"which": "__targets__/embAc/bad.html",
|
|
30
30
|
"what": "page with embeddings in links and buttons"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/focAll/good.html",
|
|
13
13
|
"what": "fully Tab-focusable page"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"type": "url",
|
|
28
|
-
"which": "
|
|
28
|
+
"which": "__targets__/focAll/less.html",
|
|
29
29
|
"what": "partly Tab-focusable page"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"type": "url",
|
|
44
|
-
"which": "
|
|
44
|
+
"which": "__targets__/focAll/more.html",
|
|
45
45
|
"what": "page with added Tab-focusability"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/focInd/good.html",
|
|
13
13
|
"what": "page with outline focus indication"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"type": "url",
|
|
33
|
-
"which": "
|
|
33
|
+
"which": "__targets__/focInd/bad.html",
|
|
34
34
|
"what": "page with mixed focus indication"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/focOp/good.html",
|
|
13
13
|
"what": "page with standard focusability and operability"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"type": "url",
|
|
32
|
-
"which": "
|
|
32
|
+
"which": "__targets__/focOp/bad.html",
|
|
33
33
|
"what": "page with deviant focusability and operability"
|
|
34
34
|
},
|
|
35
35
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/hover/good.html",
|
|
13
13
|
"what": "page with standard hover behavior"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"type": "url",
|
|
30
|
-
"which": "
|
|
30
|
+
"which": "__targets__/hover/bad.html",
|
|
31
31
|
"what": "page with deviant hover behavior"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/labClash/good.html",
|
|
13
13
|
"what": "page with standard labeling"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"type": "url",
|
|
28
|
-
"which": "
|
|
28
|
+
"which": "__targets__/labClash/bad.html",
|
|
29
29
|
"what": "page with deviant labeling"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/linkUl/good.html",
|
|
13
13
|
"what": "page with underlined inline links"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"type": "url",
|
|
29
|
-
"which": "
|
|
29
|
+
"which": "__targets__/linkUl/bad.html",
|
|
30
30
|
"what": "page without underlined inline links"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"type": "url",
|
|
46
|
-
"which": "
|
|
46
|
+
"which": "__targets__/linkUl/na.html",
|
|
47
47
|
"what": "page without inline links"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/menuNav/good.html",
|
|
13
13
|
"what": "page with standard menu navigation"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"type": "url",
|
|
55
|
-
"which": "
|
|
55
|
+
"which": "__targets__/menuNav/bad.html",
|
|
56
56
|
"what": "page with deviant menu navigation"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/motion/good.html",
|
|
13
13
|
"what": "page without motion"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"type": "url",
|
|
33
|
-
"which": "
|
|
33
|
+
"which": "__targets__/motion/bad.html",
|
|
34
34
|
"what": "page with motion"
|
|
35
35
|
},
|
|
36
36
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/radioSet/good.html",
|
|
13
13
|
"what": "page with standard radio-button grouping"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"type": "url",
|
|
28
|
-
"which": "
|
|
28
|
+
"which": "__targets__/radioSet/bad.html",
|
|
29
29
|
"what": "page with deviant radio-button grouping"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/role/good.html",
|
|
13
13
|
"what": "page with standard roles"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"type": "url",
|
|
26
|
-
"which": "
|
|
26
|
+
"which": "__targets__/role/bad.html",
|
|
27
27
|
"what": "page with deviant roles"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/styleDiff/good.html",
|
|
13
13
|
"what": "page with consistent styles"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
"type": "url",
|
|
35
|
-
"which": "
|
|
35
|
+
"which": "__targets__/styleDiff/bad.html",
|
|
36
36
|
"what": "page with consistent styles"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/tabNav/good.html",
|
|
13
13
|
"what": "page with standard menu navigation"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"type": "url",
|
|
55
|
-
"which": "
|
|
55
|
+
"which": "__targets__/tabNav/bad.html",
|
|
56
56
|
"what": "page with deviant menu navigation"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"type": "url",
|
|
12
|
-
"which": "
|
|
12
|
+
"which": "__targets__/zIndex/good.html",
|
|
13
13
|
"what": "page with no explicit z-index attributes"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"type": "url",
|
|
26
|
-
"which": "
|
|
26
|
+
"which": "__targets__/zIndex/bad.html",
|
|
27
27
|
"what": "page with explicit z-index attributes roles"
|
|
28
28
|
},
|
|
29
29
|
{
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// sample.js
|
|
2
|
-
// Sample executor for Testaro.
|
|
3
|
-
|
|
4
|
-
const options = {
|
|
5
|
-
reports: `${__dirname}/../../reports`,
|
|
6
|
-
// To use the sample batch, uncomment the following line.
|
|
7
|
-
batches: `${__dirname}/../../batches/sample.json`,
|
|
8
|
-
script: `${__dirname}/../../scripts/app/sample.json`
|
|
9
|
-
};
|
|
10
|
-
const {handleRequest} = require('../../index');
|
|
11
|
-
handleRequest(options);
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"what": "Sample Testaro executor with 1 test",
|
|
3
|
-
"strict": true,
|
|
4
|
-
"commands": [
|
|
5
|
-
{
|
|
6
|
-
"type": "launch",
|
|
7
|
-
"which": "chromium",
|
|
8
|
-
"what": "Chromium browser"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"type": "url",
|
|
12
|
-
"which": "https://example.com/",
|
|
13
|
-
"what": "simple page, replaced if there is a batch"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"type": "test",
|
|
17
|
-
"which": "bulk",
|
|
18
|
-
"what": "bulk"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|