@afixt/test-utils 1.1.2 → 1.1.3

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 (86) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/CLAUDE.md +12 -0
  3. package/package.json +1 -1
  4. package/src/domUtils.js +1 -1
  5. package/src/getAccessibleName.js +8 -4
  6. package/src/getFocusableElements.js +13 -4
  7. package/test/domUtils.test.js +117 -0
  8. package/test/getAccessibleName.test.js +182 -0
  9. package/test/getAccessibleText.test.js +350 -79
  10. package/test/getCSSGeneratedContent.test.js +175 -1
  11. package/test/getFocusableElements.test.js +106 -35
  12. package/test/getImageText.test.js +61 -12
  13. package/test/hasParent.test.js +116 -0
  14. package/test/index.test.js +165 -0
  15. package/test/interactiveRoles.test.js +60 -0
  16. package/test/isAriaAttributesValid.test.js +36 -0
  17. package/test/isDataTable.test.js +492 -0
  18. package/test/isValidUrl.test.js +31 -19
  19. package/test/stringUtils.test.js +235 -1
  20. package/test/testContrast.test.js +176 -8
  21. package/test/testOrder.integration.test.js +369 -0
  22. package/test/testOrder.test.js +756 -21
  23. package/todo.md +150 -1
  24. package/coverage/base.css +0 -224
  25. package/coverage/block-navigation.js +0 -87
  26. package/coverage/coverage-final.json +0 -51
  27. package/coverage/favicon.png +0 -0
  28. package/coverage/index.html +0 -161
  29. package/coverage/prettify.css +0 -1
  30. package/coverage/prettify.js +0 -2
  31. package/coverage/sort-arrow-sprite.png +0 -0
  32. package/coverage/sorter.js +0 -196
  33. package/coverage/test-utils/docs/scripts/core.js.html +0 -2263
  34. package/coverage/test-utils/docs/scripts/core.min.js.html +0 -151
  35. package/coverage/test-utils/docs/scripts/index.html +0 -176
  36. package/coverage/test-utils/docs/scripts/resize.js.html +0 -355
  37. package/coverage/test-utils/docs/scripts/search.js.html +0 -880
  38. package/coverage/test-utils/docs/scripts/search.min.js.html +0 -100
  39. package/coverage/test-utils/docs/scripts/third-party/fuse.js.html +0 -109
  40. package/coverage/test-utils/docs/scripts/third-party/hljs-line-num-original.js.html +0 -1192
  41. package/coverage/test-utils/docs/scripts/third-party/hljs-line-num.js.html +0 -85
  42. package/coverage/test-utils/docs/scripts/third-party/hljs-original.js.html +0 -15598
  43. package/coverage/test-utils/docs/scripts/third-party/hljs.js.html +0 -85
  44. package/coverage/test-utils/docs/scripts/third-party/index.html +0 -236
  45. package/coverage/test-utils/docs/scripts/third-party/popper.js.html +0 -100
  46. package/coverage/test-utils/docs/scripts/third-party/tippy.js.html +0 -88
  47. package/coverage/test-utils/docs/scripts/third-party/tocbot.js.html +0 -2098
  48. package/coverage/test-utils/docs/scripts/third-party/tocbot.min.js.html +0 -85
  49. package/coverage/test-utils/index.html +0 -131
  50. package/coverage/test-utils/src/arrayUtils.js.html +0 -283
  51. package/coverage/test-utils/src/domUtils.js.html +0 -622
  52. package/coverage/test-utils/src/getAccessibleName.js.html +0 -1444
  53. package/coverage/test-utils/src/getAccessibleText.js.html +0 -271
  54. package/coverage/test-utils/src/getAriaAttributesByElement.js.html +0 -142
  55. package/coverage/test-utils/src/getCSSGeneratedContent.js.html +0 -265
  56. package/coverage/test-utils/src/getComputedRole.js.html +0 -592
  57. package/coverage/test-utils/src/getFocusableElements.js.html +0 -163
  58. package/coverage/test-utils/src/getGeneratedContent.js.html +0 -130
  59. package/coverage/test-utils/src/getImageText.js.html +0 -160
  60. package/coverage/test-utils/src/getStyleObject.js.html +0 -220
  61. package/coverage/test-utils/src/hasAccessibleName.js.html +0 -166
  62. package/coverage/test-utils/src/hasAttribute.js.html +0 -130
  63. package/coverage/test-utils/src/hasCSSGeneratedContent.js.html +0 -145
  64. package/coverage/test-utils/src/hasHiddenParent.js.html +0 -172
  65. package/coverage/test-utils/src/hasParent.js.html +0 -247
  66. package/coverage/test-utils/src/hasValidAriaAttributes.js.html +0 -175
  67. package/coverage/test-utils/src/hasValidAriaRole.js.html +0 -172
  68. package/coverage/test-utils/src/index.html +0 -611
  69. package/coverage/test-utils/src/index.js.html +0 -274
  70. package/coverage/test-utils/src/interactiveRoles.js.html +0 -145
  71. package/coverage/test-utils/src/isAriaAttributesValid.js.html +0 -304
  72. package/coverage/test-utils/src/isComplexTable.js.html +0 -412
  73. package/coverage/test-utils/src/isDataTable.js.html +0 -799
  74. package/coverage/test-utils/src/isFocusable.js.html +0 -187
  75. package/coverage/test-utils/src/isHidden.js.html +0 -136
  76. package/coverage/test-utils/src/isOffScreen.js.html +0 -133
  77. package/coverage/test-utils/src/isValidUrl.js.html +0 -124
  78. package/coverage/test-utils/src/isVisible.js.html +0 -271
  79. package/coverage/test-utils/src/listEventListeners.js.html +0 -370
  80. package/coverage/test-utils/src/queryCache.js.html +0 -1156
  81. package/coverage/test-utils/src/stringUtils.js.html +0 -535
  82. package/coverage/test-utils/src/testContrast.js.html +0 -784
  83. package/coverage/test-utils/src/testLang.js.html +0 -1810
  84. package/coverage/test-utils/src/testOrder.js.html +0 -355
  85. package/coverage/test-utils/vitest.config.browser.js.html +0 -133
  86. package/coverage/test-utils/vitest.config.js.html +0 -157
