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 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
- - `sources.script`: This preserves the ID of the script after the `id` property is replaced with a job ID.
258
- - `sources.sendReportTo`: This (if not `''`) is the URL to which a Testaro agent is to send its report after it performs a job derived from the script.
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
- script: 'ts99',
443
+ …,
439
444
  batch: 'departments',
440
445
  mergeID: '7f',
441
- sendReportTo: 'https://abccorp.com/api/report',
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 `sources.target.what` property).
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.sources
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
- sources.target.what = what;
123
- sources.target.url = url;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testilo",
3
- "version": "36.0.2",
3
+ "version": "37.0.1",
4
4
  "description": "Prepares Testaro jobs and processes Testaro reports",
5
5
  "main": "call.js",
6
6
  "scripts": {
@@ -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, sources, jobData, score} = report;
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, score} = report;
55
- const {script, target, requester} = sources;
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, script, target, requester} = sources;
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;
@@ -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.sources.target.what)))
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.sources.target.what,
33
+ target: report.target.what,
34
34
  score: report.score.total
35
35
  }));
36
36
  const entriesHTML = entries
@@ -29,6 +29,6 @@
29
29
 
30
30
  // Adds parameters to a query for a digest.
31
31
  exports.digester = (report, query) => {
32
- query.target = report.sources.target.what;
32
+ query.target = report.target.what;
33
33
  query.testCount = report.score.testCount;
34
34
  };
@@ -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.sources.target.id}`;
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].sources.target.id === batch.targets[jobIndex].id
120
+ jobIndex => array[jobIndex].target.id === batch.targets[jobIndex].id
121
121
  ))) {
122
- console.log('Success: Every job has a correct sources.target.id property');
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 sources.target.id property');
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].sources.target.what === batch.targets[jobIndex].what
129
+ jobIndex => array[jobIndex].target.what === batch.targets[jobIndex].what
130
130
  ))) {
131
- console.log('Success: Every job has a correct sources.target.what property');
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 sources.target.what property');
134
+ console.log('ERROR: A job does not have a correct target.what property');
135
135
  return;
136
136
  }
137
137
  if (jobArrays.every(