testaro 25.0.1 → 25.1.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 (2) hide show
  1. package/package.json +1 -1
  2. package/testaro/hover.js +48 -143
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testaro",
3
- "version": "25.0.1",
3
+ "version": "25.1.0",
4
4
  "description": "Run 920 web accessibility tests from 9 tools and get a standardized report",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/testaro/hover.js CHANGED
@@ -1,153 +1,58 @@
1
1
  /*
2
2
  hover
3
- This test reports unexpected impacts of hovering on the visible page. Impacts are measured by
4
- pixel changes outside the hovered element and by unhoverability.
5
-
6
- The elements that are subjected to hovering (called “triggers”) are the Playwright-visible
7
- elements that have 'A', 'BUTTON', or (if not with role=menuitem) 'LI' tag names or have
8
- 'onmouseenter' or 'onmouseover' attributes.
9
-
10
- Despite the delay, the test can make the execution time practical by randomly sampling triggers
11
- instead of hovering over all of them. When sampling is performed, the results may vary from one
12
- execution to another. Because hover impacts typically occur near the beginning of a page with
13
- navigation menus, the probability of the inclusion of a trigger in a sample decreases with the
14
- index of the trigger.
15
-
16
- Pixel changes: If no pixel changes occur immediately after an element is hovered over, the page
17
- is examined once more, after 0.5 second. The greater the fraction of changed pixels, the greater
18
- the ordinal severity.
19
-
20
- Unhoverability: An element is reported as unhoverable when it fails the Playwright actionability
21
- checks for hovering, i.e. fails to be attached to the DOM, visible, stable (not or no longer
22
- animating), and able to receive events. All triggers satisfy the first two conditions, so only the
23
- last two might fail. Playwright defines the ability to receive events as being the target of an
24
- action on the location where the center of the element is, rather than some other element with a
25
- higher zIndex value in the same location being the target.
26
-
27
- WARNING: This test uses the procs/visChange module. See the warning in that module about browser
28
- types.
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.
29
8
  */
30
9
 
