Dropdown component items can't be interacted with in jsdom env
Ziinc opened this issue · comments
Bug report
Seems like the radix implementation places the dropdown dom node at the bottom of the body (after scripts), which is out of the container dom node that the dropdown is rendered in.
I think this interferes with the way react-testing-library renders components in jsdom, as the container dom node for component does not seem to show the dropdown options showing screen.debug()
, which shows the entire document's
For example, this is the output of the rendered dropdown after clicking on the Dropdown labelled "Templates"
<body>
<div>
<div
class="sbui-loading"
>
<div
class="sbui-loading-content"
>
<div
class="
border border-panel-border-light dark:border-panel-border-dark
rounded mb-8 undefined"
>
<div
class="
bg-panel-header-light dark:bg-panel-header-dark
border-b border-panel-border-interior-light dark:border-panel-border-interior-dark"
>
<div
class="px-6 py-4 flex items-center"
>
<div
class="flex items-center justify-between w-full"
>
<div
class="flex flex-row gap-x-4"
>
<button
aria-haspopup="menu"
class="sbui-dropdown__trigger"
data-state="closed"
id="radix-id-4651021723-1"
type="button"
>
<span
class="sbui-btn-container"
>
<button
class="sbui-btn sbui-btn-secondary sbui-btn-container--shadow sbui-btn--tiny sbui-btn--text-align-center"
>
<span>
Templates
</span>
</button>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
This blocks downstream ui testing.
Example test case:
test('templates', async () => {
const mockFn = jest.fn()
render(<Dropdown overlay={[
<Dropdown.Item onClick={mockFn}>Some option</Dropdown.Item>
]}>
<Button>Templates</Button>
</Dropdown)
// dropdown interaction
userEvent.click(screen.getByText("Templates"))
await waitFor(() => screen.getByText("Some option"))
userEvent.click(screen.getByText("Some option"))
expect(mockFn).toBeCalled()
})
On a related note, the radix implementation also gives a validateDOMNesting warning when rendered in jsdom env
console.error
Warning: validateDOMNesting(...): <button> cannot appear as a descendant of <button>.
at button
at RenderedButton (/Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/components/Button/Button2.js:96:5)
at span
at /Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/components/Button/Button2.js:14:5
at button
at /Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/node_modules/@radix-ui/react-primitive/dist/index.module.js:31:161
at SlotClone (/Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/node_modules/@radix-ui/react-slot/dist/index.module.js:31:598)
at Slot (/Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/node_modules/@radix-ui/react-slot/dist/index.module.js:31:77)
at /Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/node_modules/@radix-ui/react-primitive/dist/index.module.js:31:161
at /Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/node_modules/@radix-ui/react-popper/dist/index.module.js:37:280
at /Users/tzeyiing/supabase/supabase/studio/node_modules/@supabase/ui/dist/cjs/node_modul
Not sure this is an issue, its by design that radix mounts the node at the bottom of body.
all the overlays behave like this by the way. all overlays are inserted at the bottom of body so they are rendered correctly on top of each other. I'm not sure if it's the 'best solution', but we're just following best practise from Radix really.
Seems like its a known issue with the radix library.
radix-ui/primitives#856
Doesn't look like an issue with the overlay after reading the issue, seems like dropdown isn't picking up the event at all. i'll probably monkey patch the userEvent library on test setup then. Seems very hacky tho.