// @vitest-environment jsdom import { describe, it, expect, vi, afterEach } from 'vitest'; import { render, screen, fireEvent, cleanup } from '@testing-library/react'; import Modal from '../../components/ui/Modal'; describe('Modal', () => { afterEach(() => cleanup()); it('renders nothing when open is false', () => { const { container } = render( {}} title="Test">

body

); expect(container.querySelector('[role="dialog"]')).toBeNull(); }); it('renders dialog with correct ARIA shape when open', () => { render( {}} title="My Title" description="My description" >

body

); const dialog = screen.getByRole('dialog'); expect(dialog.getAttribute('aria-modal')).toBe('true'); expect(dialog.getAttribute('aria-labelledby')).toBeTruthy(); expect(dialog.getAttribute('aria-describedby')).toBeTruthy(); expect(screen.getByText('My Title')).toBeTruthy(); expect(screen.getByText('My description')).toBeTruthy(); }); it('omits aria-describedby when no description is provided', () => { render( {}} title="t">

b

); const dialog = screen.getByRole('dialog'); expect(dialog.getAttribute('aria-describedby')).toBeNull(); }); it('calls onClose on ESC keydown', () => { const onClose = vi.fn(); render(

b

); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).toHaveBeenCalledTimes(1); }); it('does NOT call onClose on ESC when closeOnEsc is false', () => { const onClose = vi.fn(); render(

b

); fireEvent.keyDown(document, { key: 'Escape' }); expect(onClose).not.toHaveBeenCalled(); }); it('calls onClose on backdrop click', () => { const onClose = vi.fn(); render(

b

); fireEvent.click(screen.getByRole('dialog')); expect(onClose).toHaveBeenCalledTimes(1); }); it('does NOT call onClose on backdrop click when closeOnBackdrop is false', () => { const onClose = vi.fn(); render(

b

); fireEvent.click(screen.getByRole('dialog')); expect(onClose).not.toHaveBeenCalled(); }); it('renders a built-in close button with aria-label="Close" that triggers onClose', () => { const onClose = vi.fn(); render(

b

); const closeBtn = screen.getByRole('button', { name: /close/i }); fireEvent.click(closeBtn); expect(onClose).toHaveBeenCalledTimes(1); }); it('hides the built-in close button when hideCloseButton is true', () => { render( {}} title="t" hideCloseButton>

b

); expect( screen.queryByRole('button', { name: /close/i }) ).toBeNull(); }); it('locks body-scroll when open and restores on close', () => { const { rerender } = render( {}} title="t">

b

); expect(document.body.style.overflow).toBe('hidden'); rerender( {}} title="t">

b

); expect(document.body.style.overflow).toBe(''); }); });