import { useState } from 'react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { render } from 'vitest-browser-react' import { userEvent } from 'vitest/browser' import { showSubmittedData } from '@/lib/show-submitted-data' import { type Task } from '../data/schema' import { TasksMutateDrawer } from './tasks-mutate-drawer' vi.mock('@/lib/show-submitted-data', () => ({ showSubmittedData: vi.fn() })) const MOCK_TASK = { id: 'task-1', title: 'Existing task', status: 'in progress', label: 'feature', priority: 'medium', } as const satisfies Task describe('TasksMutateDrawer', () => { beforeEach(() => vi.clearAllMocks()) it('renders create title and description', async () => { const { getByRole, getByText } = await render( ) const title = getByRole('heading', { level: 2, name: /Create Task/i, }) const desc = getByText(/Add a new task/i) await expect.element(title).toBeInTheDocument() await expect.element(desc).toBeInTheDocument() }) it('renders edit title, description, and prefilled title', async () => { const { getByRole, getByText } = await render( ) const title = getByRole('heading', { level: 2, name: /Update Task/i, }) const desc = getByText(/Update the task/i) const titleInput = getByRole('textbox', { name: /Title/i }) const statusSelect = getByRole('combobox', { name: /Status/i }) const labelRadio = getByRole('radio', { name: MOCK_TASK.label }) const priorityRadio = getByRole('radio', { name: MOCK_TASK.priority }) await expect.element(title).toBeInTheDocument() await expect.element(desc).toBeInTheDocument() await expect.element(titleInput).toHaveValue(MOCK_TASK.title) await expect .element(statusSelect) .toHaveTextContent(new RegExp(MOCK_TASK.status, 'i')) await expect.element(labelRadio).toBeChecked() await expect.element(priorityRadio).toBeChecked() }) it('shows validation messages when submitting an empty form', async () => { const { getByRole, getByText } = await render( ) const saveButton = getByRole('button', { name: /Save changes/i }) await userEvent.click(saveButton) await expect.element(getByText(/Title is required.$/i)).toBeInTheDocument() await expect .element(getByText(/Please select a status.$/i)) .toBeInTheDocument() await expect .element(getByText(/Please select a label.$/i)) .toBeInTheDocument() await expect .element(getByText(/Please choose a priority.$/i)) .toBeInTheDocument() }) it('submits create form and shows submitted data', async () => { const onOpenChange = vi.fn() const { getByRole } = await render( ) const titleInput = getByRole('textbox', { name: /Title/i }) await userEvent.fill(titleInput, 'New task title') const statusSelect = getByRole('combobox', { name: /Status/i }) await userEvent.click(statusSelect) await userEvent.click(getByRole('option', { name: /Todo/i })) await userEvent.click(getByRole('radio', { name: /^Bug$/i })) await userEvent.click(getByRole('radio', { name: /^Low$/i })) const saveButton = getByRole('button', { name: /Save changes/i }) await userEvent.click(saveButton) expect(onOpenChange).toHaveBeenCalledOnce() expect(onOpenChange).toHaveBeenCalledWith(false) expect(showSubmittedData).toHaveBeenCalledOnce() expect(showSubmittedData).toHaveBeenCalledWith({ title: 'New task title', status: 'todo', label: 'bug', priority: 'low', }) }) it('closes when Close is clicked', async () => { const onOpenChange = vi.fn() const { getByRole } = await render( ) const closeButtons = getByRole('dialog') .getByRole('button', { name: /Close/i, }) .all() expect(closeButtons).toHaveLength(2) await userEvent.click(closeButtons[1]) expect(onOpenChange).toHaveBeenCalledOnce() expect(onOpenChange).toHaveBeenCalledWith(false) }) it('resets entered values when the sheet is closed and reopened', async () => { function Harness() { const [open, setOpen] = useState(true) return ( <> ) } const { getByRole } = await render() const titleInput = getByRole('textbox', { name: /Title/i }) await userEvent.fill(titleInput, 'Draft title') await expect.element(titleInput).toHaveValue('Draft title') const statusSelect = getByRole('combobox', { name: /Status/i }) await userEvent.click(statusSelect) await userEvent.click(getByRole('option', { name: /Todo/i })) await expect.element(statusSelect).toHaveTextContent(/Todo/i) const labelRadio = getByRole('radio', { name: /^Documentation$/i }) await userEvent.click(labelRadio) await expect.element(labelRadio).toBeChecked() const priorityRadio = getByRole('radio', { name: /^High$/i }) await userEvent.click(priorityRadio) await expect.element(priorityRadio).toBeChecked() const closeButtons = getByRole('dialog') .getByRole('button', { name: /Close/i, }) .all() await userEvent.click(closeButtons[0]) const reopenButton = getByRole('button', { name: /Reopen/i }) await userEvent.click(reopenButton) await expect.element(titleInput).toHaveValue('') await expect.element(statusSelect).not.toHaveTextContent(/Todo/i) await expect.element(labelRadio).not.toBeChecked() await expect.element(priorityRadio).not.toBeChecked() }) })