testaro 60.16.2 → 60.18.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.
package/tests/testaro.js CHANGED
@@ -15,12 +15,8 @@
15
15
 
16
16
  // IMPORTS
17
17
 
18
- // Module to perform common operations.
19
- const {init, getRuleResult} = require('../procs/testaro');
20
18
  // Function to launch a browser.
21
19
  const {launch} = require('../run');
22
- // Module to handle files.
23
- const fs = require('fs/promises');
24
20
 
25
21
  // CONSTANTS
26
22
 
@@ -44,7 +40,7 @@ const allRules = [
44
40
  id: 'allCaps',
45
41
  what: 'leaf elements with entirely upper-case text longer than 7 characters',
46
42
  launchRole: 'sharer',
47
- timeOut: 10,
43
+ timeOut: 5,
48
44
  defaultOn: true
49
45
  },
50
46
  {
@@ -114,14 +110,14 @@ const allRules = [
114
110
  id: 'distortion',
115
111
  what: 'distorted text',
116
112
  launchRole: 'sharer',
117
- timeOut: 10,
113
+ timeOut: 5,
118
114
  defaultOn: true
119
115
  },
120
116
  {
121
117
  id: 'docType',
122
118
  what: 'document without a doctype property',
123
119
  launchRole: 'sharer',
124
- timeOut: 10,
120
+ timeOut: 5,
125
121
  defaultOn: true
126
122
  },
127
123
  {
@@ -170,7 +166,7 @@ const allRules = [
170
166
  id: 'labClash',
171
167
  what: 'labeling inconsistencies',
172
168
  launchRole: 'sharer',
173
- timeOut: 10,
169
+ timeOut: 5,
174
170
  defaultOn: true
175
171
  },
176
172
  {
@@ -184,14 +180,14 @@ const allRules = [
184
180
  id: 'lineHeight',
185
181
  what: 'text with a line height less than 1.5 times its font size',
186
182
  launchRole: 'sharer',
187
- timeOut: 10,
183
+ timeOut: 5,
188
184
  defaultOn: true
189
185
  },
190
186
  {
191
187
  id: 'linkAmb',
192
188
  what: 'links with identical texts but different destinations',
193
189
  launchRole: 'sharer',
194
- timeOut: 50,
190
+ timeOut: 20,
195
191
  defaultOn: true
196
192
  },
197
193
  {
@@ -208,13 +204,6 @@ const allRules = [
208
204
  timeOut: 5,
209
205
  defaultOn: true
210
206
  },
211
- {
212
- id: 'linkTitle',
213
- what: 'links with title attributes repeating text content',
214
- launchRole: 'sharer',
215
- timeOut: 10,
216
- defaultOn: true
217
- },
218
207
  {
219
208
  id: 'linkTo',
220
209
  what: 'links without destinations',
@@ -226,7 +215,7 @@ const allRules = [
226
215
  id: 'linkUl',
227
216
  what: 'missing underlines on inline links',
228
217
  launchRole: 'sharer',
229
- timeOut: 10,
218
+ timeOut: 5,
230
219
  defaultOn: true
231
220
  },
232
221
  {
@@ -275,7 +264,7 @@ const allRules = [
275
264
  id: 'role',
276
265
  what: 'native-replacing explicit roles',
277
266
  launchRole: 'sharer',
278
- timeOut: 5,
267
+ timeOut: 20,
279
268
  defaultOn: true
280
269
  },
281
270
  {
@@ -303,7 +292,7 @@ const allRules = [
303
292
  id: 'textSem',
304
293
  what: 'semantically vague elements i, b, and/or small',
305
294
  launchRole: 'sharer',
306
- timeOut: 10,
295
+ timeOut: 5,
307
296
  defaultOn: true
308
297
  },
309
298
  {
@@ -387,7 +376,7 @@ const allRules = [
387
376
  id: 'hover',
388
377
  what: 'hover-caused content changes',
389
378
  launchRole: 'waster',
390
- timeOut: 300,
379
+ timeOut: 20,
391
380
  defaultOn: true
392
381
  },
393
382
  {
@@ -428,24 +417,6 @@ process.on('unhandledRejection', reason => {
428
417
 
429
418
  // FUNCTIONS
430
419
 
431
- // Conducts a JSON-defined test.
432
- const jsonTest = async (ruleID, ruleArgs) => {
433
- const [page, withItems] = ruleArgs;
434
- // Get the rule definition.
435
- const ruleJSON = await fs.readFile(`${__dirname}/../testaro/${ruleID}.json`, 'utf8');
436
- const ruleObj = JSON.parse(ruleJSON);
437
- // Initialize the locators and result.
438
- const all = await init(100, page, ruleObj.selector);
439
- all.locs = all.allLocs;
440
- // Populate and return the result.
441
- const whats = [
442
- ruleObj.complaints.instance,
443
- ruleObj.complaints.summary
444
- ];
445
- return await getRuleResult(
446
- withItems, all, ruleObj.ruleID, whats, ruleObj.ordinalSeverity, ruleObj.summaryTagName
447
- );
448
- };
449
420
  // Waits.
450
421
  const wait = ms => {
451
422
  return new Promise(resolve => {
@@ -547,158 +518,136 @@ exports.reporter = async (page, report, actIndex) => {
547
518
  };
548
519
  browser.on('disconnected', disconnectHandler);
549
520
  }
550
- // Initialize an argument array for reporter or jsonTest.
521
+ // Initialize an argument array for the reporter.
551
522
  const ruleArgs = [page, withItems];
552
- const ruleFileNames = await fs.readdir(`${__dirname}/../testaro`);
553
- const isJS = ruleFileNames.includes(`${ruleID}.js`);
554
- const isJSON = ruleFileNames.includes(`${ruleID}.json`);
555
- // If the rule is defined with JavaScript or JSON but not both:
556
- if ((isJS || isJSON) && ! (isJS && isJSON)) {
557
- // If with JavaScript and it has extra arguments:
558
- if (isJS && argRules && argRules.includes(ruleID)) {
559
- // Add them to the argument array.
560
- ruleArgs.push(... args[ruleID]);
561
- }
562
- result[ruleID] ??= {};
563
- const ruleResult = result[ruleID];
564
- const {what} = rule;
565
- ruleResult.what = what || '';
566
- const startTime = Date.now();
567
- let timeout;
568
- let testRetries = 2;
569
- let testSuccess = false;
570
- while (testRetries > 0 && ! testSuccess) {
571
- try {
572
- // Apply a time limit to the test.
573
- const timeLimit = 1000 * timeoutMultiplier * rule.timeOut;
574
- // If the time limit expires during the test:
575
- const timer = new Promise(resolve => {
576
- timeout = setTimeout(() => {
577
- // Add data about the test, including its prevention, to the result.
578
- const endTime = Date.now();
579
- testTimes.push([rule, Math.round((endTime - startTime) / 1000)]);
580
- data.rulePreventions.push(ruleID);
581
- data.rulePreventionMessages[ruleID] = 'Timeout';
582
- ruleResult.totals = [0, 0, 0, 0];
583
- ruleResult.standardInstances = [];
584
- console.log(`ERROR: Test of testaro rule ${ruleID} timed out`);
585
- resolve({timedOut: true});
586
- }, timeLimit);
587
- });
588
- // Perform the test, subject to the time limit.
589
- const ruleReport = isJS
590
- ? require(`../testaro/${ruleID}`).reporter(... ruleArgs)
591
- : jsonTest(ruleID, ruleArgs);
592
- // Get the test result or a timeout result.
593
- const ruleOrTimeoutReport = await Promise.race([timer, ruleReport]);
594
- // If the test was completed:
595
- if (! ruleOrTimeoutReport.timedOut) {
596
- // Add data from the test to the result.
523
+ // If the rule has extra arguments:
524
+ if (argRules && argRules.includes(ruleID)) {
525
+ // Add them to the argument array.
526
+ ruleArgs.push(... args[ruleID]);
527
+ }
528
+ result[ruleID] ??= {};
529
+ const ruleResult = result[ruleID];
530
+ const {what} = rule;
531
+ ruleResult.what = what || '';
532
+ const startTime = Date.now();
533
+ let timeout;
534
+ let testRetries = 2;
535
+ let testSuccess = false;
536
+ // Until all permitted retries are exhausted or the test succeeds:
537
+ while (testRetries > 0 && ! testSuccess) {
538
+ try {
539
+ // Apply a time limit to the test.
540
+ const timeLimit = 1000 * timeoutMultiplier * rule.timeOut;
541
+ // If the time limit expires during the test:
542
+ const timer = new Promise(resolve => {
543
+ timeout = setTimeout(() => {
544
+ // Add data about the test, including its prevention, to the result.
597
545
  const endTime = Date.now();
598
- testTimes.push([ruleID, Math.round((endTime - startTime) / 1000)]);
599
- Object.keys(ruleOrTimeoutReport).forEach(key => {
600
- ruleResult[key] = ruleOrTimeoutReport[key];
601
- });
602
- // If the test was prevented:
603
- if (ruleResult.data?.prevented && ruleResult.data.error) {
604
- // Add this to the result.
605
- data.rulePreventions.push(ruleID);
606
- data.rulePreventionMessages[ruleID] = ruleResult.data.error;
607
- }
608
- // If the result includes totals:
609
- if (ruleResult.totals) {
610
- // Round them.
611
- ruleResult.totals = ruleResult.totals.map(total => Math.round(total));
612
- }
613
- // Prevent a retry of the test.
614
- testSuccess = true;
615
- // If testing is to stop after a failure and the page failed the test:
616
- if (stopOnFail && ruleResult.totals && ruleResult.totals.some(total => total)) {
617
- // Stop testing.
618
- break;
619
- }
620
- }
621
- // Otherwise, i.e. if the test timed out:
622
- else {
623
- // Report this.
546
+ testTimes.push([rule, Math.round((endTime - startTime) / 1000)]);
624
547
  data.rulePreventions.push(ruleID);
625
548
  data.rulePreventionMessages[ruleID] = 'Timeout';
626
- // Stop retrying the test.
549
+ ruleResult.totals = [0, 0, 0, 0];
550
+ ruleResult.standardInstances = [];
551
+ console.log(`ERROR: Test of testaro rule ${ruleID} timed out`);
552
+ resolve({timedOut: true});
553
+ }, timeLimit);
554
+ });
555
+ // Perform the test, subject to the time limit.
556
+ const ruleReport = require(`../testaro/${ruleID}`).reporter(... ruleArgs);
557
+ // Get the test result or a timeout result.
558
+ const ruleOrTimeoutReport = await Promise.race([timer, ruleReport]);
559
+ // If the test was completed:
560
+ if (! ruleOrTimeoutReport.timedOut) {
561
+ // Add data from the test to the result.
562
+ const endTime = Date.now();
563
+ testTimes.push([ruleID, Math.round((endTime - startTime) / 1000)]);
564
+ Object.keys(ruleOrTimeoutReport).forEach(key => {
565
+ ruleResult[key] = ruleOrTimeoutReport[key];
566
+ });
567
+ // If the test was prevented:
568
+ if (ruleResult.data?.prevented && ruleResult.data.error) {
569
+ // Add this to the result.
570
+ data.rulePreventions.push(ruleID);
571
+ data.rulePreventionMessages[ruleID] = ruleResult.data.error;
572
+ }
573
+ // If the result includes totals:
574
+ if (ruleResult.totals) {
575
+ // Round them.
576
+ ruleResult.totals = ruleResult.totals.map(total => Math.round(total));
577
+ }
578
+ // Prevent a retry of the test.
579
+ testSuccess = true;
580
+ // If testing is to stop after a failure and the page failed the test:
581
+ if (stopOnFail && ruleResult.totals && ruleResult.totals.some(total => total)) {
582
+ // Stop testing.
627
583
  break;
628
584
  }
629
585
  }
630
- // If an error is thrown by the test:
631
- catch(error) {
632
- const isPageClosed = ['closed', 'Protocol error', 'Target page'].some(phrase =>
633
- error.message.includes(phrase)
586
+ // Otherwise, i.e. if the test timed out:
587
+ else {
588
+ // Report this.
589
+ data.rulePreventions.push(ruleID);
590
+ data.rulePreventionMessages[ruleID] = 'Timeout';
591
+ // Stop retrying the test.
592
+ break;
593
+ }
594
+ }
595
+ // If an error is thrown by the test:
596
+ catch(error) {
597
+ const isPageClosed = ['closed', 'Protocol error', 'Target page'].some(phrase =>
598
+ error.message.includes(phrase)
599
+ );
600
+ // If the page has closed and there are retries left:
601
+ if (isPageClosed && testRetries) {
602
+ // Report this and decrement the allowed retry count.
603
+ console.log(
604
+ `WARNING: Retry ${3 - testRetries--} of test ${ruleID} starting after page closed`
634
605
  );
635
- // If the page has closed and there are retries left:
636
- if (isPageClosed && testRetries) {
637
- // Report this and decrement the allowed retry count.
638
- console.log(
639
- `WARNING: Retry ${3 - testRetries--} of test ${ruleID} starting after page closed`
640
- );
641
- await wait(2000);
642
- // Replace the browser and the page in the run module and navigate to the target.
643
- await launch(
644
- report,
645
- actIndex,
646
- headEmulation,
647
- report.browserID,
648
- url
649
- );
650
- page = require('../run').page;
651
- // If the page replacement failed:
652
- if (! page) {
653
- // Report this.
654
- console.log(`ERROR: Browser relaunch to retry test ${ruleID} failed`);
655
- data.rulePreventions.push(ruleID);
656
- data.rulePreventionMessages[ruleID] = 'Retry failure due to browser relaunch failure';
657
- // Stop retrying the test.
658
- break;
659
- }
660
- // Update the rule arguments with the current page.
661
- ruleArgs[0] = page;
662
- }
663
- // Otherwise, i.e. if the page is open or it is closed but no retries are left:
664
- else {
665
- // Treat the test as prevented.
606
+ await wait(2000);
607
+ // Replace the browser and the page in the run module and navigate to the target.
608
+ await launch(
609
+ report,
610
+ actIndex,
611
+ headEmulation,
612
+ report.browserID,
613
+ url
614
+ );
615
+ page = require('../run').page;
616
+ // If the page replacement failed:
617
+ if (! page) {
618
+ // Report this.
619
+ console.log(`ERROR: Browser relaunch to retry test ${ruleID} failed`);
666
620
  data.rulePreventions.push(ruleID);
667
- data.rulePreventionMessages[ruleID] = error.message;
668
- console.log(`ERROR: Test of testaro rule ${ruleID} prevented (${error.message})`);
669
- // Do not retry the test even if retries are left.
621
+ data.rulePreventionMessages[ruleID] = 'Retry failure due to browser relaunch failure';
622
+ // Stop retrying the test.
670
623
  break;
671
624
  }
625
+ // Update the rule arguments with the current page.
626
+ ruleArgs[0] = page;
672
627
  }
673
- finally {
674
- // Clear the timeout.
675
- clearTimeout(timeout);
628
+ // Otherwise, i.e. if the page is open or it is closed but no retries are left:
629
+ else {
630
+ // Treat the test as prevented.
631
+ data.rulePreventions.push(ruleID);
632
+ data.rulePreventionMessages[ruleID] = error.message;
633
+ console.log(`ERROR: Test of testaro rule ${ruleID} prevented (${error.message})`);
634
+ // Do not retry the test even if retries are left.
635
+ break;
676
636
  }
677
637
  }
678
- // Clear the error listeners.
679
- if (page && ! page.isClosed() && crashHandler) {
680
- page.off('crash', crashHandler);
681
- crashHandler = null;
682
- }
683
- if (browser && disconnectHandler) {
684
- browser.off('disconnected', disconnectHandler);
685
- disconnectHandler = null;
638
+ finally {
639
+ // Clear the timeout.
640
+ clearTimeout(timeout);
686
641
  }
687
642
  }
688
- // Otherwise, i.e. if the rule is undefined or doubly defined:
689
- else {
690
- // Report this.
691
- data.rulesInvalid.push(rule);
692
- console.log(`ERROR: Rule ${rule.id} not validly defined`);
693
- // Clear the crash listener.
694
- if (page && ! page.isClosed() && crashHandler) {
695
- page.off('crash', crashHandler);
696
- crashHandler = null;
697
- }
698
- if (browser && disconnectHandler) {
699
- browser.off('disconnected', disconnectHandler);
700
- disconnectHandler = null;
701
- }
643
+ // Clear the error listeners.
644
+ if (page && ! page.isClosed() && crashHandler) {
645
+ page.off('crash', crashHandler);
646
+ crashHandler = null;
647
+ }
648
+ if (browser && disconnectHandler) {
649
+ browser.off('disconnected', disconnectHandler);
650
+ disconnectHandler = null;
702
651
  }
703
652
  // Force a garbage collection.
704
653
  try {
package/data/template.js DELETED
@@ -1,39 +0,0 @@
1
- /*
2
- © 2023 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
- template
12
- This test reports ….
13
- */
14
-
15
- // ########## IMPORTS
16
-
17
- // Module to perform common operations.
18
- const {init, report} = require('../procs/testaro');
19
-
20
- // ########## FUNCTIONS
21
-
22
- // Runs the test and returns the result.
23
- exports.reporter = async (page, withItems) => {
24
- // Initialize the locators and result.
25
- const all = await init(100, page, 'body a');
26
- // For each locator:
27
- for (const loc of all.allLocs) {
28
- // Get whether its element violates the rule.
29
- const isBad = await loc.evaluate(el => el.tabIndex !== 0);
30
- // If it does:
31
- if (isBad) {
32
- // Add the locator to the array of violators.
33
- all.locs.push(loc);
34
- }
35
- }
36
- // Populate and return the result.
37
- const whats = ['Itemized description', 'Summary description'];
38
- return await report(withItems, all, 'ruleID', whats, 0);
39
- };
package/testaro/hr.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "ruleID": "hr",
3
- "selector": "body hr",
4
- "complaints": {
5
- "instance": "Element instead of styling is used for vertical segmentation",
6
- "summary": "Elements instead of styling are used for vertical segmentation"
7
- },
8
- "ordinalSeverity": 0,
9
- "summaryTagName": "HR"
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "ruleID": "linkExt",
3
- "selector": "a[target=_blank]",
4
- "complaints": {
5
- "instance": "Link has a target=_blank attribute",
6
- "summary": "Links have target=_blank attributes"
7
- },
8
- "ordinalSeverity": 0,
9
- "summaryTagName": "A"
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "ruleID": "linkOldAtt",
3
- "selector": "a[charset], a[coords], a[name], a[rev], a[shape]",
4
- "complaints": {
5
- "instance": "Element has a deprecated attribute",
6
- "summary": "Links have deprecated attributes"
7
- },
8
- "ordinalSeverity": 1,
9
- "summaryTagName": "A"
10
- }
@@ -1,46 +0,0 @@
1
- /*
2
- © 2023 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
- linkTitle
13
- Related to Tenon rule 79.
14
- This test reports links with title attributes whose values the link text contains.
15
- */
16
-
17
- // ########## IMPORTS
18
-
19
- // Module to perform common operations.
20
- const {simplify} = require('../procs/testaro');
21
- // Module to get locator data.
22
- const {getLocatorData} = require('../procs/getLocatorData');
23
-
24
- // ########## FUNCTIONS
25
-
26
- // Runs the test and returns the result.
27
- exports.reporter = async (page, withItems) => {
28
- // Specify the rule.
29
- const ruleData = {
30
- ruleID: 'linkTitle',
31
- selector: 'a[title]',
32
- pruner: async loc => {
33
- const elData = await getLocatorData(loc);
34
- const title = await loc.getAttribute('title');
35
- return elData.excerpt.toLowerCase().includes(title.toLowerCase());
36
- },
37
- complaints: {
38
- instance: 'Link has a title attribute that repeats link text content',
39
- summary: 'Links have title attributes that repeat link text contents'
40
- },
41
- ordinalSeverity: 0,
42
- summaryTagName: 'A'
43
- };
44
- // Run the test and return the result.
45
- return await simplify(page, withItems, ruleData);
46
- };
@@ -1,10 +0,0 @@
1
- {
2
- "ruleID": "linkTo",
3
- "selector": "a:not([href]):visible",
4
- "complaints": {
5
- "instance": "Element has no href attribute",
6
- "summary": "Links are missing href attributes"
7
- },
8
- "ordinalSeverity": 2,
9
- "summaryTagName": "A"
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "ruleID": "pseudoP",
3
- "selector": "body br + br",
4
- "complaints": {
5
- "instance": "br element follows another br element, likely acting as a pseudo-paragraph",
6
- "summary": "br elements follow other br elements, likely acting as pseudo-paragraphs"
7
- },
8
- "ordinalSeverity": 0,
9
- "summaryTagName": "BR"
10
- }
@@ -1,10 +0,0 @@
1
- {
2
- "ruleID": "titledEl",
3
- "selector": "[title]:not(button, iframe, input, link, select, textarea)",
4
- "complaints": {
5
- "instance": "Ineligible element has a title attribute",
6
- "summary": "Ineligible elements have title attributes"
7
- },
8
- "ordinalSeverity": 2,
9
- "summaryTagName": ""
10
- }