import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; import GameForm from '../../src/components/games/GameForm'; import { Game } from '../../src/types/game'; describe('GameForm Component', () => { let mockOnSubmit: ReturnType; beforeEach(() => { mockOnSubmit = vi.fn(); mockOnSubmit.mockClear(); }); it('should render form with required fields', () => { render(); expect(screen.getByLabelText(/title/i)).toBeInTheDocument(); expect(screen.getByLabelText(/platform/i)).toBeInTheDocument(); }); it('should render optional fields', () => { render(); // búsqueda de campos opcionales expect(screen.getByLabelText(/price/i)).toBeInTheDocument(); expect(screen.getByLabelText(/description/i)).toBeInTheDocument(); expect(screen.getByLabelText(/notes/i)).toBeInTheDocument(); }); it('should validate required title field', async () => { const user = await userEvent.setup(); render(); const submitButton = screen.getByText('Save Game'); await user.click(submitButton); await waitFor(() => { expect(screen.getByText(/title.*required/i)).toBeInTheDocument(); }); expect(mockOnSubmit).not.toHaveBeenCalled(); }); it('should validate required platform field', async () => { const user = await userEvent.setup(); render(); const titleInput = screen.getByLabelText(/title/i); await user.type(titleInput, 'My Game'); const submitButton = screen.getByText('Save Game'); await user.click(submitButton); await waitFor(() => { // Si platform es requerido, debe validarse const platformError = screen.queryByText(/platform.*required/i); if (platformError) { expect(platformError).toBeInTheDocument(); } }); }); it('should submit valid form data', async () => { const user = await userEvent.setup(); render(); const titleInputs = screen.getAllByDisplayValue(''); const titleInput = titleInputs.find( (el) => (el as HTMLInputElement).id === 'title' ) as HTMLInputElement; const platformInputs = screen.getAllByDisplayValue(''); const platformInput = platformInputs.find( (el) => (el as HTMLInputElement).id === 'platformId' ) as HTMLInputElement; await user.type(titleInput, 'Zelda Game'); await user.type(platformInput, 'Nintendo'); const submitButton = screen.getByText('Save Game'); await user.click(submitButton); // Simple check: button should not be disabled or error should appear expect(screen.queryByText(/required/)).not.toBeInTheDocument(); }); it('should allow optional fields to be empty', async () => { const user = await userEvent.setup(); render(); const titleInputs = screen.getAllByDisplayValue(''); const titleInput = titleInputs.find( (el) => (el as HTMLInputElement).id === 'title' ) as HTMLInputElement; const platformInputs = screen.getAllByDisplayValue(''); const platformInput = platformInputs.find( (el) => (el as HTMLInputElement).id === 'platformId' ) as HTMLInputElement; await user.type(titleInput, 'Game Title'); await user.type(platformInput, 'PS5'); const submitButton = screen.getByText('Save Game'); await user.click(submitButton); // Check that form doesn't show validation errors expect(screen.queryByText(/required/)).not.toBeInTheDocument(); }); it('should populate form with initial data when provided', async () => { const initialGame: Partial = { id: '1', title: 'Existing Game', slug: 'existing-game', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; render(); expect(screen.getByDisplayValue('Existing Game')).toBeInTheDocument(); }); it('should show loading state', () => { render(); const submitButton = screen.getByText('Saving...'); expect(submitButton).toBeDisabled(); }); });