testaro 67.0.0 → 68.0.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 (95) hide show
  1. package/LICENSE +4 -16
  2. package/README.md +10 -2
  3. package/UPGRADES.md +1 -1
  4. package/dirWatch.js +2 -3
  5. package/ed11y/editoria11y.min.js +109 -690
  6. package/ed11y/editoria11y210.min.js +747 -0
  7. package/netWatch.js +6 -6
  8. package/package.json +1 -1
  9. package/procs/aslint.js +2 -2
  10. package/procs/catalog.js +190 -0
  11. package/procs/{dateOf.js → dateTime.js} +6 -4
  12. package/procs/doActs.js +1227 -0
  13. package/procs/doTestAct.js +63 -29
  14. package/procs/error.js +53 -0
  15. package/procs/job.js +64 -38
  16. package/procs/launch.js +596 -0
  17. package/procs/nu.js +3 -18
  18. package/procs/shoot.js +18 -2
  19. package/procs/testaro.js +102 -125
  20. package/procs/xPath.js +62 -0
  21. package/run.js +42 -1938
  22. package/scratch/README.md +9 -0
  23. package/testaro/adbID.js +3 -3
  24. package/testaro/allCaps.js +4 -5
  25. package/testaro/allHidden.js +19 -18
  26. package/testaro/allSlanted.js +4 -5
  27. package/testaro/altScheme.js +3 -3
  28. package/testaro/attVal.js +19 -35
  29. package/testaro/autocomplete.js +65 -62
  30. package/testaro/bulk.js +21 -20
  31. package/testaro/buttonMenu.js +112 -33
  32. package/testaro/captionLoc.js +3 -3
  33. package/testaro/datalistRef.js +4 -5
  34. package/testaro/distortion.js +3 -3
  35. package/testaro/docType.js +6 -9
  36. package/testaro/dupAtt.js +12 -25
  37. package/testaro/elements.js +4 -3
  38. package/testaro/embAc.js +4 -2
  39. package/testaro/focAll.js +6 -13
  40. package/testaro/focAndOp.js +3 -3
  41. package/testaro/focInd.js +3 -3
  42. package/testaro/focVis.js +4 -3
  43. package/testaro/headEl.js +5 -12
  44. package/testaro/headingAmb.js +45 -88
  45. package/testaro/hovInd.js +5 -5
  46. package/testaro/hover.js +44 -8
  47. package/testaro/hr.js +4 -4
  48. package/testaro/imageLink.js +3 -3
  49. package/testaro/labClash.js +3 -3
  50. package/testaro/legendLoc.js +3 -3
  51. package/testaro/lineHeight.js +3 -3
  52. package/testaro/linkAmb.js +25 -17
  53. package/testaro/linkExt.js +5 -5
  54. package/testaro/linkOldAtt.js +4 -3
  55. package/testaro/linkTo.js +4 -3
  56. package/testaro/linkUl.js +4 -5
  57. package/testaro/miniText.js +4 -3
  58. package/testaro/motion.js +3 -22
  59. package/testaro/nonTable.js +4 -5
  60. package/testaro/optRoleSel.js +3 -3
  61. package/testaro/phOnly.js +3 -3
  62. package/testaro/pseudoP.js +5 -5
  63. package/testaro/radioSet.js +4 -5
  64. package/testaro/role.js +4 -5
  65. package/testaro/secHeading.js +4 -5
  66. package/testaro/shoot0.js +3 -2
  67. package/testaro/shoot1.js +3 -2
  68. package/testaro/styleDiff.js +5 -12
  69. package/testaro/tabNav.js +30 -118
  70. package/testaro/targetSmall.js +30 -15
  71. package/testaro/textNodes.js +3 -1
  72. package/testaro/textSem.js +4 -5
  73. package/testaro/title.js +4 -2
  74. package/testaro/titledEl.js +3 -3
  75. package/testaro/zIndex.js +3 -3
  76. package/tests/alfa.js +28 -54
  77. package/tests/aslint.js +20 -53
  78. package/tests/axe.js +76 -13
  79. package/tests/ed11y.js +69 -141
  80. package/tests/htmlcs.js +69 -38
  81. package/tests/ibm.js +54 -9
  82. package/tests/nuVal.js +65 -12
  83. package/tests/nuVnu.js +76 -26
  84. package/tests/qualWeb.js +89 -44
  85. package/tests/testaro.js +288 -273
  86. package/tests/wave.js +142 -117
  87. package/tests/wax.js +61 -42
  88. package/procs/getLocatorData.js +0 -192
  89. package/procs/identify.js +0 -250
  90. package/procs/isInlineLink.js +0 -42
  91. package/procs/screenShot.js +0 -32
  92. package/procs/standardize.js +0 -524
  93. package/procs/target.js +0 -90
  94. package/procs/tellServer.js +0 -43
  95. package/scripts/dumpAlts.js +0 -28
