import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; import ScanDialog from '../../src/components/roms/ScanDialog'; const mockScanDirectory = vi.fn(); vi.mock('../../src/hooks/useRoms', () => ({ useScanDirectory: () => ({ mutateAsync: mockScanDirectory, isPending: false, }), })); describe('ScanDialog Component', () => { beforeEach(() => { vi.clearAllMocks(); }); it('should not render when isOpen is false', () => { render(); // Dialog content should not be visible expect(screen.queryByText(/scan roms directory/i)).not.toBeInTheDocument(); }); it('should render when isOpen is true', () => { render(); expect(screen.getByText(/scan roms directory/i)).toBeInTheDocument(); }); it('should have input field for path', () => { render(); expect(screen.getByPlaceholderText(/enter rom directory path/i)).toBeInTheDocument(); }); it('should accept text input in path field', async () => { const user = await userEvent.setup(); render(); const input = screen.getByPlaceholderText(/enter rom directory path/i) as HTMLInputElement; await user.type(input, '/path/to/roms'); expect(input.value).toBe('/path/to/roms'); }); it('should have "Scan Directory" button', () => { render(); expect(screen.getByRole('button', { name: /scan directory/i })).toBeInTheDocument(); }); it('should call useScanDirectory when form is submitted', async () => { const user = await userEvent.setup(); mockScanDirectory.mockResolvedValue({ processed: 5, createdCount: 3, upserted: 2 }); render(); const input = screen.getByPlaceholderText(/enter rom directory path/i); const button = screen.getByRole('button', { name: /scan directory/i }); await user.type(input, '/roms'); await user.click(button); await waitFor(() => { expect(mockScanDirectory).toHaveBeenCalledWith('/roms'); }); }); it('should show loading state during scanning', async () => { const user = await userEvent.setup(); const { rerender } = render(); const input = screen.getByPlaceholderText(/enter rom directory path/i); const button = screen.getByRole('button', { name: /scan directory/i }); await user.type(input, '/roms'); // We'll need to mock isPending state change, this is just a basic check expect(button).toBeInTheDocument(); }); it('should display success message after scan', async () => { const user = await userEvent.setup(); mockScanDirectory.mockResolvedValue({ processed: 5, createdCount: 3, upserted: 2 }); render(); const input = screen.getByPlaceholderText(/enter rom directory path/i); const button = screen.getByRole('button', { name: /scan directory/i }); await user.type(input, '/roms'); await user.click(button); await waitFor(() => { expect(screen.getByText(/scan completed/i)).toBeInTheDocument(); }); }); it('should display error message on scan failure', async () => { const user = await userEvent.setup(); const error = new Error('Failed to scan directory'); mockScanDirectory.mockRejectedValue(error); render(); const input = screen.getByPlaceholderText(/enter rom directory path/i); const button = screen.getByRole('button', { name: /scan directory/i }); await user.type(input, '/roms'); await user.click(button); await waitFor(() => { expect(screen.getByText(/error/i)).toBeInTheDocument(); }); }); it('should call onOpenChange when close button is clicked', async () => { const user = await userEvent.setup(); const onOpenChange = vi.fn(); render(); const cancelButton = screen.getByText('Cancel'); await user.click(cancelButton); expect(onOpenChange).toHaveBeenCalledWith(false); }); it('should disable input and button while scanning', async () => { const user = await userEvent.setup(); let isPending = false; const ScanDialogWithPending = ({ isOpen, onOpenChange }: any) => { return ; }; render(); const input = screen.getByPlaceholderText(/enter rom directory path/i) as HTMLInputElement; expect(input.disabled).toBe(false); }); });