import {act, cleanup, fireEvent, render, screen} from '@testing-library/react'; import {useState} from 'react'; import {useClick, useFloating, useHover, useInteractions} from '../../src'; import type {UseClickProps} from '../../src/hooks/useClick'; function App({ button = true, typeable = false, initialOpen = false, ...props }: UseClickProps & { button?: boolean; typeable?: boolean; initialOpen?: boolean; }) { const [open, setOpen] = useState(initialOpen); const {refs, context} = useFloating({ open, onOpenChange: setOpen, }); const {getReferenceProps, getFloatingProps} = useInteractions([ useClick(context, props), ]); const Tag = typeable ? 'input' : button ? 'button' : 'div'; return ( <> {open && (
)} ); } describe('default', () => { test('changes `open` state to `true` after click', () => { render(); const button = screen.getByRole('button'); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); fireEvent.click(button); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('changes `open` state to `false` after two clicks', () => { render(); const button = screen.getByRole('button'); fireEvent.click(button); fireEvent.click(button); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); cleanup(); }); }); describe('mousedown `event` prop', () => { test('changes `open` state to `true` after click', () => { render(); const button = screen.getByRole('button'); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); fireEvent.click(button); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('changes `open` state to `false` after two clicks', () => { render(); const button = screen.getByRole('button'); fireEvent.click(button); fireEvent.click(button); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); cleanup(); }); }); describe('`toggle` prop', () => { test('changes `open` state to `true` after click', () => { render(); const button = screen.getByRole('button'); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); fireEvent.click(button); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('`open` state remains `true` after two clicks', () => { render(); const button = screen.getByRole('button'); fireEvent.click(button); fireEvent.click(button); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('`open` state remains `true` after two clicks with `mousedown`', () => { render(); const button = screen.getByRole('button'); fireEvent.click(button); fireEvent.click(button); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('`open` state becomes `false` after clicking when initially open', () => { render(); const button = screen.getByRole('button'); fireEvent.click(button); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); cleanup(); }); }); describe('non-buttons', () => { test('adds Enter keydown', () => { render(); const button = screen.getByTestId('reference'); fireEvent.keyDown(button, {key: 'Enter'}); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('adds Space keyup', () => { render(); const button = screen.getByTestId('reference'); fireEvent.keyDown(button, {key: ' '}); fireEvent.keyUp(button, {key: ' '}); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); test('typeable reference does not receive space key handler', async () => { render(); const button = screen.getByTestId('reference'); fireEvent.keyDown(button, {key: ' '}); fireEvent.keyUp(button, {key: ' '}); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); cleanup(); }); test('typeable reference does receive Enter key handler', async () => { render(); const button = screen.getByTestId('reference'); fireEvent.keyDown(button, {key: 'Enter'}); expect(screen.queryByRole('tooltip')).toBeInTheDocument(); cleanup(); }); }); test('ignores Space keydown on another element then keyup on the button', async () => { render(); await act(async () => {}); const button = screen.getByRole('button'); fireEvent.keyDown(document.body, {key: ' '}); fireEvent.keyUp(button, {key: ' '}); expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); }); test('with useHover does not close on mouseleave after click', async () => { function App() { const [open, setOpen] = useState(false); const {refs, context} = useFloating({ open, onOpenChange: setOpen, }); const {getReferenceProps, getFloatingProps} = useInteractions([ useHover(context), useClick(context), ]); return ( <>