import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useState } from 'react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import Modal from '@/components/modals/Modal'
function mockMatchMedia(matches: boolean) {
Object.defineProperty(window, 'matchMedia', {
writable: true,
configurable: true,
value: vi.fn().mockImplementation((query: string) => ({
matches: matches && query === '(max-width: 768px)',
media: query,
onchange: null,
addListener: () => {},
removeListener: () => {},
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => false,
})),
})
}
afterEach(cleanup)
beforeEach(() => {
mockMatchMedia(false)
})
function ModalHarness() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
>
)
}
describe('Modal', () => {
it('contains focus, closes with Escape, and restores focus to its trigger', async () => {
render()
const trigger = screen.getByRole('button', { name: 'باز کردن' })
trigger.focus()
fireEvent.click(trigger)
const dialog = await screen.findByRole('dialog', { name: 'ویرایش' })
await waitFor(() => expect(dialog).toContainElement(document.activeElement as HTMLElement))
trigger.focus()
await waitFor(() => expect(dialog).toContainElement(document.activeElement as HTMLElement))
fireEvent.keyDown(document.activeElement as HTMLElement, { key: 'Escape' })
await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument())
await waitFor(() => expect(trigger).toHaveFocus())
})
it('opens as a bottom sheet on mobile by default', async () => {
mockMatchMedia(true)
render()
fireEvent.click(screen.getByRole('button', { name: 'باز کردن' }))
const dialog = await screen.findByRole('dialog', { name: 'ویرایش' })
expect(dialog.className).toContain('mt-auto')
expect(dialog.className).toContain('rounded-b-none')
expect(dialog.className).toContain('max-h-full')
expect(dialog.className).not.toContain('--keyboard-inset')
})
})