import { describe, it, expect, vi, afterEach } from 'vitest'; import '@testing-library/jest-dom/vitest'; import { render, cleanup, fireEvent } from '@solidjs/testing-library'; import { Popover } from './popover'; afterEach(cleanup); // createPresence unmounts on a microtask when there is no exit animation (jsdom), // so flush the queue before asserting a closed popover has left the DOM. const tick = () => new Promise((r) => setTimeout(r, 0)); describe('Popover', () => { it('renders the trigger and hides the content until opened', () => { const { getByText, queryByText } = render(() => ( Open menu}>
Panel body
)); expect(getByText('Open menu')).toBeInTheDocument(); expect(queryByText('Panel body')).not.toBeInTheDocument(); }); it('opens on trigger click and calls onOpenChange(true)', () => { const onOpenChange = vi.fn(); const { getByText, queryByText } = render(() => ( Open menu} onOpenChange={onOpenChange}>
Panel body
)); fireEvent.click(getByText('Open menu')); expect(queryByText('Panel body')).toBeInTheDocument(); expect(onOpenChange).toHaveBeenCalledWith(true); }); it('toggles closed on a second trigger click and calls onOpenChange(false)', async () => { const onOpenChange = vi.fn(); const { getByText, queryByText } = render(() => ( Open menu} onOpenChange={onOpenChange}>
Panel body
)); const trigger = getByText('Open menu'); fireEvent.click(trigger); expect(queryByText('Panel body')).toBeInTheDocument(); fireEvent.click(trigger); await tick(); expect(queryByText('Panel body')).not.toBeInTheDocument(); expect(onOpenChange).toHaveBeenLastCalledWith(false); }); it('closes on Escape', async () => { const { getByText, queryByText } = render(() => ( Open menu}>
Panel body
)); fireEvent.click(getByText('Open menu')); expect(queryByText('Panel body')).toBeInTheDocument(); fireEvent.keyDown(document, { key: 'Escape' }); await tick(); expect(queryByText('Panel body')).not.toBeInTheDocument(); }); it('stays open when clicking inside the panel, closes on an outside pointerdown', async () => { const { getByText, queryByText } = render(() => ( Open menu}>
Panel body
)); fireEvent.click(getByText('Open menu')); fireEvent.pointerDown(getByText('Panel body')); expect(queryByText('Panel body')).toBeInTheDocument(); fireEvent.pointerDown(document.body); await tick(); expect(queryByText('Panel body')).not.toBeInTheDocument(); }); it('respects the controlled open prop', () => { const { queryByText } = render(() => ( Open menu}>
Panel body
)); expect(queryByText('Panel body')).toBeInTheDocument(); }); it('does not change its own state when controlled — defers to onOpenChange', () => { const onOpenChange = vi.fn(); const { getByText, queryByText } = render(() => ( Open menu} onOpenChange={onOpenChange}>
Panel body
)); fireEvent.click(getByText('Open menu')); // controlled: stays closed until the parent flips `open` expect(queryByText('Panel body')).not.toBeInTheDocument(); expect(onOpenChange).toHaveBeenCalledWith(true); }); });