Skip to content

Commit 40a575d

Browse files
committed
Increase test coverage
1 parent a06a26b commit 40a575d

File tree

6 files changed

+124
-63
lines changed

6 files changed

+124
-63
lines changed

docusaurus/pages/shadow-dom/useMultipleCombobox.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@ import {ReactShadowRoot} from '../../../test/react-shadow'
55

66
export default function MultipleComboboxShadow() {
77
return (
8-
<div data-testid="shadow-root">
9-
<ReactShadowRoot>
10-
<h2>Shadow DOM</h2>
11-
<DropdownMultipleCombobox />
12-
</ReactShadowRoot>
8+
<div>
9+
<div>
10+
<button>Button before shadow root</button>
11+
</div>
12+
<h2>Shadow DOM</h2>
13+
<div data-testid="shadow-root">
14+
<ReactShadowRoot>
15+
<DropdownMultipleCombobox />
16+
</ReactShadowRoot>
17+
</div>
18+
<div>
19+
<button>Button after shadow root</button>
20+
</div>
1321
</div>
1422
)
1523
}

docusaurus/pages/shadow-dom/useSelect.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import DropdownSelect from '../useSelect'
44
import {ReactShadowRoot} from '../../../test/react-shadow'
55

66
export default function DropdownSelectShadow() {
7-
return <ReactShadowRoot>
8-
<DropdownSelect />
9-
</ReactShadowRoot>
7+
return (
8+
<ReactShadowRoot>
9+
<DropdownSelect />
10+
</ReactShadowRoot>
11+
)
1012
}

src/__tests__/.eslintrc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"react/prop-types": "off",
66
"react/display-name": "off",
77
"react/no-deprecated": "off",
8-
"no-console": "off"
9-
}
8+
"no-console": "off",
9+
"no-unused-vars": "off",
10+
},
1011
}

src/__tests__/downshift.shadow-root.js

Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,32 @@ import DropdownCombobox, {colors} from '../../test/useCombobox.test'
77
import DropdownMultipleSelect from '../../test/useMultipleSelect.test'
88
import {ReactShadowRoot} from '../../test/react-shadow'
99

