From c76ae79d7a273cb2b47132317e4242f656ba65a1 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:01:45 +0100 Subject: [PATCH] test: add ConfirmDialog test file Co-Authored-By: Claude Sonnet 4.6 --- .../ConfirmDialog/ConfirmDialog.test.tsx | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/design-system/composites/ConfirmDialog/ConfirmDialog.test.tsx diff --git a/src/design-system/composites/ConfirmDialog/ConfirmDialog.test.tsx b/src/design-system/composites/ConfirmDialog/ConfirmDialog.test.tsx new file mode 100644 index 0000000..f554d9a --- /dev/null +++ b/src/design-system/composites/ConfirmDialog/ConfirmDialog.test.tsx @@ -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() + expect(screen.getByText('Confirm Deletion')).toBeInTheDocument() + expect(screen.getByText('Delete user "alice"? This cannot be undone.')).toBeInTheDocument() + }) + + it('does not render when closed', () => { + render() + expect(screen.queryByText('Confirm Deletion')).not.toBeInTheDocument() + }) + + it('renders custom title', () => { + render() + expect(screen.getByText('Remove item')).toBeInTheDocument() + }) + + it('shows confirm instruction text', () => { + render() + expect(screen.getByText(/Type "alice" to confirm/)).toBeInTheDocument() + }) + + it('disables confirm button until text matches', () => { + render() + expect(screen.getByRole('button', { name: 'Delete' })).toBeDisabled() + }) + + it('enables confirm button when text matches', async () => { + const user = userEvent.setup() + render() + 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() + 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() + 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() + 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() + 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() + 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() + rerender() + await waitFor(() => { + expect(screen.getByRole('textbox')).toHaveValue('') + }) + }) + + it('auto-focuses input on open', async () => { + render() + await waitFor(() => { + expect(screen.getByRole('textbox')).toHaveFocus() + }) + }) + + it('renders custom button labels', () => { + render() + expect(screen.getByRole('button', { name: 'Remove' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'Keep' })).toBeInTheDocument() + }) +})