testaro 26.0.0 → 26.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/package.json +2 -2
  2. package/procs/nav.js +3 -1
  3. package/procs/operable.js +1 -1
  4. package/run.js +24 -3
  5. package/testaro/buttonMenu.js +54 -56
  6. package/testaro/hover.js +34 -8
  7. package/testaro/linkTo.js +2 -2
  8. package/validation/tests/jobs/allCaps.json +1 -5
  9. package/validation/tests/jobs/allHidden.json +8 -12
  10. package/validation/tests/jobs/allSlanted.json +1 -5
  11. package/validation/tests/jobs/attVal.json +2 -6
  12. package/validation/tests/jobs/autocomplete.json +2 -6
  13. package/validation/tests/jobs/bulk.json +2 -11
  14. package/validation/tests/jobs/buttonMenu.json +2 -6
  15. package/validation/tests/jobs/distortion.json +1 -5
  16. package/validation/tests/jobs/docType.json +2 -6
  17. package/validation/tests/jobs/dupAtt.json +2 -6
  18. package/validation/tests/jobs/elements.json +1 -5
  19. package/validation/tests/jobs/embAc.json +2 -6
  20. package/validation/tests/jobs/filter.json +2 -6
  21. package/validation/tests/jobs/focAll.json +3 -7
  22. package/validation/tests/jobs/focInd.json +22 -41
  23. package/validation/tests/jobs/focOp.json +16 -75
  24. package/validation/tests/jobs/focVis.json +1 -5
  25. package/validation/tests/jobs/headEl.json +1 -5
  26. package/validation/tests/jobs/headingAmb.json +1 -5
  27. package/validation/tests/jobs/hovInd.json +1 -5
  28. package/validation/tests/jobs/hover.json +29 -114
  29. package/validation/tests/jobs/hr.json +1 -5
  30. package/validation/tests/jobs/labClash.json +2 -6
  31. package/validation/tests/jobs/lineHeight.json +1 -5
  32. package/validation/tests/jobs/linkAmb.json +1 -5
  33. package/validation/tests/jobs/linkExt.json +1 -5
  34. package/validation/tests/jobs/linkTitle.json +1 -5
  35. package/validation/tests/jobs/linkTo.json +1 -5
  36. package/validation/tests/jobs/linkUl.json +3 -7
  37. package/validation/tests/jobs/miniText.json +1 -5
  38. package/validation/tests/jobs/motion.json +2 -6
  39. package/validation/tests/jobs/nonTable.json +1 -5
  40. package/validation/tests/jobs/pseudoP.json +1 -5
  41. package/validation/tests/jobs/radioSet.json +2 -6
  42. package/validation/tests/jobs/role.json +2 -6
  43. package/validation/tests/jobs/styleDiff.json +2 -6
  44. package/validation/tests/jobs/tabNav.json +2 -6
  45. package/validation/tests/jobs/targetSize.json +1 -5
  46. package/validation/tests/jobs/textNodes.json +1 -5
  47. package/validation/tests/jobs/title.json +2 -6
  48. package/validation/tests/jobs/titledEl.json +2 -6
  49. package/validation/tests/jobs/zIndex.json +2 -6
  50. package/validation/tests/targets/focInd/bad.html +8 -8
  51. package/validation/tests/targets/focInd/good.html +1 -1
  52. package/validation/tests/targets/focOp/bad.html +3 -4
  53. package/validation/tests/targets/hover/bad.html +15 -7
  54. package/validation/tests/targets/opFoc/bad.html +18 -0
  55. package/validation/tests/targets/opFoc/good.html +15 -0
  56. package/validation/validateTest.js +5 -4
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "26.0.0",
4
- "description": "Run 920 web accessibility tests from 9 tools and get a standardized report",
3
+ "version": "26.2.0",
4
+ "description": "Run 650 web accessibility tests from 8 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "tests": "node validation/executors/tests",
package/procs/nav.js CHANGED
@@ -39,8 +39,10 @@ let browser;
39
39
  const deSlash = string => string.endsWith('/') ? string.slice(0, -1) : string;
40
40
  // Visits a URL and returns the response of the server.
