@afixt/test-utils 1.1.7 → 1.2.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 (70) hide show
  1. package/.claude/settings.local.json +6 -1
  2. package/.github/workflows/ci.yml +71 -0
  3. package/.github/workflows/pr-check.yml +88 -0
  4. package/.github/workflows/security.yml +139 -0
  5. package/.husky/pre-commit +1 -0
  6. package/.jscpd.json +27 -0
  7. package/.markdownlint.json +9 -0
  8. package/.prettierignore +13 -0
  9. package/.prettierrc +10 -0
  10. package/docs/arrayUtils.js.html +2 -2
  11. package/docs/domUtils.js.html +2 -2
  12. package/docs/getAccessibleName.js.html +2 -2
  13. package/docs/getAccessibleText.js.html +2 -2
  14. package/docs/getAriaAttributesByElement.js.html +2 -2
  15. package/docs/getCSSGeneratedContent.js.html +2 -2
  16. package/docs/getComputedRole.js.html +2 -2
  17. package/docs/getFocusableElements.js.html +2 -2
  18. package/docs/getGeneratedContent.js.html +2 -2
  19. package/docs/getImageText.js.html +2 -2
  20. package/docs/getStyleObject.js.html +2 -2
  21. package/docs/global.html +2 -2
  22. package/docs/hasAccessibleName.js.html +2 -2
  23. package/docs/hasAttribute.js.html +2 -2
  24. package/docs/hasCSSGeneratedContent.js.html +2 -2
  25. package/docs/hasHiddenParent.js.html +2 -2
  26. package/docs/hasParent.js.html +2 -2
  27. package/docs/hasValidAriaAttributes.js.html +2 -2
  28. package/docs/hasValidAriaRole.js.html +2 -2
  29. package/docs/index.html +2 -2
  30. package/docs/index.js.html +2 -2
  31. package/docs/isAriaAttributesValid.js.html +2 -2
  32. package/docs/isComplexTable.js.html +2 -2
  33. package/docs/isDataTable.js.html +2 -2
  34. package/docs/isFocusable.js.html +2 -2
  35. package/docs/isHidden.js.html +2 -2
  36. package/docs/isOffScreen.js.html +2 -2
  37. package/docs/isValidUrl.js.html +2 -2
  38. package/docs/isVisible.js.html +2 -2
  39. package/docs/module-afixt-test-utils.html +2 -2
  40. package/docs/scripts/core.js +726 -726
  41. package/docs/scripts/core.min.js +22 -22
  42. package/docs/scripts/resize.js +90 -90
  43. package/docs/scripts/search.js +265 -265
  44. package/docs/scripts/third-party/Apache-License-2.0.txt +202 -202
  45. package/docs/scripts/third-party/fuse.js +8 -8
  46. package/docs/scripts/third-party/hljs-line-num-original.js +369 -369
  47. package/docs/scripts/third-party/hljs-original.js +5171 -5171
  48. package/docs/scripts/third-party/popper.js +5 -5
  49. package/docs/scripts/third-party/tippy.js +1 -1
  50. package/docs/scripts/third-party/tocbot.js +671 -671
  51. package/docs/styles/clean-jsdoc-theme-base.css +1159 -1159
  52. package/docs/styles/clean-jsdoc-theme-dark.css +412 -412
  53. package/docs/styles/clean-jsdoc-theme-light.css +482 -482
  54. package/docs/styles/clean-jsdoc-theme-scrollbar.css +29 -29
  55. package/docs/testContrast.js.html +2 -2
  56. package/docs/testLang.js.html +2 -2
  57. package/docs/testOrder.js.html +2 -2
  58. package/eslint.config.mjs +84 -0
  59. package/package.json +68 -41
  60. package/scratchpads/issue-6-standardize-repo.md +109 -0
  61. package/src/getAccessibleName.js +156 -112
  62. package/src/getAccessibleText.js +71 -42
  63. package/src/stringUtils.js +19 -21
  64. package/src/testContrast.js +103 -22
  65. package/test/getAccessibleName.test.js +379 -315
  66. package/test/getAccessibleText.test.js +375 -308
  67. package/test/stringUtils.test.js +376 -332
  68. package/test/testContrast.test.js +801 -651
  69. package/.eslintrc +0 -78
  70. package/.github/workflows/test.yml +0 -26
@@ -2,381 +2,425 @@ import { describe, it, expect } from 'vitest';
2
2
  import stringUtils from '../src/stringUtils.js';
3
3
 