10-
1110
function _queryAllByRoleDeep(container, ...rest) {
12-
// eslint-disable-next-line testing-library/prefer-screen-queries
13-
const result = queryAllByRole(container, ...rest) // replace here with different queryAll* variants.
14-
for (const element of container.querySelectorAll('*')) {
15-
if (element.shadowRoot) {
16-
result.push(..._queryAllByRoleDeep(element.shadowRoot, ...rest))
17-
}
11+
// eslint-disable-next-line testing-library/prefer-screen-queries
12+
const result = queryAllByRole(container, ...rest) // replace here with different queryAll* variants.
13+
for (const element of container.querySelectorAll('*')) {
14+
if (element.shadowRoot) {
15+
result.push(..._queryAllByRoleDeep(element.shadowRoot, ...rest))
1816
}
19-
20-
return result
2117
}
22-
23-
// eslint-disable-next-line no-unused-vars
24-
const [_queryByRoleDeep, _getAllByRoleDeep, _getByRoleDeep, _findAllByRoleDeep, _findByRoleDeep] = buildQueries(
25-
_queryAllByRoleDeep,
26-
(_, role) => `Found multiple elements with the role ${role}`,
27-
(_, role) => `Unable to find an element with the role ${role}`
28-
)
2918

30-
const getAllByRoleDeep = _getAllByRoleDeep.bind(null, document.body)
31-
const getByRoleDeep = _getByRoleDeep.bind(null, document.body)
19+
return result
20+
}
3221

22+
const [
23+
_queryByRoleDeep,
24+
_getAllByRoleDeep,
25+
_getByRoleDeep,
26+
_findAllByRoleDeep,
27+
_findByRoleDeep,
28+
] = buildQueries(
29+
_queryAllByRoleDeep,
30+
(_, role) => `Found multiple elements with the role ${role}`,
31+
(_, role) => `Unable to find an element with the role ${role}`,
32+
)
33+
34+
const getAllByRoleDeep = _getAllByRoleDeep.bind(null, document.body)
35+
const getByRoleDeep = _getByRoleDeep.bind(null, document.body)
3336

3437
const Wrapper = ({children}) => {
3538
return <ReactShadowRoot>{children}</ReactShadowRoot>
@@ -65,37 +68,37 @@ test('DropdownSelect works correctly in shadow DOM', async () => {
6568

6669
// Verify shadow root exists
6770
expect(container.shadowRoot).toBeDefined()
68-
71+
6972
// Get elements within the shadow root
7073
const toggleButton = getByRoleDeep('combobox')
7174
const menu = getByRoleDeep('listbox')
7275
expect(toggleButton).toBeInTheDocument()
7376
expect(menu).toBeInTheDocument()
74-
77+
7578
// Initially menu should be closed
7679
expect(toggleButton).toHaveAttribute('aria-expanded', 'false')
77-
80+
7881
// Open the dropdown
7982
await user.click(toggleButton)
80-
83+
8184
// Menu should now be open
8285
expect(toggleButton).toHaveAttribute('aria-expanded', 'true')
83-
86+
8487
// Select an item
8588
const blackOption = getByRoleDeep('option', {name: 'Black'})
8689
await user.click(blackOption)
87-
90+
8891
// Menu should close and selected item should appear in button
8992
expect(toggleButton).toHaveAttribute('aria-expanded', 'false')
9093
expect(toggleButton).toHaveTextContent('Black')
91-
94+
9295
// Open it again
9396
await user.click(toggleButton)
9497
expect(toggleButton).toHaveAttribute('aria-expanded', 'true')
95-
98+
9699
// Click outside (this tests our targetWithinDownshift with composedPath)
97100
await user.click(document.body)
98-
101+
99102
// Menu should close
100103
expect(toggleButton).toHaveAttribute('aria-expanded', 'false')
101104
})
@@ -106,65 +109,53 @@ test('DropdownCombobox works correctly in shadow DOM', async () => {
106109

107110
// Verify shadow root exists
108111
expect(container.shadowRoot).toBeDefined()
109-
112+
110113
// Get elements within the shadow root
111114
const input = getByRoleDeep('combobox')
112115
const toggleButton = getByRoleDeep('button', {name: 'toggle menu'})
113116
const clearButton = getByRoleDeep('button', {name: 'clear'})
114117
const menu = getByRoleDeep('listbox')
115-
118+
116119
expect(input).toBeInTheDocument()
117120
expect(toggleButton).toBeInTheDocument()
118121
expect(clearButton).toBeInTheDocument()
119122
expect(menu).toBeInTheDocument()
120-
123+
121124
// Initially menu should be closed
122125
expect(input).toHaveAttribute('aria-expanded', 'false')
123126
expect(toggleButton).toHaveAttribute('aria-expanded', 'false')
124-
127+
125128
// Open the dropdown
126129
await user.click(toggleButton)
127-
130+
128131
// Menu should now be open
129132
expect(input).toHaveAttribute('aria-expanded', 'true')
130-
133+
131134
// All colors should initially be visible
132135
const items = getAllByRoleDeep('option')
133136
expect(items).toHaveLength(colors.length)
134-
135-
// // Type in the input to filter items
136-
// await user.click(input)
137-
// input.focus()
138-
// expect(input).toHaveFocus()
139-
// await user.type(input, 'bl')
140-
141-
// // Only Black and Blue should be visible
142-
// items = getAllByRoleDeep('option')
143-
// await waitFor(() => expect(items).toHaveLength(2))
144-
// expect(items[0]).toHaveTextContent('Black')
145-
// expect(items[1]).toHaveTextContent('Blue')
146-
137+
147138
// Select an item
148139
await user.click(items[0])
149-
140+
150141
// Menu should close and input should have selected value
151142
expect(input).toHaveAttribute('aria-expanded', 'false')
152143
expect(toggleButton).toHaveAttribute('aria-expanded', 'false')
153144
expect(input).toHaveValue('Black')
154-
145+
155146
// Clear the selection
156147
await user.click(clearButton)
157-
148+
158149
// Input should be empty
159150
expect(input).toHaveValue('')
160-
151+
161152
// Open it again
162153
await user.click(toggleButton)
163154
expect(input).toHaveAttribute('aria-expanded', 'true')
164-
155+
165156
// Click outside to close
166157
await user.click(document.body)
167-
158+
168159
// Menu should close
169160
expect(input).toHaveAttribute('aria-expanded', 'false')
170161
})
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {targetWithinDownshift} from '../utils'
2+
3+
test('returns false if environment is not defined', () => {
4+
expect(targetWithinDownshift(null, [], null)).toBe(false)
5+
})
6+
7+
test('returns false if the target is not within the downshift', () => {
8+
const downshift = document.createElement('div')
9+
downshift.innerHTML = '<div id="target"></div>'
10+
expect(targetWithinDownshift(null, [downshift], window)).toBe(false)
11+
})
12+
13+
test('correctly identifies active elements nested in shadow DOM', () => {
14+
// Create a host element for the shadow DOM
15+
const hostElement = document.createElement('div')
16+
document.body.appendChild(hostElement)
17+
18+
// Attach a shadow root to the host element
19+
const shadowRoot = hostElement.attachShadow({mode: 'open'})
20+
21+
// Create an element inside the shadow root
22+
const innerElement = document.createElement('button')
23+
innerElement.setAttribute('data-testid', 'inner-button')
24+
shadowRoot.appendChild(innerElement)
25+
26+
// Create another nested level with another shadow root
27+
const nestedHost = document.createElement('div')
28+
shadowRoot.appendChild(nestedHost)
29+
30+
const nestedShadowRoot = nestedHost.attachShadow({mode: 'open'})
31+
32+
const deepActiveElement = document.createElement('button')
33+
34+
// Create some downshift elements
35+
const downshiftElement = document.createElement('div')
36+
nestedShadowRoot.appendChild(downshiftElement)
37+
downshiftElement.appendChild(deepActiveElement)
38+
39+
// Focus the deep element to make it the active element
40+
deepActiveElement.focus()
41+
42+
expect(hostElement.shadowRoot).toBe(shadowRoot)
43+
expect(nestedHost.shadowRoot).toBe(nestedShadowRoot)
44+
expect(nestedShadowRoot.activeElement).toBe(deepActiveElement)
45+
46+
// Test the function with the active element in the shadow DOM
47+
expect(
48+
targetWithinDownshift(deepActiveElement, [downshiftElement], window, true),
49+
).toBe(true)
50+
51+
// Test with a non-related element
52+
const unrelatedElement = document.createElement('div')
53+
expect(
54+
targetWithinDownshift(unrelatedElement, [downshiftElement], window, true),
55+
).toBe(true) // Should still be true because of activeElement check
56+
57+
// Cleanup
58+
document.body.removeChild(hostElement)
59+
})

src/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ function getNonDisabledIndex(
417417
* @param {HTMLElement[]} downshiftElements The elements that form downshift (list, toggle button etc).
418418
* @param {Window} environment The window context where downshift renders.
419419
* @param {boolean} checkActiveElement Whether to also check activeElement.
420-
* @param {boolean} composedPath Whether to check the composed path.
420+
* @param {EventTarget[]} composedPath The composed path of the event.
421421
*
422422
* @returns {boolean} Whether or not the target is within downshift elements.
423423
*/

0 commit comments

Comments
 (0)