@afixt/test-utils 1.2.3 → 2.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 (39) hide show
  1. package/.claude/settings.local.json +1 -6
  2. package/BROWSER_TESTING.md +42 -22
  3. package/CHANGELOG.md +40 -0
  4. package/CLAUDE.md +10 -9
  5. package/package.json +1 -1
  6. package/src/constants.js +438 -1
  7. package/src/domUtils.js +17 -38
  8. package/src/formUtils.js +7 -24
  9. package/src/getAccessibleName.js +20 -56
  10. package/src/getCSSGeneratedContent.js +2 -0
  11. package/src/getFocusableElements.js +12 -21
  12. package/src/getGeneratedContent.js +18 -11
  13. package/src/getImageText.js +22 -7
  14. package/src/hasValidAriaRole.js +11 -19
  15. package/src/index.js +4 -4
  16. package/src/interactiveRoles.js +2 -19
  17. package/src/isA11yVisible.js +95 -0
  18. package/src/isAriaAttributesValid.js +5 -64
  19. package/src/isFocusable.js +30 -10
  20. package/src/isHidden.js +44 -8
  21. package/src/listEventListeners.js +115 -10
  22. package/src/stringUtils.js +19 -98
  23. package/src/tableUtils.js +4 -36
  24. package/src/testContrast.js +54 -0
  25. package/test/domUtils.test.js +156 -0
  26. package/test/formUtils.test.js +0 -47
  27. package/test/getAccessibleName.test.js +39 -0
  28. package/test/getGeneratedContent.test.js +305 -241
  29. package/test/getImageText.test.js +158 -99
  30. package/test/index.test.js +54 -17
  31. package/test/{isVisible.test.js → isA11yVisible.test.js} +39 -33
  32. package/test/isFocusable.test.js +265 -272
  33. package/test/isHidden.test.js +257 -153
  34. package/test/listEventListeners.test.js +163 -44
  35. package/test/playwright/css-pseudo-elements.spec.js +3 -13
  36. package/test/stringUtils.test.js +55 -228
  37. package/test/testContrast.test.js +104 -2
  38. package/todo.md +2 -2
  39. package/src/isVisible.js +0 -103
@@ -2,156 +2,260 @@ import { describe, it, expect, beforeEach } from 'vitest';
2
2
  import isHidden from '../src/isHidden.js';
3
3
 
