test: add ConfirmDialog test file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest'
|
||||||
|
import { render, screen, waitFor } from '@testing-library/react'
|
||||||
|
import userEvent from '@testing-library/user-event'
|
||||||
|
import { ConfirmDialog } from './ConfirmDialog'
|
||||||
|
|
||||||
|
const defaultProps = {
|
||||||
|
open: true,
|
||||||
|
onClose: vi.fn(),
|
||||||
|
onConfirm: vi.fn(),
|
||||||
|
message: 'Delete user "alice"? This cannot be undone.',
|
||||||
|
confirmText: 'alice',
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ConfirmDialog', () => {
|
||||||
|
it('renders title and message when open', () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} />)
|
||||||
|
expect(screen.getByText('Confirm Deletion')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('Delete user "alice"? This cannot be undone.')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not render when closed', () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} open={false} />)
|
||||||
|
expect(screen.queryByText('Confirm Deletion')).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders custom title', () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} title="Remove item" />)
|
||||||
|
expect(screen.getByText('Remove item')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows confirm instruction text', () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} />)
|
||||||
|
expect(screen.getByText(/Type "alice" to confirm/)).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('disables confirm button until text matches', () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} />)
|
||||||
|
expect(screen.getByRole('button', { name: 'Delete' })).toBeDisabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('enables confirm button when text matches', async () => {
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(<ConfirmDialog {...defaultProps} />)
|
||||||
|
await user.type(screen.getByRole('textbox'), 'alice')
|
||||||
|
expect(screen.getByRole('button', { name: 'Delete' })).toBeEnabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls onConfirm when confirm button is clicked after typing', async () => {
|
||||||
|
const onConfirm = vi.fn()
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(<ConfirmDialog {...defaultProps} onConfirm={onConfirm} />)
|
||||||
|
await user.type(screen.getByRole('textbox'), 'alice')
|
||||||
|
await user.click(screen.getByRole('button', { name: 'Delete' }))
|
||||||
|
expect(onConfirm).toHaveBeenCalledOnce()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls onClose when cancel button is clicked', async () => {
|
||||||
|
const onClose = vi.fn()
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(<ConfirmDialog {...defaultProps} onClose={onClose} />)
|
||||||
|
await user.click(screen.getByRole('button', { name: 'Cancel' }))
|
||||||
|
expect(onClose).toHaveBeenCalledOnce()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls onConfirm on Enter when text matches', async () => {
|
||||||
|
const onConfirm = vi.fn()
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(<ConfirmDialog {...defaultProps} onConfirm={onConfirm} />)
|
||||||
|
await user.type(screen.getByRole('textbox'), 'alice')
|
||||||
|
await user.keyboard('{Enter}')
|
||||||
|
expect(onConfirm).toHaveBeenCalledOnce()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not call onConfirm on Enter when text does not match', async () => {
|
||||||
|
const onConfirm = vi.fn()
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(<ConfirmDialog {...defaultProps} onConfirm={onConfirm} />)
|
||||||
|
await user.type(screen.getByRole('textbox'), 'alic')
|
||||||
|
await user.keyboard('{Enter}')
|
||||||
|
expect(onConfirm).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('disables both buttons when loading', async () => {
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(<ConfirmDialog {...defaultProps} loading />)
|
||||||
|
await user.type(screen.getByRole('textbox'), 'alice')
|
||||||
|
const buttons = screen.getAllByRole('button')
|
||||||
|
for (const btn of buttons) {
|
||||||
|
expect(btn).toBeDisabled()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clears input when opened', async () => {
|
||||||
|
const { rerender } = render(<ConfirmDialog {...defaultProps} open={false} />)
|
||||||
|
rerender(<ConfirmDialog {...defaultProps} open={true} />)
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('textbox')).toHaveValue('')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('auto-focuses input on open', async () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} />)
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('textbox')).toHaveFocus()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders custom button labels', () => {
|
||||||
|
render(<ConfirmDialog {...defaultProps} confirmLabel="Remove" cancelLabel="Keep" />)
|
||||||
|
expect(screen.getByRole('button', { name: 'Remove' })).toBeInTheDocument()
|
||||||
|
expect(screen.getByRole('button', { name: 'Keep' })).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user