@@ -1,524 +0,0 @@
1
- /*
2
- © 2023–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
- © 2025 Jonathan Robert Pool.
4
-
5
- Licensed under the MIT License. See LICENSE file at the project root or
6
- https://opensource.org/license/mit/ for details.
7
-
8
- SPDX-License-Identifier: MIT
9
- */
10
-
11
- /*
12
- standardize.js
13
- Converts test results to the standard format.
14
- */
15
-
16
- // IMPORTS
17
-
18
- const {cap} = require('./job');
19
-
20
- // FUNCTIONS
21
-
22
- // Returns whether an id attribute value is valid without character escaping.
23
- const isBadID = id => /[^-\w]|^\d|^--|^-\d/.test(id);
24
- // Returns a tag name and the value of an id attribute from a substring of HTML code.
25
- const getIdentifiers = exports.getIdentifiers = code => {
26
- // Normalize the code.
27
- code = code.replace(/\s+/g, ' ').replace(/\\"/g, '"');
28
- // Get the first start tag of an element, if any.
29
- const startTagData = code.match(/^.*?<([a-zA-][^>]*)/);
30
- // If there is any:
31
- if (startTagData) {
32
- // Get the tag name.
33
- const tagNameArray = startTagData[1].match(/^[A-Za-z0-9]+/);
34
- const tagName = tagNameArray ? tagNameArray[0].toUpperCase() : '';
35
- // Get the value of the id attribute, if any.
36
- const identifierData = startTagData[1].match(/ id="([^"]+)"/);
37
- const id = identifierData ? identifierData[1] : '';
38
- // Return the tag name and the value of the id attribute, if any.
39
- return [tagName, id];
40
- }
41
- return ['', ''];
42
- };
43
- // Converts issue instances at an axe certainty level.
44
- const doAxe = (result, standardResult, certainty) => {
45
- if (result.details && result.details[certainty]) {
46
- result.details[certainty].forEach(rule => {
47
- rule.nodes.forEach(node => {
48
- const whatSet = new Set([
49
- rule.help,
50
- ... node.any.map(anyItem => anyItem.message),
51
- ... node.all.map(allItem => allItem.message)
52
- ]);
53
- const severityWeights = {
54
- minor: 0,
55
- moderate: 0,
56
- serious: 1,
57
- critical: 1
58
- };
59
- const ordinalSeverity = severityWeights[node.impact] + (certainty === 'violations' ? 2 : 0);
60
- const identifiers = getIdentifiers(node.html);
61
- const instance = {
62
- ruleID: rule.id,
63
- what: Array.from(whatSet.values()).join('; '),
64
- ordinalSeverity,
65
- tagName: identifiers[0],
66
- id: identifiers[1],
67
- location: {
68
- doc: 'dom',
69
- type: 'selector',
70
- spec: node.target && node.target.length ? node.target[0] : ''
71
- },
72
- excerpt: cap(node.html),
73
- boxID: '',
74
- pathID: ''
75
- };
76
- standardResult.instances.push(instance);
77
- });
78
- });
79
- }
80
- };
81
- // Converts issue instances at an htmlcs severity level.
82
- const doHTMLCS = (result, standardResult, severity) => {
83
- if (result[severity]) {
84
- Object.keys(result[severity]).forEach(ruleID => {
85
- const ruleData = result[severity][ruleID];
86
- Object.keys(ruleData).forEach(what => {
87
- ruleData[what].forEach(item => {
88
- const {tagName, id, excerpt, notInDOM, boxID, pathID} = item;
89
- const instance = {
90
- ruleID,
91
- what,
92
- ordinalSeverity: ['Warning', '', '', 'Error'].indexOf(severity),
93
- tagName: tagName.toUpperCase(),
94
- id: isBadID(id.slice(1)) ? '' : id.slice(1),
95
- location: {
96
- doc: notInDOM ? 'notInDOM' : 'dom',
97
- type: '',
98
- spec: ''
99
- },
100
- excerpt: cap(excerpt),
101
- boxID,
102
- pathID
103
- };
104
- standardResult.instances.push(instance);
105
- });
106
- });
107
- });
108
- }
109
- };
110
- // Converts issue instances from a nuVal or nuVnu result.
111
- const doNu = (withSource, result, standardResult) => {
112
- const items = result && result.messages;
113
- // If there are any messages:
114
- if (items && items.length) {
115
- // For each one:
116
- items.forEach(item => {
117
- const {
118
- extract,
119
- firstColumn,
120
- lastColumn,
121
- lastLine,
122
- message,
123
- subType,
124
- type,
125
- elementLocation
126
- } = item;
127
- const identifiers = getIdentifiers(extract);
128
- if (! identifiers[0] && message) {
129
- const tagNameLCArray = message.match(
130
- /^Element ([^ ]+)|^An (img) element| (meta|script) element| element (script)| tag (script)/
131
- );
132
- if (tagNameLCArray && tagNameLCArray[1]) {
133
- identifiers[0] = tagNameLCArray[1].toUpperCase();
134
- }
135
- }
136
- let spec = '';
137
- const locationSegments = [lastLine, firstColumn, lastColumn];
138
- if (locationSegments.every(segment => typeof segment === 'number')) {
139
- spec = locationSegments.join(':');
140
- }
141
- const {notInDOM} = elementLocation;
142
- const instance = {
143
- ruleID: message,
144
- what: message,
145
- ordinalSeverity: -1,
146
- tagName: identifiers[0],
147
- id: identifiers[1],
148
- location: {
149
- doc: withSource ? 'source' : (notInDOM ? 'notInDOM' : 'dom'),
150
- type: 'code',
151
- spec
152
- },
153
- excerpt: cap(extract),
154
- boxID: elementLocation?.boxID || '',
155
- pathID: elementLocation?.pathID || ''
156
- };
157
- if (type === 'info' && subType === 'warning') {
158
- instance.ordinalSeverity = 0;
159
- }
160
- else if (type === 'error') {
161
- instance.ordinalSeverity = subType === 'fatal' ? 3 : 2;
162
- }
163
- standardResult.instances.push(instance);
164
- });
165
- }
166
- };
167
- // Converts issue instances from a nuVal result.
168
- const doNuVal = (withSource, result, standardResult) => {
169
- doNu(withSource, result, standardResult);
170
- };
171
- // Converts issue instances from a nuVnu result.
172
- const doNuVnu = (withSource, result, standardResult) => {
173
- doNu(withSource, result, standardResult);
174
- };
175
- // Converts instances of a qualWeb rule class.
176
- const doQualWeb = (result, standardResult, ruleClassName) => {
177
- if (result.modules && result.modules[ruleClassName]) {
178
- const ruleClass = result.modules[ruleClassName];
179
- const severities = {
180
- 'best-practices': {
181
- warning: 0,
182
- failed: 1
183
- },
184
- 'wcag-techniques': {
185
- warning: 0,
186
- failed: 2
187
- },
188
- 'act-rules': {
189
- warning: 1,
190
- failed: 3
191
- }
192
- };
193
- Object.keys(ruleClass.assertions).forEach(ruleID => {
194
- const ruleResult = ruleClass.assertions[ruleID];
195
- ruleResult.results.forEach(item => {
196
- item.elements.forEach(element => {
197
- const {htmlCode} = element;
198
- const identifiers = getIdentifiers(htmlCode);
199
- const instance = {
200
- ruleID,
201
- what: item.description,
202
- ordinalSeverity: severities[ruleClassName][item.verdict] || 0,
203
- tagName: identifiers[0],
204
- id: identifiers[1],
205
- location: {
206
- doc: 'dom',
207
- type: 'selector',
208
- spec: element.pointer
209
- },
210
- excerpt: cap(htmlCode),
211
- boxID: element.locationData?.boxID || '',
212
- pathID: element.locationData?.pathID || ''
213
- };
214
- standardResult.instances.push(instance);
215
- });
216
- });
217
- });
218
- }
219
- };
220
- // Converts instances of a wave rule category.
221
- const doWAVE = (result, standardResult, categoryName) => {
222
- // If results for the category are reported:
223
- if (result.categories && result.categories[categoryName]) {
224
- const category = result.categories[categoryName];
225
- const ordinalSeverity = categoryName === 'alert' ? 0 : 3;
226
- const {items} = category;
227
- // If any violations in the category are reported:
228
- if (items) {
229
- // For each rule violated:
230
- Object.keys(items).forEach(ruleID => {
231
- const item = items[ruleID];
232
- // For each violation:
233
- item.selectors.forEach(violationFacts => {
234
- let tagName = '';
235
- let id = '';
236
- const finalTerm = violationFacts[0].replace(/^.+\s/, '');
237
- // If the selector is an element ID:
238
- if (finalTerm.includes('#')) {
239
- const finalArray = finalTerm.split('#');
240
- // Use it to get the element tagname and ID
241
- tagName = finalArray[0].replace(/:.*/, '');
242
- id = isBadID(finalArray[1]) ? '' : finalArray[1];
243
- }
244
- // Otherwise, i.e. if the selector is not an element ID:
245
- else {
246
- // Get the element tagname from it.
247
- tagName = finalTerm.replace(/:.*/, '') || 'HTML';
248
- }
249
- const {wcag} = item;
250
- // Get a violation description suffix from the WCAG data of the rule.
251
- const wcagSuffix = wcag.length
252
- ? ` (${wcag.map(wcagItem => wcagItem.name).join('; ')})`
253
- : '';
254
- // Get a standard instance.
255
- const instance = {
256
- ruleID,
257
- what: `${item.description}${wcagSuffix}`,
258
- ordinalSeverity,
259
- tagName,
260
- id,
261
- location: {
262
- doc: 'dom',
263
- type: 'selector',
264
- spec: violationFacts[0] || 'html'
265
- },
266
- excerpt: violationFacts[1],
267
- boxID: '',
268
- pathID: ''
269
- };
270
- // Add it to the standard result.
271
- standardResult.instances.push(instance);
272
- });
273
- });
274
- }
275
- }
276
- };
277
- // Populates the initialized standard result of an act with the act data and result.
278
- const convert = (toolName, data, result, standardResult) => {
279
- // If the act data state that the act was prevented:
280
- if (data.prevented) {
281
- // Add that to the standard result and disregard tool-specific conversions.
282
- standardResult.prevented = true;
283
- }
284
- // alfa, aslint
285
- else if (['alfa', 'aslint'].includes(toolName) && result.standardResult) {
286
- // Move the results to standard locations.
287
- Object.assign(result, result.nativeResult);
288
- Object.assign(standardResult, result.standardResult);
289
- delete result.nativeResult;
290
- delete result.standardResult;
291
- }
292
- // axe
293
- else if (
294
- toolName === 'axe'
295
- && result
296
- && result.totals
297
- && (result.totals.rulesWarned || result.totals.rulesViolated)
298
- ) {
299
- doAxe(result, standardResult, 'incomplete');
300
- doAxe(result, standardResult, 'violations');
301
- }
302
- // ed11y
303
- else if (
304
- toolName === 'ed11y'
305
- && result
306
- && ['imageAlts', 'violations', 'errorCount', 'warningCount']
307
- .every(key => result[key] !== undefined)
308
- ) {
309
- // For each violation:
310
- result.violations.forEach(violation => {
311
- const {test, content, tagName, id, loc, excerpt, boxID, pathID} = violation;
312
- if (['test', 'content'].every(key => key)) {
313
- // Standardize the what property.
314
- let what = '';
315
- if (content.includes('<p>This')) {
316
- what = content.replace(/^.*?<p>(This.+?)<\/p> *<p>(.*?)<\/p>.*/, '$1 $2');
317
- }
318
- else {
319
- what = content.replace(/^.*?<p>(.+?)<\/p>.*/, '$1');
320
- }
321
- // Add a standard instance to the standard result.
322
- standardResult.instances.push({
323
- ruleID: test,
324
- what,
325
- ordinalSeverity: 0,
326
- tagName,
327
- id: isBadID(id) ? '' : id,
328
- location: {
329
- doc: 'dom',
330
- type: 'box',
331
- spec: loc
332
- },
333
- excerpt,
334
- boxID,
335
- pathID
336
- });
337
- }
338
- });
339
- }
340
- // htmlcs
341
- else if (toolName === 'htmlcs' && result) {
342
- doHTMLCS(result, standardResult, 'Warning');
343
- doHTMLCS(result, standardResult, 'Error');
344
- }
345
- // ibm
346
- else if (toolName === 'ibm' && result.totals) {
347
- if (result.items) {
348
- result.items.forEach(item => {
349
- const identifiers = getIdentifiers(item.snippet);
350
- if (! identifiers[0] && item.path && item.path.dom) {
351
- const tagNameArray = item.path.dom.match(/^.+\/([^/[]+)/s);
352
- if (tagNameArray && tagNameArray.length === 2) {
353
- identifiers[0] = tagNameArray[1].toUpperCase();
354
- }
355
- }
356
- const instance = {
357
- ruleID: item.ruleId,
358
- what: item.message,
359
- ordinalSeverity: ['', 'recommendation', '', 'violation'].indexOf(item.level),
360
- tagName: identifiers[0],
361
- id: identifiers[1],
362
- location: {
363
- doc: 'dom',
364
- type: 'xpath',
365
- spec: item.path.dom
366
- },
367
- excerpt: cap(item.snippet),
368
- boxID: '',
369
- pathID: ''
370
- };
371
- standardResult.instances.push(instance);
372
- });
373
- }
374
- }
375
- // nuVal
376
- else if (toolName === 'nuVal' && result) {
377
- doNuVal(data.withSource, result, standardResult);
378
- }
379
- // nuVnu
380
- else if (toolName === 'nuVnu' && result) {
381
- doNuVnu(data.withSource, result, standardResult);
382
- }
383
- // qualWeb
384
- else if (
385
- toolName === 'qualWeb'
386
- && result.modules
387
- && (
388
- result.modules['act-rules']
389
- || result.modules['wcag-techniques']
390
- || result.modules['best-practices']
391
- )
392
- ) {
393
- if (result.modules['act-rules']) {
394
- doQualWeb(result, standardResult, 'act-rules');
395
- }
396
- if (result.modules['wcag-techniques']) {
397
- doQualWeb(result, standardResult, 'wcag-techniques');
398
- }
399
- if (result.modules['best-practices']) {
400
- doQualWeb(result, standardResult, 'best-practices');
401
- }
402
- }
403
- // testaro
404
- else if (toolName === 'testaro') {
405
- // Initialize a record of instance totals by rule and severity.
406
- data.ruleTotals = {};
407
- // For each violated rule:
408
- const rules = result ? Object.keys(result) : [];
409
- rules.forEach(rule => {
410
- // Copy its instances to the standard result.
411
- const ruleResult = result[rule];
412
- ruleResult.standardInstances ??= [];
413
- standardResult.instances.push(... ruleResult.standardInstances);
414
- // Initialize a record of its sample-ratio-weighted totals.
415
- data.ruleTotals[rule] = [0, 0, 0, 0];
416
- // Add those totals to the record and to the standard result.
417
- ruleResult.totals ??= [0, 0, 0, 0];
418
- for (const index in ruleResult.totals) {
419
- const ruleTotal = ruleResult.totals[index];
420
- data.ruleTotals[rule][index] += ruleTotal;
421
- standardResult.totals[index] += ruleTotal;
422
- }
423
- });
424
- const preventionCount = result.preventions && result.preventions.length;
425
- if (preventionCount) {
426
- standardResult.instances.push({
427
- ruleID: 'testPrevention',
428
- what: 'Page prevented tests from being performed',
429
- ordinalSeverity: 3,
430
- count: preventionCount,
431
- tagName: '',
432
- id: '',
433
- location: '',
434
- excerpt: '',
435
- boxID: '',
436
- pathID: ''
437
- });
438
- }
439
- }
440
- // wave
441
- else if (
442
- toolName === 'wave'
443
- && result.categories
444
- && (
445
- result.categories.error
446
- || result.categories.contrast
447
- || result.categories.alert
448
- )
449
- ) {
450
- const {categories} = result;
451
- standardResult.totals = [0, 0, 0, 0];
452
- standardResult.totals[0] = categories.alert.count;
453
- standardResult.totals[3] = (categories.error.count || 0) + (categories.contrast.count || 0);
454
- ['error', 'contrast', 'alert'].forEach(categoryName => {
455
- doWAVE(result, standardResult, categoryName);
456
- });
457
- }
458
- // wax
459
- else if (toolName === 'wax' && result.violations && result.violations.length) {
460
- // For each violation:
461
- result.violations.forEach(violation => {
462
- // Get its standard instance properties.
463
- const element = violation.element.replace(/\s+/g, ' ');
464
- const {boxID, description, message, notInDOM, pathID, severity} = violation;
465
- const ordinalSeverity = ['Minor', 'Moderate', '', 'Severe'].indexOf(severity);
466
- const tagNameCandidate = element.replace(/^<| .*$/g, '');
467
- const tagName = /^[a-zA-Z0-9]+$/.test(tagNameCandidate) ? tagNameCandidate.toUpperCase() : '';
468
- let id = '';
469
- const location = {};
470
- if (notInDOM) {
471
- location.doc = 'notInDOM';
472
- location.type = '';
473
- location.spec = '';
474
- }
475
- else if (tagName) {
476
- const idTerm = element
477
- .replace(/>.*$/, '')
478
- .split(' ')
479
- .slice(1)
480
- .find(term => term.startsWith('id="'));
481
- if (idTerm) {
482
- const idCandidate = idTerm.slice(4, -1);
483
- if (! idCandidate.includes('"')) {
484
- id = idCandidate;
485
- location.doc = 'dom';
486
- location.type = 'selector';
487
- location.spec = `#${id}`;
488
- }
489
- }
490
- }
491
- const instance = {
492
- ruleID: message,
493
- what: description,
494
- ordinalSeverity,
495
- tagName,
496
- id,
497
- location,
498
- excerpt: element,
499
- boxID,
500
- pathID
501
- };
502
- // Add the instance to the standard result.
503
- standardResult.instances.push(instance);
504
- });
505
- }
506
- // Populate the totals of the standard result if the tool is not Alfa, Testaro or WAVE.
507
- if (! ['alfa', 'testaro', 'wave'].includes(toolName)) {
508
- standardResult.instances.forEach(instance => {
509
- standardResult.totals[instance.ordinalSeverity] += instance.count || 1;
510
- });
511
- }
512
- // Round the totals of the standard result.
513
- standardResult.totals = standardResult.totals.map(total => Math.round(total));
514
- };
515
- // Populates the initialized standard result of an act.
516
- exports.standardize = act => {
517
- const {which, data, result, standardResult} = act;
518
- if (which && result && standardResult) {
519
- convert(which, data, result, standardResult);
520
- }
521
- else {
522
- console.log(`ERROR: Result of incomplete ${which || 'unknown'} act cannot be standardized`);
523
- }
524
- };
package/procs/target.js DELETED
@@ -1,90 +0,0 @@
1
- /*
2
- © 2023–2025 CVS Health and/or one of its affiliates. All rights reserved.
3
- © 2025 Jonathan Robert Pool.
4
-
5
- Licensed under the MIT License. See LICENSE file at the project root or
6
- https://opensource.org/license/mit/ for details.
7
-
8
- SPDX-License-Identifier: MIT
9
- */
10
-
11
- /*
12
- target
13
- Utilities for Testaro targetSmall and targetTiny tests.
14
- */
15
-
16
- // ########## IMPORTS
17
-
18
- // Module to classify links.
19
- const {isInlineLink} = require('./isInlineLink');
20
-
21
- // ########## FUNCTIONS
22
-
23
- // Returns data about a target if it is displayed and illicitly small.
24
- exports.isTooSmall = async (loc, min) => {
25
- let sizeData = null;
26
- // If the target is not an inline link:
27
- if (!(await isInlineLink(loc))) {
28
- // Get data on it if it is too small.
29
- sizeData = await loc.evaluate((el, min) => {
30
- // Get its styles.
31
- const styleDec = window.getComputedStyle(el);
32
- const displayStyle = styleDec.display;
33
- // If it is hidden (which should be impossible because of the selector):
34
- if (displayStyle === 'none') {
35
- // Exempt it.
36
- return null;
37
- }
38
- // Otherwise, i.e. if it is displayed:
39
- else {
40
- // Gets the width and height of an element.
41
- const getDims = el => {
42
- const rect = el.getBoundingClientRect();
43
- const widthR = rect && rect.width || 0;
44
- const heightR = rect && rect.height || 0;
45
- const widthP = el.offsetWidth || 0;
46
- const width = Math.max(widthP, Math.round(widthR));
47
- const heightP = el.offsetHeight || 0;
48
- const height = Math.max(heightP, Math.round(heightR));
49
- return [width, height];
50
- };
51
- const tagName = el.tagName;
52
- // Get the width and height of the target.
53
- const elDims = getDims(el);
54
- // If either dimension is too small:
55
- if (elDims.some(dim => dim < min)) {
56
- // Get the parent element of the target.
57
- const elParent = el.parentElement;
58
- // If the parent element exists:
59
- if (elParent) {
60
- // Get the child elements of the parent, including the target.
61
- const elGeneration = Array.from(elParent.children);
62
- // If the target has no siblings of its type:
63
- if (elGeneration.filter(peer => peer.tagName === tagName).length === 1) {
64
- // Get the width and height of the parent.
65
- const parentDims = getDims(elParent);
66
- // For each dimension of the target:
67
- elDims.forEach((elDim, index) => {
68
- // If it is too small and smaller than that of the parent:
69
- if (elDim < min && parentDims[index] > elDim) {
70
- // Replace it with the dimension of the parent (a substitute for distance).
71
- elDims[index] = parentDims[index];
72
- }
73
- });
74
- }
75
- }
76
- // Otherwise, i.e. if it does not exist:
77
- else {
78
- console.log(`WARNING: Target ${tagName} (${el.innerHTML}) has no parent element`);
79
- }
80
- }
81
- // Get whether it is too small.
82
- const isSmall = elDims.some(dim => dim < min);
83
- // Get its data if too small or its compliant status.
84
- return isSmall ? {tagName, width: elDims[0], height: elDims[1]} : null;
85
- }
86
- }, min);
87
- }
88
- // Return data about the target or its compliant status.
89
- return sizeData;
90
- };
@@ -1,43 +0,0 @@
1
- /*
2
- © 2023–2024 CVS Health and/or one of its affiliates. All rights reserved.
3
-
4
- Licensed under the MIT License. See LICENSE file at the project root or
5
- https://opensource.org/license/mit/ for details.
6
-
7
- SPDX-License-Identifier: MIT
8
- */
9
-
10
- /*
11
- tellServer
12
- Send a notice to an observer.
13
- */
14
-
15
- // CONSTANTS
16
-
17
- const httpClient = require('http');
18
- const httpsClient = require('https');
19
- const agent = process.env.AGENT;
20
-
21
- // FUNCTIONS
22
-
23
- // Sends a notice to an observer.
24
- exports.tellServer = (report, messageParams, logMessage) => {
25
- const {serverID} = report.sources;
26
- const observerURL = typeof serverID === 'number'
27
- ? process.env[`NETWATCH_URL_${serverID}_OBSERVE`]
28
- : '';
29
- if (observerURL) {
30
- const whoParams = `agent=${agent}&jobID=${report.id || ''}`;
31
- const wholeURL = `${observerURL}?${whoParams}&${messageParams}`;
32
- const client = wholeURL.startsWith('https://') ? httpsClient : httpClient;
33
- client.request(wholeURL)
34
- // If the notification threw an error:
35
- .on('error', error => {
36
- // Report the error.
37
- const errorMessage = 'ERROR notifying the server';
38
- console.log(`${errorMessage} (${error.message})`);
39
- })
40
- .end();
41
- console.log(`${logMessage} (server notified)`);
42
- }
43
- };
@@ -1,28 +0,0 @@
1
- /*
2
- © 2025 CVS Health and/or one of its affiliates. All rights reserved.
3
- © 2025 Jonathan Robert Pool.
4
-
5
- Licensed under the MIT License. See LICENSE file at the project root or
6
- https://opensource.org/license/mit/ for details.
7
-
8
- SPDX-License-Identifier: MIT
9
- */
10
-
11
- const { chromium } = require('playwright');
12
- const path = require('path');
13
-
14
- (async () => {
15
- const browser = await chromium.launch();
16
- const page = await browser.newPage();
17
- const target = `file://${path.resolve(__dirname, '../validation/tests/targets/altScheme/index.html')}`;
18
- console.log('Opening', target);
19
- await page.goto(target, { waitUntil: 'domcontentloaded' });
20
- const images = await page.$$eval('img', imgs => imgs.map(img => ({
21
- id: img.id || null,
22
- alt: img.getAttribute('alt'),
23
- src: img.getAttribute('src'),
24
- href: img.getAttribute('href')
25
- })));
26
- console.log(JSON.stringify(images, null, 2));
27
- await browser.close();
28
- })();