41
41
  const goTo = async (report, page, url, timeout, waitUntil) => {
42
+ // If the URL is a file path:
42
43
  if (url.startsWith('file://')) {
43
- url = url.replace('file://', `file://${__dirname}/`);
44
+ // Make it absolute.
45
+ url = url.replace('file://', `file://${__dirname.replace(/procs$/, '')}`);
44
46
  }
45
47
  // Visit the URL.
46
48
  const startTime = Date.now();
package/procs/operable.js CHANGED
@@ -63,7 +63,7 @@ exports.isOperable = async loc => {
63
63
  opHow.push('pointer cursor');
64
64
  }
65
65
  // If the element is clickable:
66
- if (el.onClick) {
66
+ if (el.onclick) {
67
67
  // Add this to the operabilities.
68
68
  opHow.push('click listener');
69
69
  }
package/run.js CHANGED
@@ -211,8 +211,20 @@ const isValidReport = report => {
211
211
  if (! ['chromium', 'webkit', 'firefox'].includes(acts[0].which)) {
212
212
  return 'Bad first act which';
213
213
  }
214
- if (! acts[0].url || typeof acts[0].url !== 'string' || ! isURL(acts[0].url)) {
215
- return 'First act url not a URL';
214
+ if (acts[0].type !== 'launch' || (
215
+ (
216
+ ! acts[0].url
217
+ || typeof acts[0].url !== 'string'
218
+ || ! isURL(acts[0].url)
219
+ )
220
+ && (
221
+ acts[1].type !== 'url'
222
+ || ! acts[1].which
223
+ || typeof acts[1].which !== 'string'
224
+ || ! isURL(acts[1].which)
225
+ )
226
+ )) {
227
+ return 'First or second act has no valid URL';
216
228
  }
217
229
  const invalidAct = acts.find(act => ! isValidAct(act));
218
230
  if (invalidAct) {
@@ -450,7 +462,16 @@ const doActs = async (report, actIndex, page) => {
450
462
  const act = acts[actIndex];
451
463
  // If it is valid:
452
464
  if (isValidAct(act)) {
453
- const whichSuffix = act.which ? ` (${act.which})` : '';
465
+ let actInfo = '';
466
+ if (act.which) {
467
+ if (act.type === 'launch' && act.url) {
468
+ actInfo = `${act.which} to ${act.url}`;
469
+ }
470
+ else {
471
+ actInfo = act.which;
472
+ }
473
+ }
474
+ const whichSuffix = actInfo ? ` (${actInfo})` : '';
454
475
  console.log(`>>>> ${act.type}${whichSuffix}`);
455
476
  // Increment the count of acts performed.
456
477
  actCount++;
@@ -27,68 +27,58 @@ const getAdjacentIndexWithWrap = (groupSize, startIndex, increment) => {
27
27
  return newIndex;
28
28
  };
29
29
  // Returns whether a key created the expected effective focus.
30
- const focusSuccess = async (miLocAll, priorIndex, key, isPseudo) => {
30
+ const focusSuccess = async (miLocsDir, priorIndex, key, isPseudo) => {
31
31
  // Initialize the result.
32
32
  const result = {
33
33
  isOK: false,
34
34
  newFocIndex: null
35
35
  };
36
- // Get the index of the effectively focused menu item.
37
- const focData = await miLocAll.evaluateAll((elements, isPseudo) => {
38
- // Get the currently focused element.
39
- let focEl = document.activeElement;
40
- // If the menu manages pseudofocus:
41
- let miFocIndex;
42
- if (isPseudo) {
43
- // Get the index of the effectively focused menu item.
44
- const pseudoFocID = focEl.getAttribute('aria-activedescendant');
45
- if (pseudoFocID) {
46
- miFocIndex = elements.map(element => element.id).indexOf(pseudoFocID);
36
+ // For each of the menu items directly descending from the menu:
37
+ for (const miLocDir of miLocsDir) {
38
+ // Get whether it is effectively focused.
39
+ const hasFocus = await miLocDir.evaluate((el, isPseudo) => {
40
+ if (isPseudo) {
41
+ const effectiveID = document.activeElement.getAttribute('aria-activeDescendant');
42
+ if (effectiveID) {
43
+ const effectiveEl = document.getElementById(effectiveID);
44
+ return effectiveEl === el;
45
+ }
46
+ else {
47
+ return false;
48
+ }
47
49
  }
48
- }
49
- // Otherwise, i.e. if the menu manages true focus:
50
- else {
51
- // Get the index of the focused menu item.
52
- miFocIndex = elements.indexOf(focEl);
53
- }
54
- // If an effectively focused menu item was identified:
55
- if (miFocIndex > -1) {
56
- // Return data on the menu items.
57
- return {
58
- count: elements.length,
59
- miFocIndex
60
- };
61
- }
62
- // Otherwise, i.e. if no effectively focused menu item was identified:
63
- else {
64
- // Return this.
65
- return null;
66
- }
67
- }, isPseudo);
68
- // If data on the menu items were obtained:
69
- if (focData) {
70
- // Get whether the effective focus is as expected and update the result.
71
- if (key === 'Home' && focData.miFocIndex === 0) {
72
- result.isOK = true;
73
- result.newFocIndex = 0;
74
- }
75
- else if (key === 'End' && focData.miFocIndex === focData.count - 1) {
76
- result.isOK = true;
77
- result.newFocIndex = focData.count - 1;
78
- }
79
- else if (['ArrowLeft', 'ArrowUp'].includes(key)) {
80
- const expectedIndex = getAdjacentIndexWithWrap(focData.count, priorIndex, -1);
81
- if (focData.miFocIndex === expectedIndex) {
50
+ else {
51
+ return document.activeElement === el;
52
+ }
53
+ }, isPseudo);
54
+ // If it is:
55
+ if (hasFocus) {
56
+ // Get whether the effective focus is as expected and update the result.
57
+ const miFocIndex = miLocsDir.indexOf(miLocDir);
58
+ const miCount = miLocsDir.length;
59
+ if (key === 'Home' && miFocIndex === 0) {
82
60
  result.isOK = true;
83
- result.newFocIndex = expectedIndex;
61
+ result.newFocIndex = 0;
84
62
  }
85
- }
86
- else if (['ArrowRight', 'ArrowDown'].includes(key)) {
87
- const expectedIndex = getAdjacentIndexWithWrap(focData.count, priorIndex, 1);
88
- if (focData.miFocIndex === expectedIndex) {
63
+ else if (key === 'End' && miFocIndex === miCount - 1) {
89
64
  result.isOK = true;
90
- result.newFocIndex = expectedIndex;
65
+ result.newFocIndex = miCount - 1;
91
66
  }
67
+ else if (['ArrowLeft', 'ArrowUp'].includes(key)) {
68
+ const expectedIndex = getAdjacentIndexWithWrap(miCount, priorIndex, -1);
69
+ if (miFocIndex === expectedIndex) {
70
+ result.isOK = true;
71
+ result.newFocIndex = expectedIndex;
72
+ }
73
+ }
74
+ else if (['ArrowRight', 'ArrowDown'].includes(key)) {
75
+ const expectedIndex = getAdjacentIndexWithWrap(miCount, priorIndex, 1);
76
+ if (miFocIndex === expectedIndex) {
77
+ result.isOK = true;
78
+ result.newFocIndex = expectedIndex;
79
+ }
80
+ }
81
+ break;
92
82
  }
93
83
  }
94
84
  // Return the result.
@@ -139,13 +129,21 @@ exports.reporter = async (page, withItems, trialKeySpecs = []) => {
139
129
  });
140
130
  // If they were obtained:
141
131
  if (extraData) {
142
- // Get locators for its direct menu items.
132
+ // Get locators for its descendant non-menu menu items.
143
133
  const miLocAll = menuLoc.locator(
144
- ':scope [role=menuitem]:not([role=menu] [role=menuitem]):not([role=menubar] [role=menuitem])'
134
+ '[role=menuitem]:not([role=menu]), [role=menuitem]:not([role=menubar])'
145
135
  );
136
+ // Get which of them are direct descendants.
137
+ const areDirect = await miLocAll.evaluateAll((els, menuID) => {
138
+ return els.map(el => {
139
+ const itsMenu = el.closest('[role=menu], [role=menubar]');
140
+ return itsMenu.id && itsMenu.id === menuID;
141
+ });
142
+ }, menuID);
146
143
  const miLocsAll = await miLocAll.all();
144
+ const miLocsDir = miLocsAll.filter((loc, index) => areDirect[index]);
147
145
  // If there are at least 2 of them:
148
- if (miLocsAll.length > 1) {
146
+ if (miLocsDir.length > 1) {
149
147
  // Ensure that the menu is collapsed.
150
148
  await menuLoc.evaluate(element => {
151
149
  element.setAttribute('aria-expanded', false);
@@ -193,7 +191,7 @@ exports.reporter = async (page, withItems, trialKeySpecs = []) => {
193
191
  // Press it.
194
192
  await page.keyboard.press(key);
195
193
  // Get whether the expected focus occurred.
196
- const focData = await focusSuccess(miLocAll, focIndex, key, extraData.isPseudo);
194
+ const focData = await focusSuccess(miLocsDir, focIndex, key, extraData.isPseudo);
197
195
  // If so:
198
196
  if (focData.isOK) {
199
197
  // Update the index of the effective focus.
package/testaro/hover.js CHANGED
@@ -1,10 +1,11 @@
1
1
  /*
2
2
  hover
3
3
  This test reports unexpected impacts of hovering. The elements that are subjected to hovering
4
- (called “triggers”) include all the elements that have aria-controls, aria-expanded,
5
- onmouseenter, or onmouseover' attributes and a sample of all visible elements in the body. If
6
- hovering over an element results in an increase or decrease in the total count of visible
7
- elements in the body, the rule is considered violated.
4
+ (called “triggers”) include all the elements that have ARIA attributes associated with control
5
+ over the visibility of other elements and all the elements that have onmouseenter or
6
+ onmouseover attributes, as well as a sample of all visible elements in the body. If hovering over
7
+ an element results in an increase or decrease in the total count of visible elements in the body,
8
+ the rule is considered violated.
8
9
  */
9
10
 
10
11
  // ########## IMPORTS
@@ -17,11 +18,29 @@ const {init, report} = require('../procs/testaro');
17
18
  // Runs the test and returns the result.
18
19
  exports.reporter = async (page, withItems) => {
19
20
  // Initialize the locators and result.
20
- const all = await init(
21
- page, 'body [aria-controls], body [aria-expanded], body [onmouseenter], body [onmouseover]'
21
+ const allTrigger = await init(
22
+ page, '[aria-controls], [aria-expanded], [aria-haspopup], [onmouseenter], [onmouseover]'
22
23
  );
23
- const miscAll = await init(page, 'body *:visible');
24
- all.allLocs.push(... miscAll.allLocs.slice(0, - all.allLocs.length));
24
+ const allNonTrigger = await init(
25
+ page,
26
+ 'body *:not([aria-controls]):not([aria-expanded]):not([aria-haspopup]):not([onmouseenter]):not([onmouseover])'
27
+ );
28
+ const populationSize
29
+ = allTrigger.result.data.populationSize + allNonTrigger.result.data.populationSize;
30
+ const sampleSize = allTrigger.result.data.sampleSize + allNonTrigger.result.data.sampleSize;
31
+ const all = {
32
+ allLocs: allTrigger.allLocs.concat(allNonTrigger.allLocs),
33
+ locs: [],
34
+ result: {
35
+ data: {
36
+ populationSize,
37
+ sampleSize,
38
+ populationRatio: sampleSize ? populationSize / sampleSize : null
39
+ },
40
+ totals: [0, 0, 0, 0],
41
+ standardInstances: []
42
+ }
43
+ };
25
44
  // For each locator:
26
45
  for (const loc of all.allLocs) {
27
46
  // Get how many elements are added or subtracted when the element is hovered over.
@@ -54,5 +73,12 @@ exports.reporter = async (page, withItems) => {
54
73
  'Hovering over the element __param__',
55
74
  'Hovering over elements adds elements to or subtracts elements from the page'
56
75
  ];
76
+ // Reload the page.
77
+ try {
78
+ await page.reload({timeout: 15000});
79
+ }
80
+ catch(error) {
81
+ console.log('ERROR: page reload timed out');
82
+ }
57
83
  return await report(withItems, all, 'hover', whats, 0);
58
84
  };
package/testaro/linkTo.js CHANGED
@@ -15,6 +15,6 @@ exports.reporter = async (page, withItems) => {
15
15
  const all = await init(page, 'a:not([href]):visible');
16
16
  all.locs = all.allLocs;
17
17
  // Populate and return the result.
18
- const whats = ['Link has no href attribute', 'inks are missing href attributes'];
19
- return await report(withItems, all, 'linkTo', whats, 2);
18
+ const whats = ['Link has no href attribute', 'Links are missing href attributes'];
19
+ return await report(withItems, all, 'linkTo', whats, 2, 'A');
20
20
  };
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/allCaps/index.html",
10
+ "url": "file://validation/tests/targets/allCaps/index.html",
15
11
  "what": "page with various letter cases"
16
12
  },
17
13
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/allHidden/good.html",
10
+ "url": "file://validation/tests/targets/allHidden/good.html",
15
11
  "what": "page with nothing hidden"
16
12
  },
17
13
  {
@@ -53,7 +49,7 @@
53
49
  },
54
50
  {
55
51
  "type": "url",
56
- "which": "__targets__/allHidden/noBody.html",
52
+ "which": "file://validation/tests/targets/allHidden/noBody.html",
57
53
  "what": "page with no body"
58
54
  },
59
55
  {
@@ -90,7 +86,7 @@
90
86
  },
91
87
  {
92
88
  "type": "url",
93
- "which": "__targets__/allHidden/noMain.html",
89
+ "which": "file://validation/tests/targets/allHidden/noMain.html",
94
90
  "what": "page with no main landmark"
95
91
  },
96
92
  {
@@ -128,7 +124,7 @@
128
124
  },
129
125
  {
130
126
  "type": "url",
131
- "which": "__targets__/allHidden/hiddenMain.html",
127
+ "which": "file://validation/tests/targets/allHidden/hiddenMain.html",
132
128
  "what": "page with a hidden main landmark"
133
129
  },
134
130
  {
@@ -171,7 +167,7 @@
171
167
  },
172
168
  {
173
169
  "type": "url",
174
- "which": "__targets__/allHidden/visHiddenMain.html",
170
+ "which": "file://validation/tests/targets/allHidden/visHiddenMain.html",
175
171
  "what": "page with a visually hidden main landmark"
176
172
  },
177
173
  {
@@ -209,7 +205,7 @@
209
205
  },
210
206
  {
211
207
  "type": "url",
212
- "which": "__targets__/allHidden/ariaHiddenBody.html",
208
+ "which": "file://validation/tests/targets/allHidden/ariaHiddenBody.html",
213
209
  "what": "page with an ARIA-hidden body"
214
210
  },
215
211
  {
@@ -242,7 +238,7 @@
242
238
  },
243
239
  {
244
240
  "type": "url",
245
- "which": "__targets__/allHidden/mixedHidden.html",
241
+ "which": "file://validation/tests/targets/allHidden/mixedHidden.html",
246
242
  "what": "page with mixed hidden states"
247
243
  },
248
244
  {
@@ -275,7 +271,7 @@
275
271
  },
276
272
  {
277
273
  "type": "url",
278
- "which": "__targets__/allHidden/noneDoc.html",
274
+ "which": "file://validation/tests/targets/allHidden/noneDoc.html",
279
275
  "what": "page with none as its display property"
280
276
  },
281
277
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/allSlanted/index.html",
10
+ "url": "file://validation/tests/targets/allSlanted/index.html",
15
11
  "what": "page with various slantednesses"
16
12
  },
17
13
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/attVal/good.html",
10
+ "url": "file://validation/tests/targets/attVal/good.html",
15
11
  "what": "page with permitted attribute values"
16
12
  },
17
13
  {
@@ -66,7 +62,7 @@
66
62
  },
67
63
  {
68
64
  "type": "url",
69
- "which": "__targets__/attVal/bad.html",
65
+ "which": "file://validation/tests/targets/attVal/bad.html",
70
66
  "what": "page with illicit attribute values"
71
67
  },
72
68
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/autocomplete/good.html",
10
+ "url": "file://validation/tests/targets/autocomplete/good.html",
15
11
  "what": "page with correct autocomplete attributes"
16
12
  },
17
13
  {
@@ -60,7 +56,7 @@
60
56
  },
61
57
  {
62
58
  "type": "url",
63
- "which": "__targets__/autocomplete/bad.html",
59
+ "which": "file://validation/tests/targets/autocomplete/bad.html",
64
60
  "what": "page with incorrect autocomplete attributes"
65
61
  },
66
62
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/bulk/good.html",
10
+ "url": "file://validation/tests/targets/bulk/good.html",
15
11
  "what": "small page"
16
12
  },
17
13
  {
@@ -38,7 +34,7 @@
38
34
  },
39
35
  {
40
36
  "type": "url",
41
- "which": "__targets__/bulk/bad.html",
37
+ "which": "file://validation/tests/targets/bulk/bad.html",
42
38
  "what": "large page"
43
39
  },
44
40
  {
@@ -75,11 +71,6 @@
75
71
  "standardResult.instances.0.ordinalSeverity",
76
72
  "=",
77
73
  0
78
- ],
79
- [
80
- "standardResult.instances.0.count",
81
- "=",
82
- 1
83
74
  ]
84
75
  ],
85
76
  "withItems": true,
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/buttonMenu/good.html",
10
+ "url": "file://validation/tests/targets/buttonMenu/good.html",
15
11
  "what": "page with standard menu navigation"
16
12
  },
17
13
  {
@@ -43,7 +39,7 @@
43
39
  },
44
40
  {
45
41
  "type": "url",
46
- "which": "__targets__/menuNav/bad.html",
42
+ "which": "file://validation/tests/targets/buttonMenu/bad.html",
47
43
  "what": "page with deviant menu navigation"
48
44
  },
49
45
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/distortion/index.html",
10
+ "url": "file://validation/tests/targets/distortion/index.html",
15
11
  "what": "page with distorted text"
16
12
  },
17
13
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/docType/good.html",
10
+ "url": "file://validation/tests/targets/docType/good.html",
15
11
  "what": "page with doctype"
16
12
  },
17
13
  {
@@ -38,7 +34,7 @@
38
34
  },
39
35
  {
40
36
  "type": "url",
41
- "which": "__targets__/docType/bad.html",
37
+ "which": "file://validation/tests/targets/docType/bad.html",
42
38
  "what": "page without doctype"
43
39
  },
44
40
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/dupAtt/good.html",
10
+ "url": "file://validation/tests/targets/dupAtt/good.html",
15
11
  "what": "page without duplicate attributes"
16
12
  },
17
13
  {
@@ -38,7 +34,7 @@
38
34
  },
39
35
  {
40
36
  "type": "url",
41
- "which": "__targets__/dupAtt/bad.html",
37
+ "which": "file://validation/tests/targets/dupAtt/bad.html",
42
38
  "what": "page with duplicate attributes"
43
39
  },
44
40
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/elements/index.html",
10
+ "url": "file://validation/tests/targets/elements/index.html",
15
11
  "what": "page with a shadow root"
16
12
  },
17
13
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/embAc/good.html",
10
+ "url": "file://validation/tests/targets/embAc/good.html",
15
11
  "what": "page without embedding in links or buttons"
16
12
  },
17
13
  {
@@ -38,7 +34,7 @@
38
34
  },
39
35
  {
40
36
  "type": "url",
41
- "which": "__targets__/embAc/bad.html",
37
+ "which": "file://validation/tests/targets/embAc/bad.html",
42
38
  "what": "page with embeddings in links and buttons"
43
39
  },
44
40
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/filter/good.html",
10
+ "url": "file://validation/tests/targets/filter/good.html",
15
11
  "what": "page with no filter styles"
16
12
  },
17
13
  {
@@ -38,7 +34,7 @@
38
34
  },
39
35
  {
40
36
  "type": "url",
41
- "which": "__targets__/filter/bad.html",
37
+ "which": "file://validation/tests/targets/filter/bad.html",
42
38
  "what": "page with filter styles"
43
39
  },
44
40
  {
@@ -7,11 +7,7 @@
7
7
  {
8
8
  "type": "launch",
9
9
  "which": "chromium",
10
- "what": "usual browser"
11
- },
12
- {
13
- "type": "url",
14
- "which": "__targets__/focAll/good.html",
10
+ "url": "file://validation/tests/targets/focAll/good.html",
15
11
  "what": "fully Tab-focusable page"
16
12
  },
17
13
  {
@@ -38,7 +34,7 @@
38
34
  },
39
35
  {
40
36
  "type": "url",
41
- "which": "__targets__/focAll/less.html",
37
+ "which": "file://validation/tests/targets/focAll/less.html",
42
38
  "what": "partly Tab-focusable page"
43
39
  },
44
40
  {
@@ -85,7 +81,7 @@
85
81
  },
86
82
  {
87
83
  "type": "url",
88
- "which": "__targets__/focAll/more.html",
84
+ "which": "file://validation/tests/targets/focAll/more.html",
89
85
  "what": "page with added Tab-focusability"
90
86
  },
91
87
  {