testilo 36.0.2 → 37.0.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 -19
- package/call.js +1 -3
- package/merge.js +3 -3
- package/package.json +1 -1
- package/procs/difgest/tfp40/index.js +1 -2
- package/procs/digest/tdp40/index.js +2 -2
- package/procs/digest/tdp43e/index.js +2 -2
- package/procs/score/tic43.js +37 -20
- package/procs/track/ttp40/index.js +2 -2
- package/script.js +5 -6
- package/validation/compare/comparer.js +1 -1
- package/validation/digest/digester.js +1 -1
- package/validation/merge/validate.js +7 -7
package/README.md
CHANGED
|
@@ -205,16 +205,15 @@ Here is a script:
|
|
|
205
205
|
timeLimit: 80,
|
|
206
206
|
creationTimeStamp: ''
|
|
207
207
|
executionTimeStamp: '',
|
|
208
|
+
sendReportTo: 'https://abccorp.com/api/report',
|
|
209
|
+
target: {
|
|
210
|
+
what: '',
|
|
211
|
+
url: ''
|
|
212
|
+
},
|
|
208
213
|
sources: {
|
|
209
214
|
script: 'ts99',
|
|
210
215
|
batch: '',
|
|
211
|
-
target: {
|
|
212
|
-
what: '',
|
|
213
|
-
url: ''
|
|
214
|
-
},
|
|
215
|
-
lastTarget: false,
|
|
216
216
|
mergeID: '',
|
|
217
|
-
sendReportTo: 'https://abccorp.com/api/report',
|
|
218
217
|
requester: 'anama@abccorp.com'
|
|
219
218
|
},
|
|
220
219
|
acts: [
|
|
@@ -254,8 +253,9 @@ A script has several properties that specify facts about the jobs to be created.
|
|
|
254
253
|
- `browserID`: This specifies the default browser type (`'chromium'`, `'firefox'`, or `'webkit'`) of the job.
|
|
255
254
|
- `lowMotion`: This is true if the browser is to create tabs with the `reduce-motion` option set to `reduce` instead of `no-preference`. This makes the browser act as if the user has chosen a [motion-reduction option in the settings of the operating system or browser](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion#user_preferences). Motions on pages are, however, often immune to this setting.
|
|
256
255
|
- `creationTimeStamp` and `executionTimeStamp`: These properties will have values assigned to them when jobs are created from the script.
|
|
257
|
-
- `
|
|
258
|
-
- `
|
|
256
|
+
- `sendReportTo`: This is a URL that Testaro is to send its job reports to, or `''` if the jobs will not be network jobs.
|
|
257
|
+
- `target`: This object contains blank `url` and `what` properties, which will be populated each time the script is converted to a job.
|
|
258
|
+
- `sources.script`: This preserves the ID of the script. The `id` property may be revised to a job ID when the script is converted to a job.
|
|
259
259
|
- `sources.requester`: This is the email address to which a message announcing the completion of the job is to be sent, if any.
|
|
260
260
|
- `acts`: an array of acts.
|
|
261
261
|
|
|
@@ -310,8 +310,6 @@ If you specify issue options, the script will prescribe the tests for all evalua
|
|
|
310
310
|
|
|
311
311
|
For example, one issue in the `tic43.js` file is `mainNot1`. Four rules are classified as belonging to that issue: rule `main_element_only_one` of the `aslint` tool and 3 more rules defined by 3 other tools. You can also create custom classifications and save them in a `score` subdirectory of the `FUNCTIONDIR` directory.
|
|
312
312
|
|
|
313
|
-
The `script()` function will populate the `sources.sendReportTo` property with the value, if any, of the environment variable `SEND_REPORT_TO`, and populate the `sources.requester` property with the value, if any, of the environment variable `REQUESTER`.
|
|
314
|
-
|
|
315
313
|
#### Invocation
|
|
316
314
|
|
|
317
315
|
There are two ways to use the `script` module.
|
|
@@ -368,6 +366,9 @@ When the `script` module creates a script for you, it does not ask you for all o
|
|
|
368
366
|
- `browserID`: `'webkit'`
|
|
369
367
|
- `lowMotion`: `false`
|
|
370
368
|
- `timeLimit`: 50 plus 30 per tool
|
|
369
|
+
- `sendReportTo`: `process.env.SEND_REPORT_TO`, or `''` if none
|
|
370
|
+
- `sources.id`: script ID
|
|
371
|
+
- `sources.requester`: `process.env.REQUESTER`, or `''` if none
|
|
371
372
|
- `axe` test act: `detailLevel` = 2
|
|
372
373
|
- `ibm` test act: `withItems` = `true`, `withNewContent` = `false`
|
|
373
374
|
- `qualWeb` test act: `withNewContent` = `false`
|
|
@@ -434,17 +435,15 @@ A Testaro job produced by `merge` will be identical to the script from which it
|
|
|
434
435
|
…
|
|
435
436
|
creationTimeStamp: '241229T0537',
|
|
436
437
|
executionTimeStamp: '250110T1200',
|
|
438
|
+
target: {
|
|
439
|
+
what: 'Real Estate Management',
|
|
440
|
+
url: 'https://abccorp.com/mgmt/realproperty.html'
|
|
441
|
+
},
|
|
437
442
|
sources: {
|
|
438
|
-
|
|
443
|
+
…,
|
|
439
444
|
batch: 'departments',
|
|
440
445
|
mergeID: '7f',
|
|
441
|
-
|
|
442
|
-
requester: 'malavu@abccorp.com'
|
|
443
|
-
target: {
|
|
444
|
-
what: 'Real Estate Management',
|
|
445
|
-
url: 'https://abccorp.com/mgmt/realproperty.html'
|
|
446
|
-
},
|
|
447
|
-
lastTarget: false,
|
|
446
|
+
…
|
|
448
447
|
},
|
|
449
448
|
…
|
|
450
449
|
```
|
|
@@ -863,7 +862,7 @@ To test the `compare` module, in the project directory you can execute the state
|
|
|
863
862
|
|
|
864
863
|
### Track
|
|
865
864
|
|
|
866
|
-
The `track` module of Testilo selects, organizes, and presents data from summaries to show changes over time in total scores. The module produces a web page, showing changes in a table and a line graph. The line graph contains a line for each target (namely, each value of the `
|
|
865
|
+
The `track` module of Testilo selects, organizes, and presents data from summaries to show changes over time in total scores. The module produces a web page, showing changes in a table and a line graph. The line graph contains a line for each target (namely, each value of the `target.what` property).
|
|
867
866
|
|
|
868
867
|
A typical use case for tracking is monitoring, i.e. periodic auditing of one or more web pages.
|
|
869
868
|
|
package/call.js
CHANGED
|
@@ -424,9 +424,7 @@ const callTrack = async (trackerID, what, selector, targetWhat) => {
|
|
|
424
424
|
// Remove unwanted results, if any, from it.
|
|
425
425
|
if (targetWhat) {
|
|
426
426
|
summaryReport.summaries = summaryReport.summaries.filter(
|
|
427
|
-
result => result.
|
|
428
|
-
&& result.sources.target
|
|
429
|
-
&& result.sources.target.what === targetWhat
|
|
427
|
+
result => result.target && result.target.what === targetWhat
|
|
430
428
|
);
|
|
431
429
|
}
|
|
432
430
|
// If any results remain:
|
package/merge.js
CHANGED
|
@@ -109,7 +109,7 @@ exports.merge = (script, batch, executionTimeStamp) => {
|
|
|
109
109
|
if (actGroups && url) {
|
|
110
110
|
// Initialize a job.
|
|
111
111
|
const job = JSON.parse(JSON.stringify(protoJob));
|
|
112
|
-
const {sources} = job;
|
|
112
|
+
const {sources, target} = job;
|
|
113
113
|
// Make the job ID unique.
|
|
114
114
|
const targetSuffix = alphaNumOf(index);
|
|
115
115
|
job.id = `${executionTimeStamp}-${sources.mergeID}-${targetSuffix}`;
|
|
@@ -119,8 +119,8 @@ exports.merge = (script, batch, executionTimeStamp) => {
|
|
|
119
119
|
sources.lastTarget = true;
|
|
120
120
|
}
|
|
121
121
|
// Populate the target-specific properties of the job.
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
target.what = what;
|
|
123
|
+
target.url = url;
|
|
124
124
|
// Replace each placeholder object in the job with the named act group of the target.
|
|
125
125
|
let {acts} = job;
|
|
126
126
|
for (const actIndex in acts) {
|
package/package.json
CHANGED
|
@@ -75,8 +75,7 @@ const populateQuery = (reportA, reportB, query) => {
|
|
|
75
75
|
[reportA, reportB].forEach((report, index) => {
|
|
76
76
|
// Add report-specific synopsis parameters to the query.
|
|
77
77
|
const suffix = ['A', 'B'][index];
|
|
78
|
-
const {id,
|
|
79
|
-
const {target} = sources;
|
|
78
|
+
const {id, jobData, score, target} = report;
|
|
80
79
|
const {summary, details} = score;
|
|
81
80
|
query[`org${suffix}`] = target.what;
|
|
82
81
|
query[`url${suffix}`] = target.which;
|
|
@@ -51,8 +51,8 @@ const getIssueScoreRow = (summary, wcag, score, tools) => {
|
|
|
51
51
|
};
|
|
52
52
|
// Adds parameters to a query for a digest.
|
|
53
53
|
const populateQuery = (report, query) => {
|
|
54
|
-
const {id, sources,
|
|
55
|
-
const {script,
|
|
54
|
+
const {id, score, sources, target} = report;
|
|
55
|
+
const {script, requester} = sources;
|
|
56
56
|
const {scoreProcID, summary, details} = score;
|
|
57
57
|
query.ts = script;
|
|
58
58
|
query.sp = scoreProcID;
|
|
@@ -57,8 +57,8 @@ const getIssueScoreRow = (issueConstants, issueDetails) => {
|
|
|
57
57
|
};
|
|
58
58
|
// Adds parameters to a query for a digest.
|
|
59
59
|
const populateQuery = (report, query) => {
|
|
60
|
-
const {browserID, deviceID, id, isolate, lowMotion, score, sources, standard, strict} = report;
|
|
61
|
-
const {agent,
|
|
60
|
+
const {browserID, deviceID, id, isolate, lowMotion, score, sources, standard, strict, target} = report;
|
|
61
|
+
const {agent, requester, script} = sources;
|
|
62
62
|
const {scoreProcID, summary, details} = score;
|
|
63
63
|
query.ts = script;
|
|
64
64
|
query.sp = scoreProcID;
|
package/procs/score/tic43.js
CHANGED
|
@@ -3130,16 +3130,6 @@ exports.issues = {
|
|
|
3130
3130
|
variable: false,
|
|
3131
3131
|
quality: 1,
|
|
3132
3132
|
what: 'Element has an event handler but no valid ARIA role'
|
|
3133
|
-
},
|
|
3134
|
-
table_aria_descendants: {
|
|
3135
|
-
variable: false,
|
|
3136
|
-
quality: 1,
|
|
3137
|
-
what: 'Table structure element specifies an explicit role within the table container'
|
|
3138
|
-
},
|
|
3139
|
-
aria_child_valid: {
|
|
3140
|
-
variable: false,
|
|
3141
|
-
quality: 1,
|
|
3142
|
-
what: 'Child element has a role not allowed for the role of the parent'
|
|
3143
3133
|
}
|
|
3144
3134
|
},
|
|
3145
3135
|
nuVal: {
|
|
@@ -3153,20 +3143,10 @@ exports.issues = {
|
|
|
3153
3143
|
quality: 1,
|
|
3154
3144
|
what: 'img element has a role attribute but no alt attribute'
|
|
3155
3145
|
},
|
|
3156
|
-
'A figure element with a figcaption descendant must not have a role attribute.': {
|
|
3157
|
-
variable: false,
|
|
3158
|
-
quality: 1,
|
|
3159
|
-
what: 'figure element has a figcaption descendant but has a role attribute'
|
|
3160
|
-
},
|
|
3161
3146
|
'^Discarding unrecognized token .+ from value of attribute role. Browsers ignore any token that is not a defined ARIA non-abstract role.*$': {
|
|
3162
3147
|
variable: true,
|
|
3163
3148
|
quality: 1,
|
|
3164
3149
|
what: 'Invalid role'
|
|
3165
|
-
},
|
|
3166
|
-
'^The role attribute must not be used on a .+ element which has a table ancestor with no role attribute, or with a role attribute whose value is table, grid, or treegrid.*$': {
|
|
3167
|
-
variable: true,
|
|
3168
|
-
quality: 1,
|
|
3169
|
-
what: 'Table cell has a role attribute'
|
|
3170
3150
|
}
|
|
3171
3151
|
},
|
|
3172
3152
|
qualWeb: {
|
|
@@ -3178,6 +3158,43 @@ exports.issues = {
|
|
|
3178
3158
|
}
|
|
3179
3159
|
}
|
|
3180
3160
|
},
|
|
3161
|
+
roleHierarchyBad: {
|
|
3162
|
+
summary: 'ancestor and descendant elements have incompatible roles',
|
|
3163
|
+
why: 'User may misunderstand or be blocked from exposure to an item',
|
|
3164
|
+
wcag: '4.1.2',
|
|
3165
|
+
weight: 4,
|
|
3166
|
+
tools: {
|
|
3167
|
+
ibm: {
|
|
3168
|
+
aria_child_valid: {
|
|
3169
|
+
variable: false,
|
|
3170
|
+
quality: 1,
|
|
3171
|
+
what: 'Child element has a role not allowed for the role of the parent'
|
|
3172
|
+
},
|
|
3173
|
+
aria_descendant_valid: {
|
|
3174
|
+
variable: false,
|
|
3175
|
+
quality: 1,
|
|
3176
|
+
what: 'Element and descendant roles make browsers ignore a descendant'
|
|
3177
|
+
},
|
|
3178
|
+
table_aria_descendants: {
|
|
3179
|
+
variable: false,
|
|
3180
|
+
quality: 1,
|
|
3181
|
+
what: 'Table structure element specifies an explicit role within the table container'
|
|
3182
|
+
}
|
|
3183
|
+
},
|
|
3184
|
+
nuVal: {
|
|
3185
|
+
'A figure element with a figcaption descendant must not have a role attribute.': {
|
|
3186
|
+
variable: false,
|
|
3187
|
+
quality: 1,
|
|
3188
|
+
what: 'figure element has a figcaption descendant but has a role attribute'
|
|
3189
|
+
},
|
|
3190
|
+
'^The role attribute must not be used on a .+ element which has a table ancestor with no role attribute, or with a role attribute whose value is table, grid, or treegrid.*$': {
|
|
3191
|
+
variable: true,
|
|
3192
|
+
quality: 1,
|
|
3193
|
+
what: 'Table cell has a role attribute'
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
},
|
|
3181
3198
|
roleRedundant: {
|
|
3182
3199
|
summary: 'role redundant',
|
|
3183
3200
|
why: 'Document includes unnecessary code',
|
|
@@ -58,7 +58,7 @@ const populateQuery = async (id, what, summaryReport, query) => {
|
|
|
58
58
|
// Get an array of target descriptions and assign to each an ID.
|
|
59
59
|
const rows = [];
|
|
60
60
|
const targets = Array
|
|
61
|
-
.from(new Set(summaries.map(result => result.
|
|
61
|
+
.from(new Set(summaries.map(result => result.target.what)))
|
|
62
62
|
.sort()
|
|
63
63
|
.map((targetWhat, index) => [alphaNumOf(index), targetWhat]);
|
|
64
64
|
const targetIDs = {};
|
|
@@ -70,13 +70,13 @@ const populateQuery = async (id, what, summaryReport, query) => {
|
|
|
70
70
|
query.legendItems = legendItems.join('\n ');
|
|
71
71
|
// For each result:
|
|
72
72
|
summaries.forEach(result => {
|
|
73
|
+
const {id, score, target} = result;
|
|
73
74
|
// Create a date-time cell.
|
|
74
75
|
const timeCell = `<td>${result.endTime}</td>`;
|
|
75
76
|
// Create a score cell.
|
|
76
77
|
const digestLinkDestination = digestURL.replace('__id__', result.id);
|
|
77
78
|
const scoreCell = `<td><a href=${digestLinkDestination}>${result.score}</a></td>`;
|
|
78
79
|
// Create a target cell.
|
|
79
|
-
const {target} = result.sources;
|
|
80
80
|
const targetLink = `<a href="${target.url}">${target.what}</a>`;
|
|
81
81
|
const targetCell = `<td>${targetIDs[target.what]}: ${targetLink}</td>`;
|
|
82
82
|
const row = `<tr>${[timeCell, scoreCell, targetCell].join('')}</tr>`;
|
package/script.js
CHANGED
|
@@ -124,16 +124,15 @@ exports.script = (id, what, options = {}) => {
|
|
|
124
124
|
timeLimit: Math.round(50 + 30 * Object.keys(toolsRulesData).length),
|
|
125
125
|
creationTimeStamp: '',
|
|
126
126
|
executionTimeStamp: '',
|
|
127
|
+
sendReportTo: process.env.SEND_REPORT_TO || '',
|
|
128
|
+
target: {
|
|
129
|
+
what: '',
|
|
130
|
+
url: ''
|
|
131
|
+
},
|
|
127
132
|
sources: {
|
|
128
133
|
script: id,
|
|
129
134
|
batch: '',
|
|
130
|
-
target: {
|
|
131
|
-
what: '',
|
|
132
|
-
url: ''
|
|
133
|
-
},
|
|
134
|
-
lastTarget: false,
|
|
135
135
|
mergeID: '',
|
|
136
|
-
sendReportTo: process.env.SEND_REPORT_TO || '',
|
|
137
136
|
requester: process.env.REQUESTER || ''
|
|
138
137
|
},
|
|
139
138
|
acts: [
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// Adds parameters to a query for a comparison.
|
|
31
31
|
exports.comparer = (reports, query) => {
|
|
32
32
|
const entries = reports.map(report => ({
|
|
33
|
-
target: report.
|
|
33
|
+
target: report.target.what,
|
|
34
34
|
score: report.score.total
|
|
35
35
|
}));
|
|
36
36
|
const entriesHTML = entries
|
|
@@ -66,7 +66,7 @@ const validate = async () => {
|
|
|
66
66
|
if (jobArrays.every(array => [0, 1].every(
|
|
67
67
|
jobIndex => {
|
|
68
68
|
const job = array[jobIndex];
|
|
69
|
-
return job.id === `${job.timeStamp}-${job.sources.script}-${job.
|
|
69
|
+
return job.id === `${job.timeStamp}-${job.sources.script}-${job.target.id}`;
|
|
70
70
|
}
|
|
71
71
|
))) {
|
|
72
72
|
console.log('Success: Every job has a correct ID');
|
|
@@ -117,21 +117,21 @@ const validate = async () => {
|
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
if (jobArrays.every(array => [0, 1].every(
|
|
120
|
-
jobIndex => array[jobIndex].
|
|
120
|
+
jobIndex => array[jobIndex].target.id === batch.targets[jobIndex].id
|
|
121
121
|
))) {
|
|
122
|
-
console.log('Success: Every job has a correct
|
|
122
|
+
console.log('Success: Every job has a correct target.id property');
|
|
123
123
|
}
|
|
124
124
|
else {
|
|
125
|
-
console.log('ERROR: A job does not have a correct
|
|
125
|
+
console.log('ERROR: A job does not have a correct target.id property');
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
if (jobArrays.every(array => [0, 1].every(
|
|
129
|
-
jobIndex => array[jobIndex].
|
|
129
|
+
jobIndex => array[jobIndex].target.what === batch.targets[jobIndex].what
|
|
130
130
|
))) {
|
|
131
|
-
console.log('Success: Every job has a correct
|
|
131
|
+
console.log('Success: Every job has a correct target.what property');
|
|
132
132
|
}
|
|
133
133
|
else {
|
|
134
|
-
console.log('ERROR: A job does not have a correct
|
|
134
|
+
console.log('ERROR: A job does not have a correct target.what property');
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
137
|
if (jobArrays.every(
|