@@ -1,94 +1,365 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
2
  import { getAccessibleText } from '../src/getAccessibleText.js';
3
3
 
4
- // Mock the isEmpty function since it's not imported
5
- const originalGetAccessibleText = getAccessibleText;
6
- vi.mock('../src/getAccessibleText.js', () => ({
7
- getAccessibleText: (el) => {
8
- if (!el) return "";
9
-
10
- let text = [];
11
-
12
- // Get text from aria-label attributes
13
- const elementsWithAriaLabel = el.querySelectorAll('[aria-label]');
14
- elementsWithAriaLabel.forEach(element => {
15
- text.push(element.getAttribute('aria-label'));
16
- });
17
-
18
- // Get text from alt attributes on img elements
19
- const imgElements = el.querySelectorAll('img[alt]');
20
- imgElements.forEach(img => {
21
- text.push(img.getAttribute('alt').trim());
22
- });
23
-
24
- // Also check the element itself for aria-label or alt
25
- if (el.hasAttribute && el.hasAttribute('aria-label')) {
26
- text.push(el.getAttribute('aria-label'));
27
- } else if (el.tagName && el.tagName.toLowerCase() === 'img' && el.hasAttribute('alt')) {
28
- text.push(el.getAttribute('alt').trim());
29
- }
30
-
31
- return text.join(' ').trim();
32
- }
33
- }));
34
-
35
4
  describe('getAccessibleText', () => {
36
5
  beforeEach(() => {
37
6
  document.body.innerHTML = '';
38
7
  });
39
8
 
40
- it('should return empty string when no element is provided', () => {
41
- expect(getAccessibleText(null)).toBe('');
42
- expect(getAccessibleText(undefined)).toBe('');
9
+ afterEach(() => {
10
+ document.body.innerHTML = '';
11
+ });
12
+
13
+ describe('input validation', () => {
14
+ it('should return empty string when no element is provided', () => {
15
+ expect(getAccessibleText(null)).toBe('');
16
+ expect(getAccessibleText(undefined)).toBe('');
17
+ });
18
+
19
+ it('should return empty string for non-Element objects', () => {
20
+ expect(getAccessibleText('string')).toBe('');
21
+ expect(getAccessibleText(123)).toBe('');
22
+ expect(getAccessibleText({})).toBe('');
23
+ expect(getAccessibleText([])).toBe('');
24
+ expect(getAccessibleText(document.createTextNode('text'))).toBe(''); // Text node, not Element
25
+ expect(getAccessibleText(document.createComment('comment'))).toBe(''); // Comment node
26
+ });
27
+
28
+ it('should return empty string for disconnected elements', () => {
29
+ const div = document.createElement('div');
30
+ div.textContent = 'Test content';
31
+ // Element is not connected to DOM
32
+ expect(getAccessibleText(div)).toBe('');
33
+ });
34
+ });
35
+
36
+ describe('aria-label handling', () => {
37
+ it('should prioritize aria-label when present', () => {
38
+ const div = document.createElement('div');
39
+ div.setAttribute('aria-label', 'Accessible Label');
40
+ div.textContent = 'Visual Text';
41
+ document.body.appendChild(div);
42
+
43
+ expect(getAccessibleText(div)).toBe('Accessible Label');
44
+ });
45
+
46
+ it('should handle empty aria-label by falling back to text content', () => {
47
+ const div = document.createElement('div');
48
+ div.setAttribute('aria-label', '');
49
+ div.textContent = 'Visual Text';
50
+ document.body.appendChild(div);
51
+
52
+ expect(getAccessibleText(div)).toBe('Visual Text');
53
+ });
54
+
55
+ it('should handle aria-label with only whitespace', () => {
56
+ const div = document.createElement('div');
57
+ div.setAttribute('aria-label', ' ');
58
+ div.textContent = 'Visual Text';
59
+ document.body.appendChild(div);
60
+
61
+ expect(getAccessibleText(div)).toBe('Visual Text');
62
+ });
63
+
64
+ it('should return empty aria-label when it exists but is empty after trim', () => {
65
+ const div = document.createElement('div');
66
+ div.setAttribute('aria-label', '');
67
+ div.textContent = '';
68
+ document.body.appendChild(div);
69
+
70
+ expect(getAccessibleText(div)).toBe('');
71
+ });
72
+ });
73
+
74
+ describe('img alt text handling', () => {
75
+ it('should get alt text from img elements', () => {
76
+ const img = document.createElement('img');
77
+ img.setAttribute('alt', 'Image description');
78
+ img.setAttribute('src', 'test.jpg');
79
+ document.body.appendChild(img);
80
+
81
+ expect(getAccessibleText(img)).toBe('Image description');
82
+ });
83
+
84
+ it('should handle img with empty alt attribute', () => {
85
+ const img = document.createElement('img');
86
+ img.setAttribute('alt', '');
87
+ img.setAttribute('src', 'test.jpg');
88
+ document.body.appendChild(img);
89
+
90
+ expect(getAccessibleText(img)).toBe('');
91
+ });
92
+
93
+ it('should handle img without alt attribute', () => {
94
+ const img = document.createElement('img');
95
+ img.setAttribute('src', 'test.jpg');
96
+ document.body.appendChild(img);
97
+
98
+ expect(getAccessibleText(img)).toBe('');
99
+ });
100
+
101
+ it('should trim whitespace from img alt text', () => {
102
+ const img = document.createElement('img');
103
+ img.setAttribute('alt', ' Image description ');
104
+ img.setAttribute('src', 'test.jpg');
105
+ document.body.appendChild(img);
106
+
107
+ expect(getAccessibleText(img)).toBe('Image description');
108
+ });
109
+
110
+ it('should prioritize aria-label over alt text on img', () => {
111
+ const img = document.createElement('img');
112
+ img.setAttribute('alt', 'Alt text');
113
+ img.setAttribute('aria-label', 'Aria label');
114
+ img.setAttribute('src', 'test.jpg');
115
+ document.body.appendChild(img);
116
+
117
+ expect(getAccessibleText(img)).toBe('Aria label');
118
+ });
43
119
  });
44
120
 
45
- it('should get text from aria-label attribute', () => {
46
- // Arrange
47
- const div = document.createElement('div');
48
- div.setAttribute('aria-label', 'Accessible Label');
49
- document.body.appendChild(div);
50
-
51
- // Act
52
- const result = getAccessibleText(div);
53
-
54
- // Assert
55
- expect(result).toBe('Accessible Label');
121
+ describe('text content extraction', () => {
122
+ it('should get text content from simple elements', () => {
123
+ const div = document.createElement('div');
124
+ div.textContent = 'Simple text content';
125
+ document.body.appendChild(div);
126
+
127
+ expect(getAccessibleText(div)).toBe('Simple text content');
128
+ });
129
+
130
+ it('should trim whitespace from text content', () => {
131
+ const div = document.createElement('div');
132
+ div.textContent = ' Padded text ';
133
+ document.body.appendChild(div);
134
+
135
+ expect(getAccessibleText(div)).toBe('Padded text');
136
+ });
137
+
138
+ it('should concatenate text from multiple child nodes', () => {
139
+ const container = document.createElement('div');
140
+ container.innerHTML = `
141
+ <span>First part</span>
142
+ <span>Second part</span>
143
+ <span>Third part</span>
144
+ `;
145
+ document.body.appendChild(container);
146
+
147
+ const result = getAccessibleText(container);
148
+ expect(result).toContain('First part');
149
+ expect(result).toContain('Second part');
150
+ expect(result).toContain('Third part');
151
+ });
152
+
153
+ it('should handle nested elements', () => {
154
+ const container = document.createElement('div');
155
+ container.innerHTML = `
156
+ <div>
157
+ <span>Nested <strong>text</strong> content</span>
158
+ </div>
159
+ `;
160
+ document.body.appendChild(container);
161
+
162
+ const result = getAccessibleText(container);
163
+ expect(result).toContain('Nested');
164
+ expect(result).toContain('text');
165
+ expect(result).toContain('content');
166
+ });
56
167
  });
57
168
 
58
- it('should get alt text from img elements', () => {
59
- // Arrange
60
- const parent = document.createElement('div');
61
- const img = document.createElement('img');
62
- img.setAttribute('alt', 'Image description');
63
- parent.appendChild(img);
64
- document.body.appendChild(parent);
65
-
66
- // Act
67
- const result = getAccessibleText(parent);
68
-
69
- // Assert
70
- expect(result).toBe('Image description');
169
+ describe('TreeWalker edge cases', () => {
170
+ it('should handle elements with no initial text content using TreeWalker', () => {
171
+ const container = document.createElement('div');
172
+ // Create element with no textContent initially
173
+ container.textContent = '';
174
+
175
+ const span1 = document.createElement('span');
176
+ const span2 = document.createElement('span');
177
+
178
+ // Create text nodes directly
179
+ span1.appendChild(document.createTextNode('Text 1'));
180
+ span2.appendChild(document.createTextNode('Text 2'));
181
+
182
+ container.appendChild(span1);
183
+ container.appendChild(document.createTextNode(' ')); // whitespace node
184
+ container.appendChild(span2);
185
+
186
+ document.body.appendChild(container);
187
+
188
+ const result = getAccessibleText(container);
189
+ expect(result).toContain('Text 1');
190
+ expect(result).toContain('Text 2');
191
+ });
192
+
193
+ it('should filter empty text nodes using TreeWalker', () => {
194
+ const container = document.createElement('div');
195
+ container.innerHTML = ''; // Start with empty container
196
+
197
+ // Add mix of empty and non-empty text nodes
198
+ container.appendChild(document.createTextNode(''));
199
+ container.appendChild(document.createTextNode('Valid text'));
200
+ container.appendChild(document.createTextNode(' ')); // Only whitespace
201
+ container.appendChild(document.createTextNode('More text'));
202
+
203
+ document.body.appendChild(container);
204
+
205
+ const result = getAccessibleText(container);
206
+ expect(result).toContain('Valid text');
207
+ expect(result).toContain('More text');
208
+ });
209
+
210
+ it('should handle complex DOM with mixed content', () => {
211
+ const container = document.createElement('div');
212
+ container.innerHTML = `
213
+ <header>
214
+ <h1>Title</h1>
215
+ <nav>
216
+ <a href="#">Link 1</a>
217
+ <a href="#">Link 2</a>
218
+ </nav>
219
+ </header>
220
+ <main>
221
+ <p>Paragraph text</p>
222
+ <ul>
223
+ <li>Item 1</li>
224
+ <li>Item 2</li>
225
+ </ul>
226
+ </main>
227
+ `;
228
+ document.body.appendChild(container);
229
+
230
+ const result = getAccessibleText(container);
231
+ expect(result).toContain('Title');
232
+ expect(result).toContain('Link 1');
233
+ expect(result).toContain('Link 2');
234
+ expect(result).toContain('Paragraph text');
235
+ expect(result).toContain('Item 1');
236
+ expect(result).toContain('Item 2');
237
+ });
71
238
  });
72
239
 
73
- it('should concatenate multiple text nodes', () => {
74
- // Arrange
75
- const container = document.createElement('div');
76
-
77
- const span1 = document.createElement('span');
78
- span1.setAttribute('aria-label', 'First label');
79
-
80
- const img = document.createElement('img');
81
- img.setAttribute('alt', 'Image alt');
82
-
83
- container.appendChild(span1);
84
- container.appendChild(img);
85
- document.body.appendChild(container);
86
-
87
- // Act
88
- const result = getAccessibleText(container);
89
-
90
- // Assert
91
- expect(result).toContain('First label');
92
- expect(result).toContain('Image alt');
240
+ describe('special cases', () => {
241
+ it('should handle elements with only child elements and no text', () => {
242
+ const container = document.createElement('div');
243
+ const child1 = document.createElement('div');
244
+ const child2 = document.createElement('div');
245
+
246
+ container.appendChild(child1);
247
+ container.appendChild(child2);
248
+ document.body.appendChild(container);
249
+
250
+ expect(getAccessibleText(container)).toBe('');
251
+ });
252
+
253
+ it('should use TreeWalker when textContent is empty but has text nodes', () => {
254
+ const container = document.createElement('div');
255
+ document.body.appendChild(container);
256
+
257
+ // Create a scenario where textContent initially appears empty
258
+ // but TreeWalker can find text nodes
259
+ Object.defineProperty(container, 'textContent', {
260
+ get: function() { return ''; },
261
+ configurable: true
262
+ });
263
+
264
+ // Add actual text nodes that TreeWalker should find
265
+ const text1 = document.createTextNode('Hidden text 1');
266
+ const text2 = document.createTextNode('Hidden text 2');
267
+ container.appendChild(text1);
268
+ container.appendChild(text2);
269
+
270
+ const result = getAccessibleText(container);
271
+ expect(result).toBe('Hidden text 1 Hidden text 2');
272
+ });
273
+
274
+ it('should handle self-closing elements', () => {
275
+ const br = document.createElement('br');
276
+ document.body.appendChild(br);
277
+
278
+ expect(getAccessibleText(br)).toBe('');
279
+ });
280
+
281
+ it('should handle input elements with value', () => {
282
+ const input = document.createElement('input');
283
+ input.type = 'text';
284
+ input.value = 'Input value';
285
+ document.body.appendChild(input);
286
+
287
+ // Input elements don't have textContent
288
+ expect(getAccessibleText(input)).toBe('');
289
+ });
290
+
291
+ it('should handle elements with comment nodes', () => {
292
+ const container = document.createElement('div');
293
+ container.appendChild(document.createTextNode('Before'));
294
+ container.appendChild(document.createComment('This is a comment'));
295
+ container.appendChild(document.createTextNode('After'));
296
+ document.body.appendChild(container);
297
+
298
+ const result = getAccessibleText(container);
299
+ expect(result).toContain('Before');
300
+ expect(result).toContain('After');
301
+ expect(result).not.toContain('comment');
302
+ });
303
+
304
+ it('should handle TreeWalker acceptNode with element nodes that should be rejected', () => {
305
+ const container = document.createElement('div');
306
+ container.textContent = ''; // Ensure no textContent initially
307
+
308
+ // Create an element node (should be rejected by acceptNode)
309
+ const span = document.createElement('span');
310
+ span.appendChild(document.createTextNode('Text inside span'));
311
+ container.appendChild(span);
312
+
313
+ // Create a direct text node (should be accepted)
314
+ container.appendChild(document.createTextNode('Direct text'));
315
+
316
+ document.body.appendChild(container);
317
+
318
+ const result = getAccessibleText(container);
319
+ expect(result).toContain('Text inside span');
320
+ expect(result).toContain('Direct text');
321
+ });
322
+
323
+ it('should handle TreeWalker acceptNode filtering and text node collection', () => {
324
+ const container = document.createElement('div');
325
+ container.textContent = ''; // Force TreeWalker path
326
+
327
+ // Create child elements with text nodes to test TreeWalker
328
+ const child1 = document.createElement('span');
329
+ child1.appendChild(document.createTextNode('First'));
330
+
331
+ const child2 = document.createElement('span');
332
+ child2.appendChild(document.createTextNode('Second'));
333
+
334
+ container.appendChild(child1);
335
+ container.appendChild(document.createTextNode(' ')); // space between
336
+ container.appendChild(child2);
337
+
338
+ document.body.appendChild(container);
339
+
340
+ const result = getAccessibleText(container);
341
+ expect(result).toBe('First Second');
342
+ });
343
+
344
+ it('should test TreeWalker acceptNode function with various node types', () => {
345
+ const container = document.createElement('div');
346
+ document.body.appendChild(container);
347
+
348
+ // Override textContent to force TreeWalker path
349
+ Object.defineProperty(container, 'textContent', {
350
+ get: function() { return ''; },
351
+ configurable: true
352
+ });
353
+
354
+ // Add mix of empty and non-empty text nodes
355
+ container.appendChild(document.createTextNode('')); // Empty - should be rejected
356
+ container.appendChild(document.createTextNode(' ')); // Whitespace only - should be rejected
357
+ container.appendChild(document.createTextNode('Valid')); // Valid - should be accepted
358
+ container.appendChild(document.createTextNode('\n\t')); // Whitespace - should be rejected
359
+ container.appendChild(document.createTextNode('Text')); // Valid - should be accepted
360
+
361
+ const result = getAccessibleText(container);
362
+ expect(result).toBe('Valid Text');
363
+ });
93
364
  });
94
365
  });
@@ -1,4 +1,4 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
2
  import { getCSSGeneratedContent } from '../src/getCSSGeneratedContent';
3
3
 
4
4
  describe('getCSSGeneratedContent', () => {
@@ -41,7 +41,16 @@ describe('getCSSGeneratedContent', () => {
41
41
  const div = document.createElement('div');
42
42
  document.body.appendChild(div);
43
43
 
44
+ // Mock getComputedStyle for this test since JSDOM doesn't support it
45
+ const originalGetComputedStyle = window.getComputedStyle;
46
+ window.getComputedStyle = () => ({
47
+ getPropertyValue: () => 'none'
48
+ });
49
+
44
50
  expect(getCSSGeneratedContent(div)).toBe(false);
51
+
52
+ // Restore original
53
+ window.getComputedStyle = originalGetComputedStyle;
45
54
  });
46
55
 
47
56
  it('should get ::before content', () => {
@@ -89,7 +98,16 @@ describe('getCSSGeneratedContent', () => {
89
98
  div.className = 'empty-content';
90
99
  document.body.appendChild(div);
91
100
 
101
+ // Mock getComputedStyle to return empty quoted content
102
+ const originalGetComputedStyle = window.getComputedStyle;
103
+ window.getComputedStyle = () => ({
104
+ getPropertyValue: () => '""'
105
+ });
106
+
92
107
  expect(getCSSGeneratedContent(div)).toBe(false);
108
+
109
+ // Restore original
110
+ window.getComputedStyle = originalGetComputedStyle;
93
111
  });
94
112
 
95
113
  it('should return false for content: none', () => {
@@ -99,4 +117,160 @@ describe('getCSSGeneratedContent', () => {
99
117
 
100
118
  expect(getCSSGeneratedContent(div)).toBe(false);
101
119
  });
120
+
121
+ it('should handle url content', () => {
122
+ const div = document.createElement('div');
123
+ div.className = 'url-content';
124
+ document.body.appendChild(div);
125
+
126
+ expect(getCSSGeneratedContent(div, 'before')).toBe('url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")');
127
+ });
128
+
129
+ it('should handle undefined and non-string pseudoElement parameter', () => {
130
+ const div = document.createElement('div');
131
+ div.className = 'with-before';
132
+ document.body.appendChild(div);
133
+
134
+ // Should default to 'both' when no pseudoElement specified
135
+ expect(getCSSGeneratedContent(div, undefined)).toBe('Before Content');
136
+ });
137
+
138
+ describe('Browser implementation paths', () => {
139
+ let originalGetComputedStyle;
140
+
141
+ beforeEach(() => {
142
+ // Mock getComputedStyle to simulate real browser behavior
143
+ originalGetComputedStyle = window.getComputedStyle;
144
+ });
145
+
146
+ afterEach(() => {
147
+ // Restore original getComputedStyle
148
+ window.getComputedStyle = originalGetComputedStyle;
149
+ });
150
+
151
+ it('should handle quote removal in browser implementation', () => {
152
+ // Mock getComputedStyle to return quoted content
153
+ window.getComputedStyle = (el, pseudo) => ({
154
+ getPropertyValue: (prop) => {
155
+ if (prop === 'content' && pseudo === '::before') {
156
+ return '"Quoted Content"';
157
+ }
158
+ return 'none';
159
+ }
160
+ });
161
+
162
+ const div = document.createElement('div');
163
+ // Remove classList to bypass JSDOM check
164
+ Object.defineProperty(div, 'classList', { value: undefined });
165
+ document.body.appendChild(div);
166
+
167
+ expect(getCSSGeneratedContent(div, 'before')).toBe('Quoted Content');
168
+ });
169
+
170
+ it('should handle single quote removal in browser implementation', () => {
171
+ window.getComputedStyle = (el, pseudo) => ({
172
+ getPropertyValue: (prop) => {
173
+ if (prop === 'content' && pseudo === '::before') {
174
+ return "'Single Quoted'";
175
+ }
176
+ return 'none';
177
+ }
178
+ });
179
+
180
+ const div = document.createElement('div');
181
+ Object.defineProperty(div, 'classList', { value: undefined });
182
+ document.body.appendChild(div);
183
+
184
+ expect(getCSSGeneratedContent(div, 'before')).toBe('Single Quoted');
185
+ });
186
+
187
+ it('should handle both before and after content with quotes', () => {
188
+ window.getComputedStyle = (el, pseudo) => ({
189
+ getPropertyValue: (prop) => {
190
+ if (prop === 'content') {
191
+ if (pseudo === '::before') return '"Before"';
192
+ if (pseudo === '::after') return '"After"';
193
+ }
194
+ return 'none';
195
+ }
196
+ });
197
+
198
+ const div = document.createElement('div');
199
+ Object.defineProperty(div, 'classList', { value: undefined });
200
+ document.body.appendChild(div);
201
+
202
+ expect(getCSSGeneratedContent(div, 'both')).toBe('Before After');
203
+ });
204
+
205
+ it('should handle after content with quotes', () => {
206
+ window.getComputedStyle = (el, pseudo) => ({
207
+ getPropertyValue: (prop) => {
208
+ if (prop === 'content' && pseudo === '::after') {
209
+ return '"After Content"';
210
+ }
211
+ return 'none';
212
+ }
213
+ });
214
+
215
+ const div = document.createElement('div');
216
+ Object.defineProperty(div, 'classList', { value: undefined });
217
+ document.body.appendChild(div);
218
+
219
+ expect(getCSSGeneratedContent(div, 'after')).toBe('After Content');
220
+ });
221
+
222
+ it('should handle content: none in browser implementation', () => {
223
+ window.getComputedStyle = (el, pseudo) => ({
224
+ getPropertyValue: (prop) => 'none'
225
+ });
226
+
227
+ const div = document.createElement('div');
228
+ Object.defineProperty(div, 'classList', { value: undefined });
229
+ document.body.appendChild(div);
230
+
231
+ expect(getCSSGeneratedContent(div)).toBe(false);
232
+ });
233
+
234
+ it('should handle content: normal in browser implementation', () => {
235
+ window.getComputedStyle = (el, pseudo) => ({
236
+ getPropertyValue: (prop) => 'normal'
237
+ });
238
+
239
+ const div = document.createElement('div');
240
+ Object.defineProperty(div, 'classList', { value: undefined });
241
+ document.body.appendChild(div);
242
+
243
+ expect(getCSSGeneratedContent(div)).toBe(false);
244
+ });
245
+
246
+ it('should handle empty quoted content', () => {
247
+ window.getComputedStyle = (el, pseudo) => ({
248
+ getPropertyValue: (prop) => {
249
+ if (prop === 'content') {
250
+ if (pseudo === '::before') return '""';
251
+ }
252
+ return 'none';
253
+ }
254
+ });
255
+
256
+ const div = document.createElement('div');
257
+ Object.defineProperty(div, 'classList', { value: undefined });
258
+ document.body.appendChild(div);
259
+
260
+ expect(getCSSGeneratedContent(div, 'before')).toBe(false);
261
+ });
262
+
263
+ it('should handle getComputedStyle error', () => {
264
+ // Mock getComputedStyle to throw an error
265
+ window.getComputedStyle = () => {
266
+ throw new Error('getComputedStyle not supported');
267
+ };
268
+
269
+ const div = document.createElement('div');
270
+ Object.defineProperty(div, 'classList', { value: undefined });
271
+ document.body.appendChild(div);
272
+
273
+ expect(getCSSGeneratedContent(div)).toBe(false);
274
+ });
275
+ });
102
276
  });