@afixt/test-utils 2.1.1 → 2.3.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.
@@ -552,6 +552,26 @@ describe('domUtils', () => {
552
552
  const child = document.getElementById('child');
553
553
  expect(domUtils.isHiddenFromAT(child)).toBe(false);
554
554
  });
555
+
556
+ it('should return true when element has inert attribute', () => {
557
+ document.body.innerHTML = '<div inert><span id="child">Inert child</span></div>';
558
+ const child = document.getElementById('child');
559
+ expect(domUtils.isHiddenFromAT(child)).toBe(true);
560
+ });
561
+
562
+ it('should return true when element itself is inert', () => {
563
+ const el = document.createElement('div');
564
+ el.setAttribute('inert', '');
565
+ document.body.appendChild(el);
566
+ expect(domUtils.isHiddenFromAT(el)).toBe(true);
567
+ });
568
+
569
+ it('should return true when element has content-visibility hidden', () => {
570
+ document.body.innerHTML = '<div id="target">Content</div>';
571
+ const el = document.getElementById('target');
572
+ el.style.contentVisibility = 'hidden';
573
+ expect(domUtils.isHiddenFromAT(el)).toBe(true);
574
+ });
555
575
  });
556
576
 
557
577
  describe('isEffectivelyInteractive', () => {
@@ -1059,4 +1079,36 @@ describe('domUtils', () => {
1059
1079
  expect(domUtils.getHeadingLevel(el)).toBeNull();
1060
1080
  });
1061
1081
  });
1082
+
1083
+ describe('shadow DOM integration', () => {
1084
+ it('isIdReferenced should find label[for] inside a shadow root', () => {
1085
+ const host = document.createElement('div');
1086
+ document.body.appendChild(host);
1087
+ const shadow = host.attachShadow({ mode: 'open' });
1088
+ const label = document.createElement('label');
1089
+ label.setAttribute('for', 'shadow-ref-target');
1090
+ shadow.appendChild(label);
1091
+
1092
+ expect(domUtils.isIdReferenced('shadow-ref-target')).toBe(true);
1093
+ });
1094
+
1095
+ it('getElementsWithDuplicateIds should detect duplicate IDs across shadow roots', () => {
1096
+ // Light DOM element with id="dup"
1097
+ const div1 = document.createElement('div');
1098
+ div1.id = 'dup';
1099
+ document.body.appendChild(div1);
1100
+
1101
+ // Shadow DOM element with same id="dup"
1102
+ const host = document.createElement('div');
1103
+ document.body.appendChild(host);
1104
+ const shadow = host.attachShadow({ mode: 'open' });
1105
+ const div2 = document.createElement('div');
1106
+ div2.id = 'dup';
1107
+ shadow.appendChild(div2);
1108
+
1109
+ const duplicates = domUtils.getElementsWithDuplicateIds();
1110
+ expect(duplicates.length).toBe(1);
1111
+ expect(duplicates[0].id).toBe('dup');
1112
+ });
1113
+ });
1062
1114
  });
@@ -120,6 +120,24 @@ describe('formUtils', () => {
120
120
  expect(formUtils.hasExplicitAccessibleName(el)).toBe(false);
121
121
  });
122
122
 
