testilo 21.4.1 → 21.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -20
- package/batch.js +0 -4
- package/merge.js +58 -9
- package/package.json +1 -1
- package/procs/digest/tdp38/index.html +3 -1
- package/procs/score/tic38.js +1 -1
- package/script.js +16 -13
- package/scripts/ts37.json +60 -0
package/README.md
CHANGED
|
@@ -137,9 +137,13 @@ Here is a script:
|
|
|
137
137
|
```javaScript
|
|
138
138
|
{
|
|
139
139
|
id: 'ts99',
|
|
140
|
-
what: '
|
|
140
|
+
what: 'aside mislocation',
|
|
141
141
|
strict: true,
|
|
142
|
+
isolate: true,
|
|
142
143
|
timeLimit: 60,
|
|
144
|
+
standard: 'also',
|
|
145
|
+
observe: false,
|
|
146
|
+
timeStamp: '240115T1200',
|
|
143
147
|
acts: [
|
|
144
148
|
{
|
|
145
149
|
type: 'placeholder',
|
|
@@ -149,27 +153,35 @@ Here is a script:
|
|
|
149
153
|
{
|
|
150
154
|
type: 'test',
|
|
151
155
|
which: 'axe',
|
|
152
|
-
detailLevel:
|
|
153
|
-
rules: [],
|
|
154
|
-
what: 'Axe
|
|
156
|
+
detailLevel: 2,
|
|
157
|
+
rules: ['landmark-complementary-is-top-level'],
|
|
158
|
+
what: 'Axe'
|
|
155
159
|
},
|
|
156
160
|
{
|
|
157
161
|
type: 'test',
|
|
158
162
|
which: 'qualWeb',
|
|
159
163
|
withNewContent: false,
|
|
160
|
-
|
|
164
|
+
rules: ['QW-BP25', 'QW-BP26']
|
|
165
|
+
what: 'QualWeb'
|
|
161
166
|
}
|
|
162
167
|
]
|
|
163
168
|
}
|
|
164
169
|
```
|
|
165
170
|
|
|
166
|
-
|
|
171
|
+
A script has several properties that specify facts about the jobs to be created. They include:
|
|
172
|
+
- `isolate`: You decide whether to isolate test acts, as needed, from effects of previous test acts. If `true`, the `merge` module will add a copy of the latest placeholder after each target-modifying test act before the immediately following test act.
|
|
173
|
+
- `standardize`: You choose how the reports of test acts should be standardized. The alternatives are `'no'` (do not standardize), `'also'` (standardize and report both the original and the standardized results), and `'only'` (standardize and report only the standardized results).
|
|
174
|
+
- `observe`: You decide how granularly Testaro will allow a server to observe job progress. If `true`, Testaro sends a message to the server to announce each test act (identifying the tool), and the `testaro` tool sends a message to the server to announce each rule when its test is performed. The server can further update the requesting client on the basis of these messages.
|
|
175
|
+
- `timeStamp`: You can specify the date and time that the job is to wait for before it is performed. This specification is a string with the format `yymmddThhMM`.
|
|
176
|
+
- `acts`: an array of acts.
|
|
177
|
+
|
|
178
|
+
The first act in this script is a placeholder, whose `which` property is `'private'`. If the above batch were merged with this script, in each job the placeholder would be replaced with the `private` acts of a target. For example, the first act of the first job would launch a Chromium browser, navigate to the Acme login page, complete and submit the login form, wait for the account page to load, run the Axe tests, and then run the QualWeb tests. If the batch contained additional targets, additional jobs would be created, with the login actions for each target specified in the `private` array of the `acts` object of that target.
|
|
167
179
|
|
|
168
|
-
As shown in this example, when a browser is launched by placeholder substitution, the script can determine the browser type (`chromium`, `firefox`, or `webkit`) by assigning a value to a `launch` property of the placeholder.
|
|
180
|
+
As shown in this example, when a browser is launched by placeholder substitution, the script can determine the browser type (`chromium`, `firefox`, or `webkit`) by assigning a value to a `launch` property of the placeholder.
|
|
169
181
|
|
|
170
182
|
### Target list to batch
|
|
171
183
|
|
|
172
|
-
If you have a target list, the `batch` module of Testilo can convert it to a batch. The batch will contain, for each target, one array of acts named `main`, containing a `launch` act (depending on the script to specify the browser type
|
|
184
|
+
If you have a target list, the `batch` module of Testilo can convert it to a batch. The batch will contain, for each target, one array of acts named `main`, containing a `launch` act (depending on the script to specify the browser type and the target to specify the URL).
|
|
173
185
|
|
|
174
186
|
#### Invocation
|
|
175
187
|
|
|
@@ -203,11 +215,13 @@ The `call` module will save the batch as a JSON file in the `batches` subdirecto
|
|
|
203
215
|
|
|
204
216
|
### Issues to script
|
|
205
217
|
|
|
206
|
-
Testilo classifies
|
|
218
|
+
Testilo classifies tool rules into _issues_. The built-in classifications are located in the `procs/score` directory, in files whose names begin with `tic` (for “Testilo issue classification”). You can create additional `tic` files with custom classifications.
|
|
219
|
+
|
|
220
|
+
For example, one of the issues in the `tic38.js` file is `mainNot1`. Four rules are classified as belonging to that issue: rule `main_element_only_one` of `aslint` and 3 more rules defined by 3 other tools.
|
|
207
221
|
|
|
208
|
-
If you want Testaro to test targets for particular issues, you can name those issues and use the Testilo `script` module to create a script.
|
|
222
|
+
If you want Testaro to test targets for only particular issues, you can name those issues and use the Testilo `script` module to create a script for that purpose. The only tools called by the script will be tools that define rules that are classified as belonging to one or more issues named.
|
|
209
223
|
|
|
210
|
-
If you want Testaro to test targets for **all** the rules of all the available tools,
|
|
224
|
+
If you want Testaro to test targets for **all** the rules of all the available tools, you can use the `script` module to create a script that does not impose any issue restrictions.
|
|
211
225
|
|
|
212
226
|
#### Invocation
|
|
213
227
|
|
|
@@ -223,13 +237,13 @@ const scriptObj = script(scriptID, issues, issueID0, issueID1, …);
|
|
|
223
237
|
```
|
|
224
238
|
|
|
225
239
|
This invocation references `scriptID`, `issues`, and `issueID` variables.
|
|
226
|
-
- The `scriptID` variable is an alphanumeric string.
|
|
227
|
-
- The `issues` variable is an object that classifies issues, such as the `issues` object in a `tic` file.
|
|
228
|
-
- The `issueID` variables are strings, such as `'regionNoText'`, that name
|
|
240
|
+
- The `scriptID` variable is an arbitrary alphanumeric string.
|
|
241
|
+
- The `issues` variable (if present) is an object that classifies issues, such as the `issues` object in a `tic` file.
|
|
242
|
+
- The `issueID` variables (if any) are strings, such as `'regionNoText'`, that name properties of the `issues` object.
|
|
229
243
|
|
|
230
|
-
The `script()` function of the `script` module generates a script and returns it as an object. The invoking module can further
|
|
244
|
+
The `script()` function of the `script` module generates a script and returns it as an object. The invoking module can further modify and use the script as needed.
|
|
231
245
|
|
|
232
|
-
To create a script without issue restrictions, a module can use this invocation:
|
|
246
|
+
To create a script **without** issue restrictions, a module can use this invocation:
|
|
233
247
|
|
|
234
248
|
```javaScript
|
|
235
249
|
const {script} = require('testilo/script');
|
|
@@ -241,11 +255,11 @@ const scriptObj = script(scriptID);
|
|
|
241
255
|
A user can invoke `script` in this way: In the Testilo project directory, execute the statement `node call script s c i0 i1 i2 i3 …`.
|
|
242
256
|
|
|
243
257
|
In this statement:
|
|
244
|
-
- Replace `s` with an ID for the script, such as `headings`.
|
|
258
|
+
- Replace `s` with an arbitrary ID for the script, such as `headings`.
|
|
245
259
|
- Replace `c` with the base name, such as `tic99`, of an issue classification file in the `score` subdirectory of the `process.env.FUNCTIONDIR` directory.
|
|
246
260
|
- Replace the remaining arguments (`i0` etc.) with issue IDs from that classification file.
|
|
247
261
|
|
|
248
|
-
The `call` module will retrieve the named classification
|
|
262
|
+
The `call` module will retrieve the named classification.
|
|
249
263
|
The `script` module will create a script.
|
|
250
264
|
The `call` module will save the script as a JSON file in the `scripts` subdirectory of the `process.env.SPECDIR` directory.
|
|
251
265
|
|
|
@@ -259,7 +273,7 @@ When the `script` module creates a script for you, it does not ask you for all o
|
|
|
259
273
|
|
|
260
274
|
Testilo merges batches with scripts, producing jobs, by means of the `merge` module.
|
|
261
275
|
|
|
262
|
-
The `merge` module needs to be given a batch and a script.
|
|
276
|
+
The `merge` module needs to be given a batch and a script.
|
|
263
277
|
|
|
264
278
|
#### Output
|
|
265
279
|
|
|
@@ -362,7 +376,7 @@ A module can invoke `merge` in this way:
|
|
|
362
376
|
|
|
363
377
|
```javaScript
|
|
364
378
|
const {merge} = require('testilo/merge');
|
|
365
|
-
const jobs = merge(script, batch, requester, true, 'only', false);
|
|
379
|
+
const jobs = merge(script, batch, requester, true, 'only', false, '240115T1200');
|
|
366
380
|
```
|
|
367
381
|
|
|
368
382
|
This invocation references `script`, `batch`, and `requester` variables that the module must have already defined. The `script` and `batch` variables are a script object and a batch object, respectively. The `requester` variable is an email address. The fourth argument is a boolean, specifying whether to perform test isolation. The fifth argument is a string that specifies the Testaro standardization option ('also', 'only', or 'no'). The sixth argument is a boolean, specifying whether Testaro will allow granular network watching of the job. The `merge()` function of the `merge` module generates jobs and returns them in an array. The invoking module can further dispose of the jobs as needed.
|
package/batch.js
CHANGED
package/merge.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
3. whether to provide test isolation
|
|
9
9
|
4. value of the standard property
|
|
10
10
|
5. whether reporting is to be granular
|
|
11
|
+
6. date and time as a compact timestamp for job execution, if not now
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
// ########## IMPORTS
|
|
@@ -24,27 +25,75 @@ const contaminantNames = new Set([
|
|
|
24
25
|
'aslint',
|
|
25
26
|
'axe',
|
|
26
27
|
'htmlcs',
|
|
27
|
-
'ibm',
|
|
28
28
|
'testaro'
|
|
29
29
|
]);
|
|
30
|
+
const randomIDChars = (() => {
|
|
31
|
+
const digits = Array(10).fill('').map((digit, index) => index.toString());
|
|
32
|
+
const uppers = Array(26).fill('').map((letter, index) => String.fromCodePoint(65 + index));
|
|
33
|
+
const lowers = Array(26).fill('').map((letter, index) => String.fromCodePoint(97 + index));
|
|
34
|
+
return digits.concat(uppers, lowers);
|
|
35
|
+
})();
|
|
36
|
+
|
|
30
37
|
|
|
31
38
|
// ########## FUNCTIONS
|
|
32
39
|
|
|
40
|
+
// Inserts a character periodically in a string.
|
|
41
|
+
const punctuate = (string, insertion, chunkSize) => {
|
|
42
|
+
const segments = [];
|
|
43
|
+
let startIndex = 0;
|
|
44
|
+
while (startIndex < string.length) {
|
|
45
|
+
segments.push(string.slice(startIndex, startIndex + chunkSize));
|
|
46
|
+
startIndex += chunkSize;
|
|
47
|
+
}
|
|
48
|
+
return segments.join(insertion);
|
|
49
|
+
};
|
|
50
|
+
// Converts a compact timestamp to a date.
|
|
51
|
+
const dateOf = timeStamp => {
|
|
52
|
+
if (/^\d{6}T\d{4}$/.test(timeStamp)) {
|
|
53
|
+
const dateString = punctuate(timeStamp.slice(0, 6), '-', 2);
|
|
54
|
+
const timeString = punctuate(timeStamp.slice(7, 11), ':', 2);
|
|
55
|
+
return new Date(`20${dateString}T${timeString}Z`);
|
|
56
|
+
} else {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
// Converts a date and time to a compact timestamp.
|
|
61
|
+
const stampTime = date => date.toISOString().replace(/[-:]/g, '').slice(2, 13);
|
|
62
|
+
// Generates a random string.
|
|
63
|
+
const getRandomID = length => {
|
|
64
|
+
const chars = [];
|
|
65
|
+
for (let i = 0; i < length; i++) {
|
|
66
|
+
chars.push(randomIDChars[Math.floor(62 * Math.random())]);
|
|
67
|
+
}
|
|
68
|
+
return chars.join('');
|
|
69
|
+
};
|
|
33
70
|
// Merges a script and a batch and returns jobs.
|
|
34
|
-
exports.merge = (script, batch, requester, isolate, standard, isGranular) => {
|
|
71
|
+
exports.merge = (script, batch, requester, isolate, standard, isGranular, timeStamp) => {
|
|
35
72
|
if (isolate === 'false') {
|
|
36
73
|
isolate = false;
|
|
37
74
|
}
|
|
38
|
-
// If
|
|
75
|
+
// If a timestamp was specified:
|
|
76
|
+
if (timeStamp) {
|
|
77
|
+
// If it is invalid:
|
|
78
|
+
if (! dateOf(timeStamp)) {
|
|
79
|
+
// Report this and quit.
|
|
80
|
+
console.log(`ERROR: Timestamp invalid`);
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Otherwise, i.e. if no timestamp was specified:
|
|
85
|
+
else {
|
|
86
|
+
// Create one for the job.
|
|
87
|
+
timeStamp = stampTime(new Date());
|
|
88
|
+
}
|
|
89
|
+
// If the requester is blank or unspecified, make it the standard requester.
|
|
39
90
|
requester ||= stdRequester;
|
|
40
|
-
// Create a
|
|
41
|
-
const timeStamp = new Date().toISOString().replace(/[-:]/g, '').slice(2, 15);
|
|
42
|
-
// Create a time description.
|
|
91
|
+
// Create a creation-time description.
|
|
43
92
|
const creationTime = (new Date()).toISOString().slice(0, 19);
|
|
44
93
|
// Initialize a target-independent job.
|
|
45
94
|
const protoJob = JSON.parse(JSON.stringify(script));
|
|
46
|
-
//
|
|
47
|
-
protoJob.id = `${timeStamp}-${
|
|
95
|
+
// Make the timestamp and a random string the ID of the job.
|
|
96
|
+
protoJob.id = `${timeStamp}-${getRandomID(Number.parseInt(process.env.RANDOM_ID_LENGTH, 10))}`;
|
|
48
97
|
// Add a sources property to the job.
|
|
49
98
|
protoJob.sources = {
|
|
50
99
|
script: script.id,
|
|
@@ -64,7 +113,7 @@ exports.merge = (script, batch, requester, isolate, standard, isGranular) => {
|
|
|
64
113
|
protoJob.observe = isGranular || false;
|
|
65
114
|
// If isolation was requested:
|
|
66
115
|
if (isolate) {
|
|
67
|
-
//
|
|
116
|
+
// Configure the job for it.
|
|
68
117
|
let {acts} = protoJob;
|
|
69
118
|
let lastPlaceholder = {};
|
|
70
119
|
for (const actIndexString in acts) {
|
package/package.json
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
<tr><th>Tested by</th><td>Testaro, procedure <code>__ts__</code></td></tr>
|
|
27
27
|
<tr><th>Scored by</th><td>Testilo, procedure <code>__sp__</code></td></tr>
|
|
28
28
|
<tr><th>Digested by</th><td>Testilo, procedure <code>__dp__</code></td></tr>
|
|
29
|
-
<tr
|
|
29
|
+
<tr>
|
|
30
|
+
<th>Full report</th><td><a href="__reportURL__"><code>__reportURL__</code></a></td>
|
|
31
|
+
</tr>
|
|
30
32
|
</table>
|
|
31
33
|
</header>
|
|
32
34
|
<h2>Introduction</h2>
|
package/procs/score/tic38.js
CHANGED
|
@@ -163,7 +163,7 @@ exports.issues = {
|
|
|
163
163
|
'QW-WCAG-T20': {
|
|
164
164
|
variable: false,
|
|
165
165
|
quality: 0,
|
|
166
|
-
what: 'Link
|
|
166
|
+
what: 'Link title may fail to describe the link correctly [speculative]'
|
|
167
167
|
},
|
|
168
168
|
'QW-WCAG-T23': {
|
|
169
169
|
variable: false,
|
package/script.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
script.js
|
|
3
|
-
Creates and returns a script.
|
|
4
|
-
Arguments:
|
|
5
|
-
0. issue classification
|
|
6
|
-
1. issue IDs
|
|
3
|
+
Creates and returns a script to perform the tests for issues.
|
|
7
4
|
*/
|
|
8
5
|
|
|
9
6
|
// ########## IMPORTS
|
|
@@ -13,6 +10,7 @@ require('dotenv').config();
|
|
|
13
10
|
|
|
14
11
|
// ########## VARIABLES
|
|
15
12
|
|
|
13
|
+
// List of presumptively needed tools.
|
|
16
14
|
let toolIDs = [
|
|
17
15
|
'alfa', 'aslint', 'axe', 'htmlcs', 'ibm', 'nuVal', 'qualWeb', 'testaro', 'wave'
|
|
18
16
|
];
|
|
@@ -21,7 +19,7 @@ let toolIDs = [
|
|
|
21
19
|
|
|
22
20
|
// Creates and returns a script.
|
|
23
21
|
exports.script = (id, issues = null, ... issueIDs) => {
|
|
24
|
-
// Initialize data on the tools and rules for the specified issues.
|
|
22
|
+
// Initialize data on the tools and their rules for the specified issues, if any.
|
|
25
23
|
const neededTools = {};
|
|
26
24
|
// If an issue classification and any issues were specified:
|
|
27
25
|
if (issues && issueIDs.length) {
|
|
@@ -53,42 +51,47 @@ exports.script = (id, issues = null, ... issueIDs) => {
|
|
|
53
51
|
}
|
|
54
52
|
});
|
|
55
53
|
});
|
|
54
|
+
// Remove unneeded tools from the tool list.
|
|
56
55
|
toolIDs = Object.keys(neededTools);
|
|
57
56
|
}
|
|
58
57
|
// Otherwise, i.e. if it does not exist in the classification:
|
|
59
58
|
else {
|
|
60
|
-
// Report this.
|
|
59
|
+
// Report this and quit.
|
|
61
60
|
console.log(`ERROR: Issue ${issueID} not in issue classification`);
|
|
62
61
|
return {};
|
|
63
62
|
}
|
|
64
63
|
});
|
|
65
64
|
}
|
|
66
|
-
// If any
|
|
65
|
+
// If, after any issue-based pruning, any needed tools remain:
|
|
67
66
|
if (toolIDs.length) {
|
|
68
67
|
// Initialize a script.
|
|
69
68
|
const scriptObj = {
|
|
70
69
|
id,
|
|
71
70
|
what: `accessibility tests`,
|
|
72
71
|
strict: true,
|
|
72
|
+
isolate: true,
|
|
73
73
|
timeLimit: 30 + (10 * issueIDs.length || 30 * toolIDs.length),
|
|
74
|
+
standard: 'only',
|
|
75
|
+
observe: true,
|
|
76
|
+
timeStamp: '',
|
|
74
77
|
acts: [
|
|
75
78
|
{
|
|
76
79
|
"type": "placeholder",
|
|
77
80
|
"which": "main",
|
|
78
|
-
"launch": "
|
|
81
|
+
"launch": "webkit"
|
|
79
82
|
}
|
|
80
83
|
]
|
|
81
84
|
};
|
|
82
|
-
// For each
|
|
85
|
+
// For each needed tool:
|
|
83
86
|
toolIDs.forEach(toolID => {
|
|
84
87
|
// Initialize a test act for it.
|
|
85
88
|
const toolAct = {
|
|
86
89
|
type: 'test',
|
|
87
90
|
which: toolID
|
|
88
91
|
};
|
|
89
|
-
// If
|
|
92
|
+
// If issues were specified:
|
|
90
93
|
if (issues && issueIDs.length) {
|
|
91
|
-
// Add a rules property to the act.
|
|
94
|
+
// Add a rules array as a property to the act.
|
|
92
95
|
toolAct.rules = neededTools[toolID];
|
|
93
96
|
// If the tool is Testaro:
|
|
94
97
|
if (toolID === 'testaro') {
|
|
@@ -96,13 +99,13 @@ exports.script = (id, issues = null, ... issueIDs) => {
|
|
|
96
99
|
toolAct.rules.unshift('y');
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
|
-
// Add option specifications
|
|
102
|
+
// Add any needed option specifications to the act.
|
|
100
103
|
if (toolID === 'axe') {
|
|
101
104
|
toolAct.detailLevel = 2;
|
|
102
105
|
}
|
|
103
106
|
else if (toolID === 'ibm') {
|
|
104
107
|
toolAct.withItems = true;
|
|
105
|
-
toolAct.withNewContent =
|
|
108
|
+
toolAct.withNewContent = true;
|
|
106
109
|
}
|
|
107
110
|
else if (toolID === 'qualWeb') {
|
|
108
111
|
toolAct.withNewContent = false;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "ts37",
|
|
3
|
+
"what": "comprehensive accessibility tests with webkit and redirection permitted",
|
|
4
|
+
"strict": false,
|
|
5
|
+
"isolate": true,
|
|
6
|
+
"timeLimit": 600,
|
|
7
|
+
"standard": "only",
|
|
8
|
+
"observe": true,
|
|
9
|
+
"timeStamp": "",
|
|
10
|
+
"acts": [
|
|
11
|
+
{
|
|
12
|
+
"type": "placeholder",
|
|
13
|
+
"which": "main",
|
|
14
|
+
"launch": "webkit"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "test",
|
|
18
|
+
"which": "alfa"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"type": "test",
|
|
22
|
+
"which": "aslint"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "test",
|
|
26
|
+
"which": "axe",
|
|
27
|
+
"detailLevel": 2
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"type": "test",
|
|
31
|
+
"which": "htmlcs"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"type": "test",
|
|
35
|
+
"which": "ibm",
|
|
36
|
+
"withItems": true,
|
|
37
|
+
"withNewContent": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": "test",
|
|
41
|
+
"which": "nuVal"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"type": "test",
|
|
45
|
+
"which": "qualWeb",
|
|
46
|
+
"withNewContent": false
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"type": "test",
|
|
50
|
+
"which": "testaro",
|
|
51
|
+
"withItems": true,
|
|
52
|
+
"stopOnFail": false
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"type": "test",
|
|
56
|
+
"which": "wave",
|
|
57
|
+
"reportType": 4
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|