4
4
  describe('stringUtils', () => {
5
- describe('isEmpty', () => {
6
- it('should return true for empty strings', () => {
7
- expect(stringUtils.isEmpty('')).toBe(true);
8
- expect(stringUtils.isEmpty(' ')).toBe(true);
9
- expect(stringUtils.isEmpty('\n\t')).toBe(true);
10
- });
5
+ describe('isEmpty', () => {
6
+ it('should return true for empty strings', () => {
7
+ expect(stringUtils.isEmpty('')).toBe(true);
8
+ expect(stringUtils.isEmpty(' ')).toBe(true);
9
+ expect(stringUtils.isEmpty('\n\t')).toBe(true);
10
+ });
11
+
12
+ it('should return true for null or undefined', () => {
13
+ expect(stringUtils.isEmpty(null)).toBe(true);
14
+ expect(stringUtils.isEmpty(undefined)).toBe(true);
15
+ });
16
+
17
+ it('should return false for non-empty strings', () => {
18
+ expect(stringUtils.isEmpty('hello')).toBe(false);
19
+ expect(stringUtils.isEmpty(' hello ')).toBe(false);
20
+ expect(stringUtils.isEmpty('0')).toBe(false);
21
+ });
22
+ });
23
+
24
+ describe('isString', () => {
25
+ it('should return true for string literals', () => {
26
+ expect(stringUtils.isString('')).toBe(true);
27
+ expect(stringUtils.isString('hello')).toBe(true);
28
+ });
29
+
30
+ it('should return true for String objects', () => {
31
+ expect(stringUtils.isString(new String('hello'))).toBe(true);
32
+ });
33
+
34
+ it('should return false for non-strings', () => {
35
+ expect(stringUtils.isString(123)).toBe(false);
36
+ expect(stringUtils.isString({})).toBe(false);
37
+ expect(stringUtils.isString([])).toBe(false);
38
+ expect(stringUtils.isString(null)).toBe(false);
39
+ expect(stringUtils.isString(undefined)).toBe(false);
40
+ });
41
+ });
42
+
43
+ describe('strlen', () => {
44
+ it('should return correct length for trimmed strings', () => {
45
+ expect(stringUtils.strlen('hello')).toBe(5);
46
+ expect(stringUtils.strlen(' hello ')).toBe(5);
47
+ });
48
+
49
+ it('should return 0 for empty strings', () => {
50
+ expect(stringUtils.strlen('')).toBe(0);
51
+ expect(stringUtils.strlen(' ')).toBe(0);
52
+ });
53
+
54
+ it('should return 0 for non-strings', () => {
55
+ expect(stringUtils.strlen(null)).toBe(0);
56
+ expect(stringUtils.strlen(undefined)).toBe(0);
57
+ expect(stringUtils.strlen(123)).toBe(0);
58
+ });
59
+ });
60
+
61
+ describe('isNormalInteger', () => {
62
+ it('should return true for valid integer strings', () => {
63
+ expect(stringUtils.isNormalInteger('0')).toBe(true);
64
+ expect(stringUtils.isNormalInteger('1')).toBe(true);
65
+ expect(stringUtils.isNormalInteger('123')).toBe(true);
66
+ });
67
+
68
+ it('should return false for non-integer strings', () => {
69
+ expect(stringUtils.isNormalInteger('1.5')).toBe(false);
70
+ expect(stringUtils.isNormalInteger('-1')).toBe(false);
71
+ expect(stringUtils.isNormalInteger('abc')).toBe(false);
72
+ expect(stringUtils.isNormalInteger('')).toBe(false);
73
+ });
74
+ });
75
+
76
+ describe('isUpperCase', () => {
77
+ it('should return true for uppercase strings', () => {
78
+ expect(stringUtils.isUpperCase('HELLO')).toBe(true);
79
+ expect(stringUtils.isUpperCase('HELLO WORLD')).toBe(true);
80
+ expect(stringUtils.isUpperCase('HELLO123')).toBe(true);
81
+ expect(stringUtils.isUpperCase('HELLO!')).toBe(true);
82
+ });
83
+
84
+ it('should return false for strings with lowercase characters', () => {
85
+ expect(stringUtils.isUpperCase('Hello')).toBe(false);
86
+ expect(stringUtils.isUpperCase('HELLO world')).toBe(false);
87
+ });
88
+
89
+ it('should handle edge cases', () => {
90
+ expect(stringUtils.isUpperCase('')).toBe(true); // Empty string has no lowercase letters
91
+ expect(stringUtils.isUpperCase('123')).toBe(true); // Numbers only
92
+ expect(stringUtils.isUpperCase('!@#')).toBe(true); // Symbols only
93
+ expect(stringUtils.isUpperCase(undefined)).toBe(false);
94
+ });
95
+ });
96
+
97
+ describe('isAlphaNumeric', () => {
98
+ it('should return true for strings containing only alphanumeric characters', () => {
99
+ expect(stringUtils.isAlphaNumeric('abc123')).toBe(true);
100
+ expect(stringUtils.isAlphaNumeric('ABC')).toBe(true);
101
+ expect(stringUtils.isAlphaNumeric('123')).toBe(true);
102
+ expect(stringUtils.isAlphaNumeric('Test123')).toBe(true);
103
+ expect(stringUtils.isAlphaNumeric('a')).toBe(true);
104
+ expect(stringUtils.isAlphaNumeric('1')).toBe(true);
105
+ });
106
+
107
+ it('should return false for strings containing non-alphanumeric characters', () => {
108
+ expect(stringUtils.isAlphaNumeric('abc 123')).toBe(false); // space
109
+ expect(stringUtils.isAlphaNumeric('abc-123')).toBe(false); // hyphen
110
+ expect(stringUtils.isAlphaNumeric('abc_123')).toBe(false); // underscore
111
+ expect(stringUtils.isAlphaNumeric('abc@123')).toBe(false); // special character
112
+ expect(stringUtils.isAlphaNumeric('abc.123')).toBe(false); // period
113
+ expect(stringUtils.isAlphaNumeric('abc!123')).toBe(false); // exclamation
114
+ expect(stringUtils.isAlphaNumeric('')).toBe(false); // empty string
115
+ });
116
+
117
+ it('should return false for special edge cases', () => {
118
+ expect(stringUtils.isAlphaNumeric('\n')).toBe(false); // newline
119
+ expect(stringUtils.isAlphaNumeric('\t')).toBe(false); // tab
120
+ expect(stringUtils.isAlphaNumeric(' ')).toBe(false); // whitespace
121
+ });
122
+ });
123
+
124
+ describe('getPathFromUrl', () => {
125
+ it('should extract the pathname correctly', () => {
126
+ expect(stringUtils.getPathFromUrl('https://example.com/path/to/resource')).toBe(
127
+ '/path/to/resource'
128
+ );
129
+ expect(stringUtils.getPathFromUrl('https://example.com/')).toBe('/');
130
+ expect(stringUtils.getPathFromUrl('https://example.com/path?query=string')).toBe(
131
+ '/path'
132
+ );
133
+ });
134
+
135
+ it('should handle complex URLs', () => {
136
+ expect(
137
+ stringUtils.getPathFromUrl('https://subdomain.example.com/path/to/resource')
138
+ ).toBe('/path/to/resource');
139
+ expect(stringUtils.getPathFromUrl('http://example.com/path/to/resource#hash')).toBe(
140
+ '/path/to/resource'
141
+ );
142
+ expect(stringUtils.getPathFromUrl('https://example.com:8080/path')).toBe('/path');
143
+ });
144
+
145
+ it('should handle URLs with encoded characters', () => {
146
+ expect(stringUtils.getPathFromUrl('https://example.com/path%20with%20spaces')).toBe(
147
+ '/path%20with%20spaces'
148
+ );
149
+ expect(
150
+ stringUtils.getPathFromUrl('https://example.com/path/with/special%20chars')
151
+ ).toBe('/path/with/special%20chars');
152
+ });
153
+ });
154
+
155
+ describe('getAllText', () => {
156
+ it('should extract text from simple text nodes', () => {
157
+ const div = document.createElement('div');
158
+ div.textContent = 'Hello World';
159
+
160
+ expect(stringUtils.getAllText(div)).toBe('Hello World');
161
+ });
162
+
163
+ it('should extract text from nested elements', () => {
164
+ const div = document.createElement('div');
165
+ const span = document.createElement('span');
166
+ span.textContent = 'Hello';
167
+ const text = document.createTextNode(' World');
168
+
169
+ div.appendChild(span);
170
+ div.appendChild(text);
171
+
172
+ expect(stringUtils.getAllText(div)).toBe('Hello World');
173
+ });
174
+
175
+ it('should extract aria-label attributes', () => {
176
+ const div = document.createElement('div');
177
+ const button = document.createElement('button');
178
+ button.setAttribute('aria-label', 'Close dialog');
179
+ button.textContent = 'X';
180
+
181
+ div.appendChild(button);
182
+
183
+ const result = stringUtils.getAllText(div);
184
+ expect(result).toContain('Close dialog');
185
+ expect(result).toContain('X');
186
+ });
187
+
188
+ it('should extract alt attributes from images', () => {
189
+ const div = document.createElement('div');
190
+ const img = document.createElement('img');
191
+ img.setAttribute('alt', 'Profile picture');
192
+ img.setAttribute('src', 'profile.jpg');
193
+
194
+ div.appendChild(img);
195
+
196
+ expect(stringUtils.getAllText(div)).toBe('Profile picture');
197
+ });
198
+
199
+ it('should handle mixed content with text, aria-labels, and alt text', () => {
200
+ const div = document.createElement('div');
201
+
202
+ // Add some text
203
+ const textNode = document.createTextNode('Welcome ');
204
+ div.appendChild(textNode);
205
+
206
+ // Add element with aria-label
207
+ const button = document.createElement('button');
208
+ button.setAttribute('aria-label', 'Help');
209
+ button.textContent = '?';
210
+ div.appendChild(button);
211
+
212
+ // Add some more text
213
+ const moreText = document.createTextNode(' to our site ');
214
+ div.appendChild(moreText);
215
+
216
+ // Add image with alt text
217
+ const img = document.createElement('img');
218
+ img.setAttribute('alt', 'Company logo');
219
+ div.appendChild(img);
220
+
221
+ const result = stringUtils.getAllText(div);
222
+ expect(result).toContain('Welcome');
223
+ expect(result).toContain('Help');
224
+ expect(result).toContain('?');
225
+ expect(result).toContain('to our site');
226
+ expect(result).toContain('Company logo');
227
+ });
228
+
229
+ it('should handle empty elements', () => {
230
+ const div = document.createElement('div');
231
+ expect(stringUtils.getAllText(div)).toBe('');
232
+ });
233
+
234
+ it('should trim whitespace from text nodes', () => {
235
+ const div = document.createElement('div');
236
+ const textNode = document.createTextNode(' Hello World ');
237
+ div.appendChild(textNode);
238
+
239
+ expect(stringUtils.getAllText(div)).toBe('Hello World');
240
+ });
11
241
 
12
- it('should return true for null or undefined', () => {
13
- expect(stringUtils.isEmpty(null)).toBe(true);
14
- expect(stringUtils.isEmpty(undefined)).toBe(true);
15
- });
242
+ it('should handle elements with only whitespace', () => {
243
+ const div = document.createElement('div');
244
+ const textNode = document.createTextNode(' ');
245
+ div.appendChild(textNode);
16
246
 
17
- it('should return false for non-empty strings', () => {
18
- expect(stringUtils.isEmpty('hello')).toBe(false);
19
- expect(stringUtils.isEmpty(' hello ')).toBe(false);
20
- expect(stringUtils.isEmpty('0')).toBe(false);
21
- });
22
- });
247
+ // Should use textContent.trim() as fallback for empty text
248
+ expect(stringUtils.getAllText(div)).toBe('');
249
+ });
23
250
 
24
- describe('isString', () => {
25
- it('should return true for string literals', () => {
26
- expect(stringUtils.isString('')).toBe(true);
27
- expect(stringUtils.isString('hello')).toBe(true);
28
- });
251
+ it('should handle deeply nested structures', () => {
252
+ const div = document.createElement('div');
253
+ const section = document.createElement('section');
254
+ const article = document.createElement('article');
255
+ const p = document.createElement('p');
29
256
 
30
- it('should return true for String objects', () => {
31
- expect(stringUtils.isString(new String('hello'))).toBe(true);
32
- });
257
+ p.textContent = 'Deep content';
258
+ article.appendChild(p);
259
+ section.appendChild(article);
260
+ div.appendChild(section);
33
261
 
34
- it('should return false for non-strings', () => {
35
- expect(stringUtils.isString(123)).toBe(false);
36
- expect(stringUtils.isString({})).toBe(false);
37
- expect(stringUtils.isString([])).toBe(false);
38
- expect(stringUtils.isString(null)).toBe(false);
39
- expect(stringUtils.isString(undefined)).toBe(false);
40
- });
41
- });
262
+ expect(stringUtils.getAllText(div)).toBe('Deep content');
263
+ });
42
264
 
43
- describe('strlen', () => {
44
- it('should return correct length for trimmed strings', () => {
45
- expect(stringUtils.strlen('hello')).toBe(5);
46
- expect(stringUtils.strlen(' hello ')).toBe(5);
47
- });
265
+ it('should handle images without alt attributes', () => {
266
+ const div = document.createElement('div');
267
+ const img = document.createElement('img');
268
+ img.setAttribute('src', 'image.jpg');
269
+ // No alt attribute
48
270
 
49
- it('should return 0 for empty strings', () => {
50
- expect(stringUtils.strlen('')).toBe(0);
51
- expect(stringUtils.strlen(' ')).toBe(0);
52
- });
271
+ const text = document.createTextNode('Some text');
272
+ div.appendChild(text);
273
+ div.appendChild(img);
53
274
 
54
- it('should return 0 for non-strings', () => {
55
- expect(stringUtils.strlen(null)).toBe(0);
56
- expect(stringUtils.strlen(undefined)).toBe(0);
57
- expect(stringUtils.strlen(123)).toBe(0);
58
- });
59
- });
275
+ expect(stringUtils.getAllText(div)).toBe('Some text');
276
+ });
60
277
 
61
- describe('isNormalInteger', () => {
62
- it('should return true for valid integer strings', () => {
63
- expect(stringUtils.isNormalInteger('0')).toBe(true);
64
- expect(stringUtils.isNormalInteger('1')).toBe(true);
65
- expect(stringUtils.isNormalInteger('123')).toBe(true);
66
- });
278
+ it('should handle elements without aria-label', () => {
279
+ const div = document.createElement('div');
280
+ const button = document.createElement('button');
281
+ button.textContent = 'Click me';
282
+ // No aria-label attribute
67
283
 
68
- it('should return false for non-integer strings', () => {
69
- expect(stringUtils.isNormalInteger('1.5')).toBe(false);
70
- expect(stringUtils.isNormalInteger('-1')).toBe(false);
71
- expect(stringUtils.isNormalInteger('abc')).toBe(false);
72
- expect(stringUtils.isNormalInteger('')).toBe(false);
73
- });
74
- });
75
-
76
- describe('isUpperCase', () => {
77
- it('should return true for uppercase strings', () => {
78
- expect(stringUtils.isUpperCase('HELLO')).toBe(true);
79
- expect(stringUtils.isUpperCase('HELLO WORLD')).toBe(true);
80
- expect(stringUtils.isUpperCase('HELLO123')).toBe(true);
81
- expect(stringUtils.isUpperCase('HELLO!')).toBe(true);
82
- });
284
+ div.appendChild(button);
83
285
 
84
- it('should return false for strings with lowercase characters', () => {
85
- expect(stringUtils.isUpperCase('Hello')).toBe(false);
86
- expect(stringUtils.isUpperCase('HELLO world')).toBe(false);
286
+ expect(stringUtils.getAllText(div)).toBe('Click me');
287
+ });
87
288
  });
88
289
 
89
- it('should handle edge cases', () => {
90
- expect(stringUtils.isUpperCase('')).toBe(true); // Empty string has no lowercase letters
91
- expect(stringUtils.isUpperCase('123')).toBe(true); // Numbers only
92
- expect(stringUtils.isUpperCase('!@#')).toBe(true); // Symbols only
93
- expect(stringUtils.isUpperCase(undefined)).toBe(false);
94
- });
95
- });
96
-
97
- describe('isAlphaNumeric', () => {
98
- it('should return true for strings containing only alphanumeric characters', () => {
99
- expect(stringUtils.isAlphaNumeric('abc123')).toBe(true);
100
- expect(stringUtils.isAlphaNumeric('ABC')).toBe(true);
101
- expect(stringUtils.isAlphaNumeric('123')).toBe(true);
102
- expect(stringUtils.isAlphaNumeric('Test123')).toBe(true);
103
- expect(stringUtils.isAlphaNumeric('a')).toBe(true);
104
- expect(stringUtils.isAlphaNumeric('1')).toBe(true);
105
- });
290
+ describe('hasText', () => {
291
+ it('should return true for elements with text content', () => {
292
+ const div = document.createElement('div');
293
+ div.textContent = 'Hello World';
106
294
 
107
- it('should return false for strings containing non-alphanumeric characters', () => {
108
- expect(stringUtils.isAlphaNumeric('abc 123')).toBe(false); // space
109
- expect(stringUtils.isAlphaNumeric('abc-123')).toBe(false); // hyphen
110
- expect(stringUtils.isAlphaNumeric('abc_123')).toBe(false); // underscore
111
- expect(stringUtils.isAlphaNumeric('abc@123')).toBe(false); // special character
112
- expect(stringUtils.isAlphaNumeric('abc.123')).toBe(false); // period
113
- expect(stringUtils.isAlphaNumeric('abc!123')).toBe(false); // exclamation
114
- expect(stringUtils.isAlphaNumeric('')).toBe(false); // empty string
115
- });
295
+ expect(stringUtils.hasText(div)).toBe(true);
296
+ });
116
297
 
117
- it('should return false for special edge cases', () => {
118
- expect(stringUtils.isAlphaNumeric('\n')).toBe(false); // newline
119
- expect(stringUtils.isAlphaNumeric('\t')).toBe(false); // tab
120
- expect(stringUtils.isAlphaNumeric(' ')).toBe(false); // whitespace
121
- });
122
- });
298
+ it('should return false for empty elements', () => {
299
+ const div = document.createElement('div');
123
300
 
124
- describe('getPathFromUrl', () => {
125
- it('should extract the pathname correctly', () => {
126
- expect(stringUtils.getPathFromUrl('https://example.com/path/to/resource')).toBe('/path/to/resource');
127
- expect(stringUtils.getPathFromUrl('https://example.com/')).toBe('/');
128
- expect(stringUtils.getPathFromUrl('https://example.com/path?query=string')).toBe('/path');
129
- });
301
+ expect(stringUtils.hasText(div)).toBe(false);
302
+ });
130
303
 
131
- it('should handle complex URLs', () => {
132
- expect(stringUtils.getPathFromUrl('https://subdomain.example.com/path/to/resource')).toBe('/path/to/resource');
133
- expect(stringUtils.getPathFromUrl('http://example.com/path/to/resource#hash')).toBe('/path/to/resource');
134
- expect(stringUtils.getPathFromUrl('https://example.com:8080/path')).toBe('/path');
135
- });
304
+ it('should return false for elements with only whitespace', () => {
305
+ const div = document.createElement('div');
306
+ div.textContent = ' \n\t ';
136
307
 
137
- it('should handle URLs with encoded characters', () => {
138
- expect(stringUtils.getPathFromUrl('https://example.com/path%20with%20spaces')).toBe('/path%20with%20spaces');
139
- expect(stringUtils.getPathFromUrl('https://example.com/path/with/special%20chars')).toBe('/path/with/special%20chars');
140
- });
141
- });
142
-
143
- describe('getAllText', () => {
144
- it('should extract text from simple text nodes', () => {
145
- const div = document.createElement('div');
146
- div.textContent = 'Hello World';
147
-
148
- expect(stringUtils.getAllText(div)).toBe('Hello World');
149
- });
308
+ expect(stringUtils.hasText(div)).toBe(false);
309
+ });
150
310
 
151
- it('should extract text from nested elements', () => {
152
- const div = document.createElement('div');
153
- const span = document.createElement('span');
154
- span.textContent = 'Hello';
155
- const text = document.createTextNode(' World');
156
-
157
- div.appendChild(span);
158
- div.appendChild(text);
159
-
160
- expect(stringUtils.getAllText(div)).toBe('Hello World');
161
- });
311
+ it('should return true for elements with aria-label', () => {
312
+ const div = document.createElement('div');
313
+ const button = document.createElement('button');
314
+ button.setAttribute('aria-label', 'Close');
162
315
 
163
- it('should extract aria-label attributes', () => {
164
- const div = document.createElement('div');
165
- const button = document.createElement('button');
166
- button.setAttribute('aria-label', 'Close dialog');
167
- button.textContent = 'X';
168
-
169
- div.appendChild(button);
170
-
171
- const result = stringUtils.getAllText(div);
172
- expect(result).toContain('Close dialog');
173
- expect(result).toContain('X');
174
- });
316
+ div.appendChild(button);
175
317
 
176
- it('should extract alt attributes from images', () => {
177
- const div = document.createElement('div');
178
- const img = document.createElement('img');
179
- img.setAttribute('alt', 'Profile picture');
180
- img.setAttribute('src', 'profile.jpg');
181
-
182
- div.appendChild(img);
183
-
184
- expect(stringUtils.getAllText(div)).toBe('Profile picture');
185
- });
318
+ expect(stringUtils.hasText(div)).toBe(true);
319
+ });
186
320
 
187
- it('should handle mixed content with text, aria-labels, and alt text', () => {
188
- const div = document.createElement('div');
189
-
190
- // Add some text
191
- const textNode = document.createTextNode('Welcome ');
192
- div.appendChild(textNode);
193
-
194
- // Add element with aria-label
195
- const button = document.createElement('button');
196
- button.setAttribute('aria-label', 'Help');
197
- button.textContent = '?';
198
- div.appendChild(button);
199
-
200
- // Add some more text
201
- const moreText = document.createTextNode(' to our site ');
202
- div.appendChild(moreText);
203
-
204
- // Add image with alt text
205
- const img = document.createElement('img');
206
- img.setAttribute('alt', 'Company logo');
207
- div.appendChild(img);
208
-
209
- const result = stringUtils.getAllText(div);
210
- expect(result).toContain('Welcome');
211
- expect(result).toContain('Help');
212
- expect(result).toContain('?');
213
- expect(result).toContain('to our site');
214
- expect(result).toContain('Company logo');
215
- });
321
+ it('should return true for elements with image alt text', () => {
322
+ const div = document.createElement('div');
323
+ const img = document.createElement('img');
324
+ img.setAttribute('alt', 'Profile picture');
216
325
 
217
- it('should handle empty elements', () => {
218
- const div = document.createElement('div');
219
- expect(stringUtils.getAllText(div)).toBe('');
220
- });
326
+ div.appendChild(img);
221
327
 
222
- it('should trim whitespace from text nodes', () => {
223
- const div = document.createElement('div');
224
- const textNode = document.createTextNode(' Hello World ');
225
- div.appendChild(textNode);
226
-
227
- expect(stringUtils.getAllText(div)).toBe('Hello World');
228
- });
328
+ expect(stringUtils.hasText(div)).toBe(true);
329
+ });
229
330
 
230
- it('should handle elements with only whitespace', () => {
231
- const div = document.createElement('div');
232
- const textNode = document.createTextNode(' ');
233
- div.appendChild(textNode);
234
-
235
- // Should use textContent.trim() as fallback for empty text
236
- expect(stringUtils.getAllText(div)).toBe('');
237
- });
331
+ it('should return true for nested elements with text', () => {
332
+ const div = document.createElement('div');
333
+ const span = document.createElement('span');
334
+ span.textContent = 'Nested text';
238
335
 
239
- it('should handle deeply nested structures', () => {
240
- const div = document.createElement('div');
241
- const section = document.createElement('section');
242
- const article = document.createElement('article');
243
- const p = document.createElement('p');
244
-
245
- p.textContent = 'Deep content';
246
- article.appendChild(p);
247
- section.appendChild(article);
248
- div.appendChild(section);
249
-
250
- expect(stringUtils.getAllText(div)).toBe('Deep content');
251
- });
336
+ div.appendChild(span);
252
337
 
253
- it('should handle images without alt attributes', () => {
254
- const div = document.createElement('div');
255
- const img = document.createElement('img');
256
- img.setAttribute('src', 'image.jpg');
257
- // No alt attribute
258
-
259
- const text = document.createTextNode('Some text');
260
- div.appendChild(text);
261
- div.appendChild(img);
262
-
263
- expect(stringUtils.getAllText(div)).toBe('Some text');
264
- });
338
+ expect(stringUtils.hasText(div)).toBe(true);
339
+ });
265
340
 
266
- it('should handle elements without aria-label', () => {
267
- const div = document.createElement('div');
268
- const button = document.createElement('button');
269
- button.textContent = 'Click me';
270
- // No aria-label attribute
271
-
272
- div.appendChild(button);
273
-
274
- expect(stringUtils.getAllText(div)).toBe('Click me');
275
- });
276
- });
277
-
278
- describe('hasText', () => {
279
- it('should return true for elements with text content', () => {
280
- const div = document.createElement('div');
281
- div.textContent = 'Hello World';
282
-
283
- expect(stringUtils.hasText(div)).toBe(true);
284
- });
341
+ it('should return false for elements with empty nested structure', () => {
342
+ const div = document.createElement('div');
343
+ const span = document.createElement('span');
344
+ const p = document.createElement('p');
285
345
 
286
- it('should return false for empty elements', () => {
287
- const div = document.createElement('div');
288
-
289
- expect(stringUtils.hasText(div)).toBe(false);
290
- });
346
+ div.appendChild(span);
347
+ span.appendChild(p);
291
348
 
292
- it('should return false for elements with only whitespace', () => {
293
- const div = document.createElement('div');
294
- div.textContent = ' \n\t ';
295
-
296
- expect(stringUtils.hasText(div)).toBe(false);
297
- });
349
+ expect(stringUtils.hasText(div)).toBe(false);
350
+ });
298
351
 
299
- it('should return true for elements with aria-label', () => {
300
- const div = document.createElement('div');
301
- const button = document.createElement('button');
302
- button.setAttribute('aria-label', 'Close');
303
-
304
- div.appendChild(button);
305
-
306
- expect(stringUtils.hasText(div)).toBe(true);
307
- });
352
+ it('should return true for input elements with a value', () => {
353
+ const input = document.createElement('input');
354
+ input.type = 'text';
355
+ input.value = 'Some input text';
308
356
 
309
- it('should return true for elements with image alt text', () => {
310
- const div = document.createElement('div');
311
- const img = document.createElement('img');
312
- img.setAttribute('alt', 'Profile picture');
313
-
314
- div.appendChild(img);
315
-
316
- expect(stringUtils.hasText(div)).toBe(true);
317
- });
357
+ expect(stringUtils.hasText(input)).toBe(true);
358
+ });
318
359
 
319
- it('should return true for nested elements with text', () => {
320
- const div = document.createElement('div');
321
- const span = document.createElement('span');
322
- span.textContent = 'Nested text';
323
-
324
- div.appendChild(span);
325
-
326
- expect(stringUtils.hasText(div)).toBe(true);
327
- });
360
+ it('should return false for input elements with empty value', () => {
361
+ const input = document.createElement('input');
362
+ input.type = 'text';
363
+ input.value = '';
328
364
 
329
- it('should return false for elements with empty nested structure', () => {
330
- const div = document.createElement('div');
331
- const span = document.createElement('span');
332
- const p = document.createElement('p');
365
+ expect(stringUtils.hasText(input)).toBe(false);
366
+ });
333
367
 
334
- div.appendChild(span);
335
- span.appendChild(p);
368
+ it('should return true for textarea elements with a value', () => {
369
+ const textarea = document.createElement('textarea');
370
+ textarea.value = 'Some textarea text';
336
371
 
337
- expect(stringUtils.hasText(div)).toBe(false);
338
- });
339
- });
372
+ expect(stringUtils.hasText(textarea)).toBe(true);
373
+ });
340
374
 
341
- describe('getAllText edge cases', () => {
342
- it('should handle text nodes with empty nodeValue but non-empty textContent', () => {
343
- const div = document.createElement('div');
344
- const textNode = document.createTextNode(' ');
345
- div.appendChild(textNode);
375
+ it('should return true for select elements with selected option text', () => {
376
+ const select = document.createElement('select');
377
+ const option = document.createElement('option');
378
+ option.textContent = 'Option 1';
379
+ select.appendChild(option);
346
380
 
347
- // This tests the else branch where nodeValue.trim() is empty
348
- const result = stringUtils.getAllText(div);
349
- expect(typeof result).toBe('string');
381
+ expect(stringUtils.hasText(select)).toBe(true);
382
+ });
350
383
  });
351
384
 
352
- it('should handle mixed content with whitespace text nodes', () => {
353
- const div = document.createElement('div');
354
- div.innerHTML = ' <span>Text</span> ';
385
+ describe('getAllText edge cases', () => {
386
+ it('should handle text nodes with empty nodeValue but non-empty textContent', () => {
387
+ const div = document.createElement('div');
388
+ const textNode = document.createTextNode(' ');
389
+ div.appendChild(textNode);
355
390
 
356
- const result = stringUtils.getAllText(div);
357
- expect(result).toContain('Text');
358
- });
391
+ // This tests the else branch where nodeValue.trim() is empty
392
+ const result = stringUtils.getAllText(div);
393
+ expect(typeof result).toBe('string');
394
+ });
359
395
 
360
- it('should handle elements with both aria-label and text content', () => {
361
- const div = document.createElement('div');
362
- const button = document.createElement('button');
363
- button.textContent = 'Visual Text';
364
- button.setAttribute('aria-label', 'Accessible Label');
365
- div.appendChild(button);
396
+ it('should handle mixed content with whitespace text nodes', () => {
397
+ const div = document.createElement('div');
398
+ div.innerHTML = ' <span>Text</span> ';
366
399
 
367
- const result = stringUtils.getAllText(div);
368
- expect(result).toContain('Accessible Label');
369
- expect(result).toContain('Visual Text');
370
- });
400
+ const result = stringUtils.getAllText(div);
401
+ expect(result).toContain('Text');
402
+ });
403
+
404
+ it('should handle elements with both aria-label and text content', () => {
405
+ const div = document.createElement('div');
406
+ const button = document.createElement('button');
407
+ button.textContent = 'Visual Text';
408
+ button.setAttribute('aria-label', 'Accessible Label');
409
+ div.appendChild(button);
410
+
411
+ const result = stringUtils.getAllText(div);
412
+ expect(result).toContain('Accessible Label');
413
+ expect(result).toContain('Visual Text');
414
+ });
371
415
 
372
- it('should handle img without alt attribute', () => {
373
- const div = document.createElement('div');
374
- const img = document.createElement('img');
375
- // No alt attribute
376
- div.appendChild(img);
416
+ it('should handle img without alt attribute', () => {
417
+ const div = document.createElement('div');
418
+ const img = document.createElement('img');
419
+ // No alt attribute
420
+ div.appendChild(img);
377
421
 
378
- const result = stringUtils.getAllText(div);
379
- expect(typeof result).toBe('string');
422
+ const result = stringUtils.getAllText(div);
423
+ expect(typeof result).toBe('string');
424
+ });
380
425
  });
381
- });
382
- });
426
+ });