123
+ it('should return true when aria-labelledby points to sr-only element', () => {
124
+ document.body.innerHTML = `
125
+ <span id="lbl" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)">SR-only Label</span>
126
+ <div id="target" aria-labelledby="lbl"></div>
127
+ `;
128
+ const target = document.getElementById('target');
129
+ expect(formUtils.hasExplicitAccessibleName(target)).toBe(true);
130
+ });
131
+
132
+ it('should return false when aria-labelledby points to aria-hidden="true" element', () => {
133
+ document.body.innerHTML = `
134
+ <span id="lbl" aria-hidden="true">Hidden Label</span>
135
+ <div id="target" aria-labelledby="lbl"></div>
136
+ `;
137
+ const target = document.getElementById('target');
138
+ expect(formUtils.hasExplicitAccessibleName(target)).toBe(false);
139
+ });
140
+
123
141
  it('should handle multiple ids in aria-labelledby', () => {
124
142
  document.body.innerHTML = `
125
143
  <span id="lbl1"></span>
@@ -339,4 +357,25 @@ describe('formUtils', () => {
339
357
  expect(text.trim()).toBe('');
340
358
  });
341
359
  });
360
+
361
+ describe('shadow DOM integration', () => {
362
+ it('hasExplicitAccessibleName should find aria-labelledby target inside shadow root', () => {
363
+ // Create shadow host with label element inside
364
+ const host = document.createElement('div');
365
+ document.body.appendChild(host);
366
+ const shadow = host.attachShadow({ mode: 'open' });
367
+ const labelEl = document.createElement('span');
368
+ labelEl.id = 'shadow-group-label';
369
+ labelEl.textContent = 'Group Name';
370
+ shadow.appendChild(labelEl);
371
+
372
+ // Create an element in light DOM referencing the shadow label
373
+ const group = document.createElement('div');
374
+ group.setAttribute('role', 'radiogroup');
375
+ group.setAttribute('aria-labelledby', 'shadow-group-label');
376
+ document.body.appendChild(group);
377
+
378
+ expect(formUtils.hasExplicitAccessibleName(group)).toBe(true);
379
+ });
380
+ });
342
381
  });
@@ -467,4 +467,87 @@ describe('getAccessibleName', () => {
467
467
  });
468
468
  });
469
469
  });
470
+
471
+ describe('whitespace-only accessible name handling', () => {
472
+ it('should ignore aria-label with only non-breaking spaces and use text content instead', () => {
473
+ document.body.innerHTML = '<button aria-label="\u00A0\u00A0">Click</button>';
474
+ const button = document.querySelector('button');
475
+ // NBSP-only aria-label is treated as empty; falls through to text content
476
+ expect(getAccessibleName(button)).toBe('Click');
477
+ });
478
+
479
+ it('should ignore aria-label with only zero-width spaces and use text content instead', () => {
480
+ document.body.innerHTML = '<button aria-label="\u200B\u200B">Click</button>';
481
+ const button = document.querySelector('button');
482
+ expect(getAccessibleName(button)).toBe('Click');
483
+ });
484
+
485
+ it('should return false when aria-label is NBSP-only and element has no other name source', () => {
486
+ document.body.innerHTML = '<div role="button" aria-label="\u00A0"></div>';
487
+ const div = document.querySelector('[role="button"]');
488
+ expect(getAccessibleName(div)).toBe(false);
489
+ });
490
+ });
491
+
492
+ describe('visibility handling for aria-labelledby referenced elements', () => {
493
+ it('should return accessible name for display:none element referenced by aria-labelledby', () => {
494
+ document.body.innerHTML = `
495
+ <li style="display:none">
496
+ <button id="expand-btn">Expand subnavigation</button>
497
+ </li>
498
+ <ul aria-labelledby="expand-btn">Items</ul>
499
+ `;
500
+ const button = document.getElementById('expand-btn');
501
+ expect(getAccessibleName(button)).toBe('Expand subnavigation');
502
+ });
503
+
504
+ it('should return false for truly hidden element not referenced by aria-labelledby', () => {
505
+ document.body.innerHTML = `
506
+ <div aria-hidden="true">
507
+ <button id="hidden-btn">Hidden button</button>
508
+ </div>
509
+ `;
510
+ const button = document.getElementById('hidden-btn');
511
+ expect(getAccessibleName(button)).toBe(false);
512
+ });
513
+ });
514
+
515
+ describe('shadow DOM integration', () => {
516
+ it('should resolve aria-labelledby referencing an element inside a shadow root', () => {
517
+ // Create a shadow host with the label inside
518
+ const host = document.createElement('div');
519
+ document.body.appendChild(host);
520
+ const shadow = host.attachShadow({ mode: 'open' });
521
+ const labelSpan = document.createElement('span');
522
+ labelSpan.id = 'shadow-label';
523
+ labelSpan.textContent = 'Shadow Label';
524
+ shadow.appendChild(labelSpan);
525
+
526
+ // Create the button in light DOM that references the shadow label
527
+ const button = document.createElement('button');
528
+ button.setAttribute('aria-labelledby', 'shadow-label');
529
+ document.body.appendChild(button);
530
+
531
+ expect(getAccessibleName(button)).toBe('Shadow Label');
532
+ });
533
+
534
+ it('should resolve label[for] inside a shadow root for text inputs', () => {
535
+ // Create a shadow host with the label inside
536
+ const host = document.createElement('div');
537
+ document.body.appendChild(host);
538
+ const shadow = host.attachShadow({ mode: 'open' });
539
+ const label = document.createElement('label');
540
+ label.setAttribute('for', 'shadow-input');
541
+ label.textContent = 'Shadow Input Label';
542
+ shadow.appendChild(label);
543
+
544
+ // Create the input in light DOM
545
+ const input = document.createElement('input');
546
+ input.type = 'text';
547
+ input.id = 'shadow-input';
548
+ document.body.appendChild(input);
549
+
550
+ expect(getAccessibleName(input)).toBe('Shadow Input Label');
551
+ });
552
+ });
470
553
  });
@@ -2,179 +2,251 @@ import { describe, it, expect, beforeEach } from 'vitest';
2
2
  import { getComputedRole, roleMapping } from '../src/getComputedRole.js';
3
3
 
4
4
  describe('getComputedRole', () => {
5
- beforeEach(() => {
6
- document.body.innerHTML = '';
7
- });
8
-
9
- it('should return undefined for null or undefined element', () => {
10
- expect(getComputedRole(null)).toBeUndefined();
11
- expect(getComputedRole(undefined)).toBeUndefined();
12
- });
13
-
14
- it('should return the role attribute value if present', () => {
15
- // Arrange
16
- const element = document.createElement('div');
17
- element.setAttribute('role', 'button');
18
- document.body.appendChild(element);
19
-
20
- // Act
21
- const result = getComputedRole(element);
22
-
23
- // Assert
24
- expect(result).toBe('button');
25
- });
26
-
27
- it('should return the correct role for basic elements with simple string mapping', () => {
28
- // Test cases for elements with simple string mapping
29
- const testCases = [
30
- { tag: 'div', expectedRole: 'group' },
31
- { tag: 'p', expectedRole: 'text' },
32
- { tag: 'ul', expectedRole: 'list' },
33
- { tag: 'h1', expectedRole: 'heading' },
34
- { tag: 'button', expectedRole: 'button' },
35
- { tag: 'nav', expectedRole: 'navigation' },
36
- { tag: 'header', expectedRole: 'banner' },
37
- { tag: 'footer', expectedRole: 'contentinfo' },
38
- { tag: 'main', expectedRole: 'main' }
39
- ];
40
-
41
- testCases.forEach(({ tag, expectedRole }) => {
42
- // Arrange
43
- const element = document.createElement(tag);
44
- document.body.appendChild(element);
45
-
46
- // Act
47
- const result = getComputedRole(element);
48
-
49
- // Assert
50
- expect(result).toBe(expectedRole);
51
- });
52
- });
53
-
54
- it('should handle link elements (a) correctly based on href attribute', () => {
55
- // Arrange
56
- const linkWithHref = document.createElement('a');
57
- linkWithHref.setAttribute('href', 'https://example.com');
58
-
59
- const linkWithoutHref = document.createElement('a');
60
-
61
- document.body.appendChild(linkWithHref);
62
- document.body.appendChild(linkWithoutHref);
63
-
64
- // Act
65
- const withHrefResult = getComputedRole(linkWithHref);
66
- const withoutHrefResult = getComputedRole(linkWithoutHref);
67
-
68
- // Assert
69
- expect(withHrefResult).toBe('link');
70
- expect(withoutHrefResult).toBe('text');
71
- });
72
-
73
- it('should handle image elements based on alt attribute', () => {
74
- // Arrange
75
- const imgWithAlt = document.createElement('img');
76
- imgWithAlt.setAttribute('alt', 'Description of image');
77
-
78
- const imgWithEmptyAlt = document.createElement('img');
79
- imgWithEmptyAlt.setAttribute('alt', '');
80
-
81
- document.body.appendChild(imgWithAlt);
82
- document.body.appendChild(imgWithEmptyAlt);
83
-
84
- // Act
85
- const withAltResult = getComputedRole(imgWithAlt);
86
- const withEmptyAltResult = getComputedRole(imgWithEmptyAlt);
87
-
88
- // Assert
89
- expect(withAltResult).toBe('image');
90
- expect(withEmptyAltResult).toBe('presentation');
91
- });
92
-
93
- it('should handle various input types correctly', () => {
94
- const inputTypes = [
95
- { type: 'button', expectedRole: 'button' },
96
- { type: 'checkbox', expectedRole: 'checkbox' },
97
- { type: 'hidden', expectedRole: 'noRole' },
98
- { type: 'image', expectedRole: 'button' },
99
- { type: 'number', expectedRole: 'spinbutton' },
100
- { type: 'radio', expectedRole: 'radio' },
101
- { type: 'range', expectedRole: 'slider' },
102
- { type: 'reset', expectedRole: 'button' },
103
- { type: 'submit', expectedRole: 'button' },
104
- { type: 'password', expectedRole: 'textbox' },
105
- { type: 'text', expectedRole: 'textbox' },
106
- { type: 'search', expectedRole: 'searchbox' }
107
- ];
108
-
109
- inputTypes.forEach(({ type, expectedRole }) => {
110
- // Arrange
111
- const input = document.createElement('input');
112
- input.setAttribute('type', type);
113
- document.body.appendChild(input);
114
-
115
- // Act
116
- const result = getComputedRole(input);
117
-
118
- // Assert
119
- expect(result).toBe(expectedRole);
120
- });
121
- });
122
-
123
- it('should handle elements with no role mapping', () => {
124
- // Create a custom element that's not in the roleMapping
125
- const customElement = document.createElement('custom-element');
126
- document.body.appendChild(customElement);
127
-
128
- // Act
129
- const result = getComputedRole(customElement);
130
-
131
- // Assert
132
- expect(result).toBeUndefined();
133
- });
134
-
135
- it('should prioritize role attribute over computed role', () => {
136
- // Arrange
137
- const element = document.createElement('button'); // Inherent role is 'button'
138
- element.setAttribute('role', 'menuitem'); // Override with custom role
139
- document.body.appendChild(element);
140
-
141
- // Act
142
- const result = getComputedRole(element);
143
-
144
- // Assert
145
- expect(result).toBe('menuitem'); // Should use the explicit role
146
- });
147
-
148
- it('should handle empty or whitespace role attribute', () => {
149
- // Arrange
150
- const emptyRoleElement = document.createElement('div');
151
- emptyRoleElement.setAttribute('role', '');
152
-
153
- const whitespaceRoleElement = document.createElement('div');
154
- whitespaceRoleElement.setAttribute('role', ' ');
155
-
156
- document.body.appendChild(emptyRoleElement);
157
- document.body.appendChild(whitespaceRoleElement);
158
-
159
- // Act
160
- const emptyResult = getComputedRole(emptyRoleElement);
161
- const whitespaceResult = getComputedRole(whitespaceRoleElement);
162
-
163
- // Assert
164
- // The implementation returns the fallback 'group' role for div when the role attribute is empty
165
- expect(emptyResult).toBe('group');
166
- expect(whitespaceResult).toBe(' '); // Whitespace is preserved
167
- });
168
-
169
- it('should handle case insensitivity for tag names', () => {
170
- // Arrange - create element with uppercase tag
171
- const upperElement = document.createElement('DIV');
172
- document.body.appendChild(upperElement);
173
-
174
- // Act
175
- const result = getComputedRole(upperElement);
176
-
177
- // Assert
178
- expect(result).toBe('group'); // Should match 'div' in the mapping
179
- });
180
- });
5
+ beforeEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ it('should return undefined for null or undefined element', () => {
10
+ expect(getComputedRole(null)).toBeUndefined();
11
+ expect(getComputedRole(undefined)).toBeUndefined();
12
+ });
13
+
14
+ it('should return the role attribute value if present', () => {
15
+ // Arrange
16
+ const element = document.createElement('div');
17
+ element.setAttribute('role', 'button');
18
+ document.body.appendChild(element);
19
+
20
+ // Act
21
+ const result = getComputedRole(element);
22
+
23
+ // Assert
24
+ expect(result).toBe('button');
25
+ });
26
+
27
+ it('should return the correct role for basic elements with simple string mapping', () => {
28
+ // Test cases for elements with simple string mapping
29
+ const testCases = [
30
+ { tag: 'div', expectedRole: 'group' },
31
+ { tag: 'p', expectedRole: 'text' },
32
+ { tag: 'ul', expectedRole: 'list' },
33
+ { tag: 'h1', expectedRole: 'heading' },
34
+ { tag: 'button', expectedRole: 'button' },
35
+ { tag: 'nav', expectedRole: 'navigation' },
36
+ { tag: 'header', expectedRole: 'banner' },
37
+ { tag: 'footer', expectedRole: 'contentinfo' },
38
+ { tag: 'main', expectedRole: 'main' },
39
+ ];
40
+
41
+ testCases.forEach(({ tag, expectedRole }) => {
42
+ // Arrange
43
+ const element = document.createElement(tag);
44
+ document.body.appendChild(element);
45
+
46
+ // Act
47
+ const result = getComputedRole(element);
48
+
49
+ // Assert
50
+ expect(result).toBe(expectedRole);
51
+ });
52
+ });
53
+
54
+ it('should handle link elements (a) correctly based on href attribute', () => {
55
+ // Arrange
56
+ const linkWithHref = document.createElement('a');
57
+ linkWithHref.setAttribute('href', 'https://example.com');
58
+
59
+ const linkWithoutHref = document.createElement('a');
60
+
61
+ document.body.appendChild(linkWithHref);
62
+ document.body.appendChild(linkWithoutHref);
63
+
64
+ // Act
65
+ const withHrefResult = getComputedRole(linkWithHref);
66
+ const withoutHrefResult = getComputedRole(linkWithoutHref);
67
+
68
+ // Assert
69
+ expect(withHrefResult).toBe('link');
70
+ expect(withoutHrefResult).toBe('text');
71
+ });
72
+
73
+ it('should handle image elements based on alt attribute', () => {
74
+ // Arrange
75
+ const imgWithAlt = document.createElement('img');
76
+ imgWithAlt.setAttribute('alt', 'Description of image');
77
+
78
+ const imgWithEmptyAlt = document.createElement('img');
79
+ imgWithEmptyAlt.setAttribute('alt', '');
80
+
81
+ document.body.appendChild(imgWithAlt);
82
+ document.body.appendChild(imgWithEmptyAlt);
83
+
84
+ // Act
85
+ const withAltResult = getComputedRole(imgWithAlt);
86
+ const withEmptyAltResult = getComputedRole(imgWithEmptyAlt);
87
+
88
+ // Assert
89
+ expect(withAltResult).toBe('image');
90
+ expect(withEmptyAltResult).toBe('presentation');
91
+ });
92
+
93
+ it('should handle various input types correctly', () => {
94
+ const inputTypes = [
95
+ { type: 'button', expectedRole: 'button' },
96
+ { type: 'checkbox', expectedRole: 'checkbox' },
97
+ { type: 'hidden', expectedRole: 'noRole' },
98
+ { type: 'image', expectedRole: 'button' },
99
+ { type: 'number', expectedRole: 'spinbutton' },
100
+ { type: 'radio', expectedRole: 'radio' },
101
+ { type: 'range', expectedRole: 'slider' },
102
+ { type: 'reset', expectedRole: 'button' },
103
+ { type: 'submit', expectedRole: 'button' },
104
+ { type: 'password', expectedRole: 'textbox' },
105
+ { type: 'text', expectedRole: 'textbox' },
106
+ { type: 'search', expectedRole: 'searchbox' },
107
+ ];
108
+
109
+ inputTypes.forEach(({ type, expectedRole }) => {
110
+ // Arrange
111
+ const input = document.createElement('input');
112
+ input.setAttribute('type', type);
113
+ document.body.appendChild(input);
114
+
115
+ // Act
116
+ const result = getComputedRole(input);
117
+
118
+ // Assert
119
+ expect(result).toBe(expectedRole);
120
+ });
121
+ });
122
+
123
+ it('should handle elements with no role mapping', () => {
124
+ // Create a custom element that's not in the roleMapping
125
+ const customElement = document.createElement('custom-element');
126
+ document.body.appendChild(customElement);
127
+
128
+ // Act
129
+ const result = getComputedRole(customElement);
130
+
131
+ // Assert
132
+ expect(result).toBeUndefined();
133
+ });
134
+
135
+ it('should prioritize role attribute over computed role', () => {
136
+ // Arrange
137
+ const element = document.createElement('button'); // Inherent role is 'button'
138
+ element.setAttribute('role', 'menuitem'); // Override with custom role
139
+ document.body.appendChild(element);
140
+
141
+ // Act
142
+ const result = getComputedRole(element);
143
+
144
+ // Assert
145
+ expect(result).toBe('menuitem'); // Should use the explicit role
146
+ });
147
+
148
+ it('should handle empty or whitespace role attribute', () => {
149
+ // Arrange
150
+ const emptyRoleElement = document.createElement('div');
151
+ emptyRoleElement.setAttribute('role', '');
152
+
153
+ const whitespaceRoleElement = document.createElement('div');
154
+ whitespaceRoleElement.setAttribute('role', ' ');
155
+
156
+ document.body.appendChild(emptyRoleElement);
157
+ document.body.appendChild(whitespaceRoleElement);
158
+
159
+ // Act
160
+ const emptyResult = getComputedRole(emptyRoleElement);
161
+ const whitespaceResult = getComputedRole(whitespaceRoleElement);
162
+
163
+ // Assert
164
+ // The implementation returns the fallback 'group' role for div when the role attribute is empty
165
+ expect(emptyResult).toBe('group');
166
+ expect(whitespaceResult).toBe(' '); // Whitespace is preserved
167
+ });
168
+
169
+ it('should return gridcell for td inside role="grid"', () => {
170
+ document.body.innerHTML = `
171
+ <table role="grid">
172
+ <tr><td id="target">Cell</td></tr>
173
+ </table>
174
+ `;
175
+ const td = document.getElementById('target');
176
+ expect(getComputedRole(td)).toBe('gridcell');
177
+ });
178
+
179
+ it('should return cell for td inside regular table', () => {
180
+ document.body.innerHTML = `
181
+ <table>
182
+ <tr><td id="target">Cell</td></tr>
183
+ </table>
184
+ `;
185
+ const td = document.getElementById('target');
186
+ expect(getComputedRole(td)).toBe('cell');
187
+ });
188
+
189
+ it('should return gridcell for td inside role="treegrid"', () => {
190
+ document.body.innerHTML = `
191
+ <table role="treegrid">
192
+ <tr><td id="target">Cell</td></tr>
193
+ </table>
194
+ `;
195
+ const td = document.getElementById('target');
196
+ expect(getComputedRole(td)).toBe('gridcell');
197
+ });
198
+
199
+ it('should return generic for header inside article', () => {
200
+ document.body.innerHTML = `
201
+ <article>
202
+ <header id="target">Article Header</header>
203
+ </article>
204
+ `;
205
+ const header = document.getElementById('target');
206
+ expect(getComputedRole(header)).toBe('generic');
207
+ });
208
+
209
+ it('should return generic for header inside section', () => {
210
+ document.body.innerHTML = `
211
+ <section>
212
+ <header id="target">Section Header</header>
213
+ </section>
214
+ `;
215
+ const header = document.getElementById('target');
216
+ expect(getComputedRole(header)).toBe('generic');
217
+ });
218
+
219
+ it('should return banner for header that is direct child of body', () => {
220
+ document.body.innerHTML = '<header id="target">Page Header</header>';
221
+ const header = document.getElementById('target');
222
+ expect(getComputedRole(header)).toBe('banner');
223
+ });
224
+
225
+ it('should return generic for footer inside article', () => {
226
+ document.body.innerHTML = `
227
+ <article>
228
+ <footer id="target">Article Footer</footer>
229
+ </article>
230
+ `;
231
+ const footer = document.getElementById('target');
232
+ expect(getComputedRole(footer)).toBe('generic');
233
+ });
234
+
235
+ it('should return contentinfo for footer that is direct child of body', () => {
236
+ document.body.innerHTML = '<footer id="target">Page Footer</footer>';
237
+ const footer = document.getElementById('target');
238
+ expect(getComputedRole(footer)).toBe('contentinfo');
239
+ });
240
+
241
+ it('should handle case insensitivity for tag names', () => {
242
+ // Arrange - create element with uppercase tag
243
+ const upperElement = document.createElement('DIV');
244
+ document.body.appendChild(upperElement);
245
+
246
+ // Act
247
+ const result = getComputedRole(upperElement);
248
+
249
+ // Assert
250
+ expect(result).toBe('group'); // Should match 'div' in the mapping
251
+ });
252
+ });