/** * Tests for LoginForm component */ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { LoginForm } from '@/components/auth/LoginForm'; // Mock router jest.mock('next/navigation', () => ({ useRouter: () => ({ push: jest.fn(), }), })); // Mock auth store jest.mock('@/stores/authStore', () => ({ useAuthStore: () => ({ isAuthenticated: false, setAuth: jest.fn(), }), })); const createWrapper = () => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); return ({ children }: { children: React.ReactNode }) => ( {children} ); }; describe('LoginForm', () => { it('renders login form with email and password fields', () => { render(, { wrapper: createWrapper() }); expect(screen.getByLabelText(/email/i)).toBeInTheDocument(); expect(screen.getByLabelText(/password/i)).toBeInTheDocument(); expect(screen.getByRole('button', { name: /sign in/i })).toBeInTheDocument(); }); it('shows validation errors for empty fields', async () => { const user = userEvent.setup(); render(, { wrapper: createWrapper() }); const submitButton = screen.getByRole('button', { name: /sign in/i }); await user.click(submitButton); await waitFor(() => { expect(screen.getByText(/email is required/i)).toBeInTheDocument(); expect(screen.getByText(/password is required/i)).toBeInTheDocument(); }); }); // Note: Email validation is primarily handled by HTML5 type="email" attribute // Zod provides additional validation layer it('shows password requirements validation', async () => { const user = userEvent.setup(); render(, { wrapper: createWrapper() }); const emailInput = screen.getByLabelText(/email/i); const passwordInput = screen.getByLabelText(/password/i); const submitButton = screen.getByRole('button', { name: /sign in/i }); await user.type(emailInput, 'test@example.com'); await user.type(passwordInput, 'short'); await user.click(submitButton); await waitFor(() => { expect(screen.getByText(/password must be at least 8 characters/i)).toBeInTheDocument(); }); }); it('shows register link when enabled', () => { render(, { wrapper: createWrapper() }); expect(screen.getByText(/don't have an account/i)).toBeInTheDocument(); expect(screen.getByRole('link', { name: /sign up/i })).toBeInTheDocument(); }); it('shows password reset link when enabled', () => { render(, { wrapper: createWrapper() }); expect(screen.getByRole('link', { name: /forgot password/i })).toBeInTheDocument(); }); // Note: Async submission tests require API mocking with MSW // Will be added in Phase 9 (Testing Infrastructure) });