4
4
  describe('isHidden', () => {
5
- // Setup before each test
6
- beforeEach(() => {
7
- document.body.innerHTML = '';
8
- });
9
-
10
- it('should return true for elements with display:none', () => {
11
- // Arrange
12
- const element = document.createElement('div');
13
- element.style.display = 'none';
14
- document.body.appendChild(element);
15
-
16
- // Act
17
- const result = isHidden(element);
18
-
19
- // Assert
20
- expect(result).toBe(true);
21
- });
22
-
23
- it('should return true for elements with hidden attribute', () => {
24
- // Arrange
25
- const element = document.createElement('div');
26
- element.setAttribute('hidden', '');
27
- document.body.appendChild(element);
28
-
29
- // Act
30
- const result = isHidden(element);
31
-
32
- // Assert
33
- expect(result).toBe(true);
34
- });
35
-
36
- it('should return true for elements with both display:none and hidden attribute', () => {
37
- // Arrange
38
- const element = document.createElement('div');
39
- element.style.display = 'none';
40
- element.setAttribute('hidden', '');
41
- document.body.appendChild(element);
42
-
43
- // Act
44
- const result = isHidden(element);
45
-
46
- // Assert
47
- expect(result).toBe(true);
48
- });
49
-
50
- it('should return false for visible elements with no hidden attribute', () => {
51
- // Arrange
52
- const element = document.createElement('div');
53
- element.textContent = 'Visible element';
54
- document.body.appendChild(element);
55
-
56
- // Act
57
- const result = isHidden(element);
58
-
59
- // Assert
60
- expect(result).toBe(false);
61
- });
62
-
63
- it('should return false for elements with display:block', () => {
64
- // Arrange
65
- const element = document.createElement('div');
66
- element.style.display = 'block';
67
- document.body.appendChild(element);
68
-
69
- // Act
70
- const result = isHidden(element);
71
-
72
- // Assert
73
- expect(result).toBe(false);
74
- });
75
-
76
- it('should return false for elements with display:inline', () => {
77
- // Arrange
78
- const element = document.createElement('span');
79
- element.style.display = 'inline';
80
- document.body.appendChild(element);
81
-
82
- // Act
83
- const result = isHidden(element);
84
-
85
- // Assert
86
- expect(result).toBe(false);
87
- });
88
-
89
- it('should return false for elements with display:flex', () => {
90
- // Arrange
91
- const element = document.createElement('div');
92
- element.style.display = 'flex';
93
- document.body.appendChild(element);
94
-
95
- // Act
96
- const result = isHidden(element);
97
-
98
- // Assert
99
- expect(result).toBe(false);
100
- });
101
-
102
- it('should handle elements with visibility:hidden but not display:none', () => {
103
- // Arrange
104
- const element = document.createElement('div');
105
- element.style.visibility = 'hidden';
106
- document.body.appendChild(element);
107
-
108
- // Act
109
- const result = isHidden(element);
110
-
111
- // Assert
112
- // Note: visibility:hidden does not qualify as "hidden" according to this function
113
- expect(result).toBe(false);
114
- });
115
-
116
- it('should handle elements with opacity:0 but not display:none', () => {
117
- // Arrange
118
- const element = document.createElement('div');
119
- element.style.opacity = '0';
120
- document.body.appendChild(element);
121
-
122
- // Act
123
- const result = isHidden(element);
124
-
125
- // Assert
126
- // Note: opacity:0 does not qualify as "hidden" according to this function
127
- expect(result).toBe(false);
128
- });
129
-
130
- it('should return false for elements with removed hidden attribute', () => {
131
- // Arrange
132
- const element = document.createElement('div');
133
- element.setAttribute('hidden', '');
134
- element.removeAttribute('hidden');
135
- document.body.appendChild(element);
136
-
137
- // Act
138
- const result = isHidden(element);
139
-
140
- // Assert
141
- expect(result).toBe(false);
142
- });
143
-
144
- it('should return false for elements with display changed from none to block', () => {
145
- // Arrange
146
- const element = document.createElement('div');
147
- element.style.display = 'none';
148
- element.style.display = 'block';
149
- document.body.appendChild(element);
150
-
151
- // Act
152
- const result = isHidden(element);
153
-
154
- // Assert
155
- expect(result).toBe(false);
156
- });
157
- });
5
+ // Setup before each test
6
+ beforeEach(() => {
7
+ document.body.innerHTML = '';
8
+ });
9
+
10
+ it('should return true for elements with display:none', () => {
11
+ // Arrange
12
+ const element = document.createElement('div');
13
+ element.style.display = 'none';
14
+ document.body.appendChild(element);
15
+
16
+ // Act
17
+ const result = isHidden(element);
18
+
19
+ // Assert
20
+ expect(result).toBe(true);
21
+ });
22
+
23
+ it('should return true for elements with hidden attribute', () => {
24
+ // Arrange
25
+ const element = document.createElement('div');
26
+ element.setAttribute('hidden', '');
27
+ document.body.appendChild(element);
28
+
29
+ // Act
30
+ const result = isHidden(element);
31
+
32
+ // Assert
33
+ expect(result).toBe(true);
34
+ });
35
+
36
+ it('should return true for elements with both display:none and hidden attribute', () => {
37
+ // Arrange
38
+ const element = document.createElement('div');
39
+ element.style.display = 'none';
40
+ element.setAttribute('hidden', '');
41
+ document.body.appendChild(element);
42
+
43
+ // Act
44
+ const result = isHidden(element);
45
+
46
+ // Assert
47
+ expect(result).toBe(true);
48
+ });
49
+
50
+ it('should return false for visible elements with no hidden attribute', () => {
51
+ // Arrange
52
+ const element = document.createElement('div');
53
+ element.textContent = 'Visible element';
54
+ document.body.appendChild(element);
55
+
56
+ // Act
57
+ const result = isHidden(element);
58
+
59
+ // Assert
60
+ expect(result).toBe(false);
61
+ });
62
+
63
+ it('should return false for elements with display:block', () => {
64
+ // Arrange
65
+ const element = document.createElement('div');
66
+ element.style.display = 'block';
67
+ document.body.appendChild(element);
68
+
69
+ // Act
70
+ const result = isHidden(element);
71
+
72
+ // Assert
73
+ expect(result).toBe(false);
74
+ });
75
+
76
+ it('should return false for elements with display:inline', () => {
77
+ // Arrange
78
+ const element = document.createElement('span');
79
+ element.style.display = 'inline';
80
+ document.body.appendChild(element);
81
+
82
+ // Act
83
+ const result = isHidden(element);
84
+
85
+ // Assert
86
+ expect(result).toBe(false);
87
+ });
88
+
89
+ it('should return false for elements with display:flex', () => {
90
+ // Arrange
91
+ const element = document.createElement('div');
92
+ element.style.display = 'flex';
93
+ document.body.appendChild(element);
94
+
95
+ // Act
96
+ const result = isHidden(element);
97
+
98
+ // Assert
99
+ expect(result).toBe(false);
100
+ });
101
+
102
+ it('should handle elements with visibility:hidden but not display:none', () => {
103
+ // Arrange
104
+ const element = document.createElement('div');
105
+ element.style.visibility = 'hidden';
106
+ document.body.appendChild(element);
107
+
108
+ // Act
109
+ const result = isHidden(element);
110
+
111
+ // Assert
112
+ // visibility:hidden is now detected as hidden via computed style
113
+ expect(result).toBe(true);
114
+ });
115
+
116
+ it('should handle elements with opacity:0 but not display:none', () => {
117
+ // Arrange
118
+ const element = document.createElement('div');
119
+ element.style.opacity = '0';
120
+ document.body.appendChild(element);
121
+
122
+ // Act
123
+ const result = isHidden(element);
124
+
125
+ // Assert
126
+ // Note: opacity:0 does not qualify as "hidden" according to this function
127
+ expect(result).toBe(false);
128
+ });
129
+
130
+ it('should return false for elements with removed hidden attribute', () => {
131
+ // Arrange
132
+ const element = document.createElement('div');
133
+ element.setAttribute('hidden', '');
134
+ element.removeAttribute('hidden');
135
+ document.body.appendChild(element);
136
+
137
+ // Act
138
+ const result = isHidden(element);
139
+
140
+ // Assert
141
+ expect(result).toBe(false);
142
+ });
143
+
144
+ it('should return false for elements with display changed from none to block', () => {
145
+ // Arrange
146
+ const element = document.createElement('div');
147
+ element.style.display = 'none';
148
+ element.style.display = 'block';
149
+ document.body.appendChild(element);
150
+
151
+ // Act
152
+ const result = isHidden(element);
153
+
154
+ // Assert
155
+ expect(result).toBe(false);
156
+ });
157
+
158
+ it('should return false for null or invalid input', () => {
159
+ expect(isHidden(null)).toBe(false);
160
+ expect(isHidden(undefined)).toBe(false);
161
+ expect(isHidden('not an element')).toBe(false);
162
+ });
163
+
164
+ it('should detect display:none applied via CSS class', () => {
165
+ // Arrange
166
+ const style = document.createElement('style');
167
+ style.textContent = '.sr-hidden { display: none; }';
168
+ document.head.appendChild(style);
169
+ const element = document.createElement('div');
170
+ element.className = 'sr-hidden';
171
+ document.body.appendChild(element);
172
+
173
+ // Act
174
+ const result = isHidden(element);
175
+
176
+ // Assert
177
+ expect(result).toBe(true);
178
+
179
+ // Cleanup
180
+ document.head.removeChild(style);
181
+ });
182
+
183
+ it('should return false for aria-hidden="true" by default', () => {
184
+ // Arrange
185
+ const element = document.createElement('div');
186
+ element.setAttribute('aria-hidden', 'true');
187
+ document.body.appendChild(element);
188
+
189
+ // Act & Assert
190
+ expect(isHidden(element)).toBe(false);
191
+ });
192
+
193
+ it('should return true for aria-hidden="true" with checkAriaHidden option', () => {
194
+ // Arrange
195
+ const element = document.createElement('div');
196
+ element.setAttribute('aria-hidden', 'true');
197
+ document.body.appendChild(element);
198
+
199
+ // Act & Assert
200
+ expect(isHidden(element, { checkAriaHidden: true })).toBe(true);
201
+ });
202
+
203
+ it('should return false for opacity:0 by default', () => {
204
+ // Arrange
205
+ const element = document.createElement('div');
206
+ element.style.opacity = '0';
207
+ document.body.appendChild(element);
208
+
209
+ // Act & Assert - already covered above, but explicit for options
210
+ expect(isHidden(element)).toBe(false);
211
+ });
212
+
213
+ it('should return true for opacity:0 with checkOpacity option', () => {
214
+ // Arrange
215
+ const element = document.createElement('div');
216
+ element.style.opacity = '0';
217
+ document.body.appendChild(element);
218
+
219
+ // Act & Assert
220
+ expect(isHidden(element, { checkOpacity: true })).toBe(true);
221
+ });
222
+
223
+ it('should return false for zero dimensions by default', () => {
224
+ // Arrange
225
+ const element = document.createElement('div');
226
+ document.body.appendChild(element);
227
+ // JSDOM sets offsetWidth/offsetHeight to 0 by default
228
+
229
+ // Act & Assert
230
+ expect(isHidden(element)).toBe(false);
231
+ });
232
+
233
+ it('should return true for zero dimensions with checkDimensions option', () => {
234
+ // Arrange
235
+ const element = document.createElement('div');
236
+ document.body.appendChild(element);
237
+ // JSDOM sets offsetWidth/offsetHeight to 0 by default
238
+
239
+ // Act & Assert
240
+ expect(isHidden(element, { checkDimensions: true })).toBe(true);
241
+ });
242
+
243
+ it('should detect visibility:hidden applied via CSS class', () => {
244
+ // Arrange
245
+ const style = document.createElement('style');
246
+ style.textContent = '.vis-hidden { visibility: hidden; }';
247
+ document.head.appendChild(style);
248
+ const element = document.createElement('div');
249
+ element.className = 'vis-hidden';
250
+ document.body.appendChild(element);
251
+
252
+ // Act
253
+ const result = isHidden(element);
254
+
255
+ // Assert
256
+ expect(result).toBe(true);
257
+
258
+ // Cleanup
259
+ document.head.removeChild(style);
260
+ });
261
+ });