31
- // IMPORTS
32
-
33
- // Module to get locator data.
34
- const {getLocatorData} = require('../procs/getLocatorData');
35
- // Module to draw a sample.
36
- const {getSample} = require('../procs/sample');
37
- // Module to get pixel changes between two times.
38
- const {visChange} = require('../procs/visChange');
39
-
40
- // FUNCTIONS
41
-
42
- // Performs the hover test and reports results.
43
- exports.reporter = async (page, withItems, sampleSize = 20) => {
44
- // Initialize the result.
45
- const data = {};
46
- const totals = [0, 0, 0, 0];
47
- const standardInstances = [];
48
- // Identify the triggers.
49
- const selectors = ['a', 'button', 'li:not([role=menuitem])', '[onmouseenter]', '[onmouseover]'];
50
- const selectorString = selectors.map(selector => `body ${selector}:visible`).join(', ');
51
- const locAll = page.locator(selectorString);
52
- const locsAll = await locAll.all();
53
- // Get the population-to-sample ratio.
54
- const psRatio = Math.max(1, locsAll.length / sampleSize);
55
- // Get a sample of the triggers.
56
- const sampleIndexes = getSample(locsAll, sampleSize);
57
- const sample = sampleIndexes.map(index => locsAll[index]);
58
- // For each trigger in the sample:
59
- for (const loc of sample) {
60
- // Hover over it and get the fractional pixel change.
61
- const hoverData = await visChange(page, {
62
- delayBefore: 0,
63
- delayBetween: 500,
64
- exclusion: loc
65
- });
66
- // If the hovering and measurement succeeded:
67
- if (hoverData.success) {
68
- // If any pixels changed:
69
- if (hoverData.changePercent) {
70
- // Get the ordinal severity from the fractional pixel change.
71
- const ordinalSeverity = Math.floor(Math.min(3, 0.4 * Math.sqrt(hoverData.changePercent)));
72
- // Add to the totals.
73
- totals[ordinalSeverity] += psRatio;
74
- // If itemization is required:
75
- if (withItems) {
76
- // Get data on the trigger.
77
- const elData = await getLocatorData(loc);
78
- // Add an instance to the result.
79
- standardInstances.push({
80
- ruleID: 'hover',
81
- what: 'Hovering over the element changes the page',
82
- ordinalSeverity,
83
- tagName: elData.tagName,
84
- id: elData.id,
85
- location: elData.location,
86
- excerpt: elData.excerpt
87
- });
88
- }
89
- }
90
- }
91
- // Otherwise, i.e. if hovering and measurement failed:
92
- else {
93
- // Add to the totals.
94
- totals[3] += psRatio;
95
- // If itemization is required:
96
- if (withItems) {
97
- // Get data on the trigger.
98
- const elData = await getLocatorData(loc);
99
- // Add an instance to the result.
100
- standardInstances.push({
101
- ruleID: 'hover',
102
- what: 'Element is not hoverable',
103
- ordinalSeverity: 3,
104
- tagName: elData.tagName,
105
- id: elData.id,
106
- location: elData.location,
107
- excerpt: elData.excerpt
108
- });
109
- }
110
- }
111
- // Reload the page to preserve locator integrity.
10
+ // ########## IMPORTS
11
+
12
+ // Module to perform common operations.
13
+ const {init, report} = require('../procs/testaro');
14
+
15
+ // ########## FUNCTIONS
16
+
17
+ // Runs the test and returns the result.
18
+ exports.reporter = async (page, withItems) => {
19
+ // Initialize the locators and result.
20
+ const all = await init(
21
+ page, 'body [aria-controls], body [aria-expanded], body [onmouseenter], body [onmouseover]'
22
+ );
23
+ const miscAll = await init(page, 'body *:visible');
24
+ all.allLocs.push(... miscAll.allLocs.slice(0, - all.allLocs.length));
25
+ // For each locator:
26
+ for (const loc of all.allLocs) {
27
+ // Get how many elements are added or subtracted when the element is hovered over.
28
+ await page.mouse.move(0, 0);
29
+ const loc0 = page.locator('body *:visible');
30
+ const elementCount0 = await loc0.count();
112
31
  try {
113
- await page.reload({timeout: 5000});
32
+ await loc.hover({
33
+ force: true,
34
+ timeout: 100
35
+ });
36
+ const loc1 = page.locator('body *:visible');
37
+ const elementCount1 = await loc1.count();
38
+ const additions = elementCount1 - elementCount0;
39
+ // If any elements are:
40
+ if (additions !== 0) {
41
+ // Add the locator and the change of element count to the array of violators.
42
+ const impact = additions > 0
43
+ ? `added ${additions} elements to the page`
44
+ : `subtracted ${- additions} from the page`;
45
+ all.locs.push([loc, impact]);
46
+ }
114
47
  }
115
48
  catch(error) {
116
- console.log('ERROR: page reload timed out');
117
- }
118
- }
119
- // If itemization is not required:
120
- if (! withItems) {
121
- // For each ordinal severity:
122
- for (const index in totals) {
123
- // If there were any instances with it:
124
- if (totals[index]) {
125
- // Add a summary instance to the result.
126
- standardInstances.push({
127
- ruleID: 'hover',
128
- what: 'Hovering over elements changes the page or fails',
129
- ordinalSeverity: index,
130
- count: Math.round(totals[index]),
131
- tagName: '',
132
- id: '',
133
- location: {
134
- doc: '',
135
- type: '',
136
- spec: ''
137
- },
138
- excerpt: ''
139
- });
140
- }
49
+ console.log(`Hovering timed out (${error.message.replace(/[\n].+/s, '')})`);
141
50
  }
142
51
  }
143
- // Round the totals.
144
- totals.forEach((total, index) => {
145
- totals[index] = Math.round(totals[index]);
146
- });
147
- // Return the result.
148
- return {
149
- data,
150
- totals,
151
- standardInstances
152
- };
52
+ // Populate and return the result.
53
+ const whats = [
54
+ 'Hovering over the element __param__',
55
+ 'Hovering over elements adds elements to or subtracts elements from the page'
56
+ ];
57
+ return await report(withItems, all, 'hover', whats, 0);
153
58
  };