103 lines
3.5 KiB
TypeScript
103 lines
3.5 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
import { render, screen, fireEvent, waitFor, cleanup, within } from '@testing-library/react';
|
|
import DeleteConfirmModal from '@/components/DeleteConfirmModal';
|
|
|
|
describe('DeleteConfirmModal', () => {
|
|
const defaultProps = {
|
|
open: true,
|
|
ingredientName: 'Organic Butter',
|
|
onClose: vi.fn(),
|
|
onConfirm: vi.fn(() => Promise.resolve()),
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
});
|
|
|
|
it('renders nothing when open=false', () => {
|
|
const { container } = render(
|
|
<DeleteConfirmModal {...defaultProps} open={false} />
|
|
);
|
|
expect(container.innerHTML).toBe('');
|
|
});
|
|
|
|
it('shows ingredient name in confirmation text', () => {
|
|
const { container } = render(<DeleteConfirmModal {...defaultProps} />);
|
|
expect(within(container).getByText('Organic Butter')).toBeInTheDocument();
|
|
});
|
|
|
|
it('calls onConfirm when Delete clicked', async () => {
|
|
const { container } = render(<DeleteConfirmModal {...defaultProps} />);
|
|
const buttons = within(container).getAllByRole('button');
|
|
const deleteBtn = buttons.find(b => b.textContent === 'Delete')!;
|
|
fireEvent.click(deleteBtn);
|
|
|
|
await waitFor(() => {
|
|
expect(defaultProps.onConfirm).toHaveBeenCalledOnce();
|
|
});
|
|
});
|
|
|
|
it('shows "Deleting..." during async operation', async () => {
|
|
let resolveDelete!: () => void;
|
|
const slowConfirm = vi.fn(() => new Promise<void>((resolve) => {
|
|
resolveDelete = resolve;
|
|
}));
|
|
|
|
const { container } = render(<DeleteConfirmModal {...defaultProps} onConfirm={slowConfirm} />);
|
|
const buttons = within(container).getAllByRole('button');
|
|
const deleteBtn = buttons.find(b => b.textContent === 'Delete')!;
|
|
fireEvent.click(deleteBtn);
|
|
|
|
await waitFor(() => {
|
|
const btns = within(container).getAllByRole('button');
|
|
expect(btns.find(b => b.textContent === 'Deleting...')).toBeDefined();
|
|
});
|
|
|
|
resolveDelete();
|
|
await waitFor(() => {
|
|
const btns = within(container).getAllByRole('button');
|
|
expect(btns.find(b => b.textContent === 'Delete')).toBeDefined();
|
|
});
|
|
});
|
|
|
|
it('disables both buttons during deletion', async () => {
|
|
let resolveDelete!: () => void;
|
|
const slowConfirm = vi.fn(() => new Promise<void>((resolve) => {
|
|
resolveDelete = resolve;
|
|
}));
|
|
|
|
const { container } = render(<DeleteConfirmModal {...defaultProps} onConfirm={slowConfirm} />);
|
|
const buttons = within(container).getAllByRole('button');
|
|
const deleteBtn = buttons.find(b => b.textContent === 'Delete')!;
|
|
fireEvent.click(deleteBtn);
|
|
|
|
await waitFor(() => {
|
|
const btns = within(container).getAllByRole('button');
|
|
const cancelBtn = btns.find(b => b.textContent === 'Cancel')!;
|
|
const deletingBtn = btns.find(b => b.textContent === 'Deleting...')!;
|
|
expect(cancelBtn).toBeDisabled();
|
|
expect(deletingBtn).toBeDisabled();
|
|
});
|
|
|
|
resolveDelete();
|
|
await waitFor(() => {
|
|
const btns = within(container).getAllByRole('button');
|
|
const cancelBtn = btns.find(b => b.textContent === 'Cancel')!;
|
|
expect(cancelBtn).not.toBeDisabled();
|
|
});
|
|
});
|
|
|
|
it('calls onClose when Cancel clicked', () => {
|
|
const { container } = render(<DeleteConfirmModal {...defaultProps} />);
|
|
const buttons = within(container).getAllByRole('button');
|
|
const cancelBtn = buttons.find(b => b.textContent === 'Cancel')!;
|
|
fireEvent.click(cancelBtn);
|
|
|
|
expect(defaultProps.onClose).toHaveBeenCalledOnce();
|
|
});
|
|
});
|