import React from 'react' import { renderWithProviders, userEvent, waitFor } from '@/__tests__/utils/test-helpers' import { mockLoginResponse } from '@/__tests__/fixtures/mock-data' import { useAuth } from '@/hooks/use-auth' import LoginPage from './page' jest.mock('@/hooks/use-auth') jest.mock('@/components/ui/button', () => ({ Button: ({ children, ...props }: any) => , })) jest.mock('@/components/ui/input', () => ({ Input: (props: any) => , })) jest.mock('@/components/ui/label', () => ({ Label: ({ children, ...props }: any) => , })) jest.mock('@/components/ui/card', () => ({ Card: ({ children }: any) =>
{children}
, CardHeader: ({ children }: any) =>
{children}
, CardTitle: ({ children }: any) =>

{children}

, CardDescription: ({ children }: any) =>

{children}

, CardContent: ({ children }: any) =>
{children}
, CardFooter: ({ children }: any) =>
{children}
, })) jest.mock('lucide-react', () => ({ Eye: () => , EyeOff: () => , })) jest.mock('next/link', () => ({ __esModule: true, default: ({ children, href }: any) => {children}, })) describe('LoginPage', () => { const mockLogin = jest.fn() beforeEach(() => { jest.clearAllMocks() ;(useAuth as jest.Mock).mockReturnValue({ login: mockLogin, }) }) it('should render login form', () => { const { getByText, getByPlaceholderText } = renderWithProviders() expect(getByText('Welcome back')).toBeInTheDocument() expect(getByText('Enter your credentials to access your dashboard')).toBeInTheDocument() expect(getByPlaceholderText('you@example.com')).toBeInTheDocument() expect(getByPlaceholderText('••••••••')).toBeInTheDocument() }) it('should display required field errors', async () => { const { getByRole, getByText } = renderWithProviders() const submitButton = getByRole('button', { name: /sign in/i }) await userEvent.click(submitButton) expect(getByText('Email is required')).toBeInTheDocument() expect(getByText('Password is required')).toBeInTheDocument() }) it('should validate email format', async () => { const { getByPlaceholderText, getByRole, getByText, queryByText } = renderWithProviders() const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const submitButton = getByRole('button', { name: /sign in/i }) await userEvent.type(emailInput, 'invalid-email') await userEvent.type(passwordInput, 'password123') await userEvent.click(submitButton) expect(queryByText('Invalid email address')).toBeInTheDocument() }) it('should validate password minimum length', async () => { const { getByPlaceholderText, getByRole, getByText } = renderWithProviders() const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const submitButton = getByRole('button', { name: /sign in/i }) await userEvent.type(emailInput, 'test@example.com') await userEvent.type(passwordInput, '12345') await userEvent.click(submitButton) expect(getByText('Password must be at least 6 characters')).toBeInTheDocument() }) it('should submit form with valid credentials', async () => { mockLogin.mockResolvedValueOnce(undefined) const { getByPlaceholderText, getByRole } = renderWithProviders() const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const submitButton = getByRole('button', { name: /sign in/i }) await userEvent.type(emailInput, 'test@example.com') await userEvent.type(passwordInput, 'password123') await userEvent.click(submitButton) expect(mockLogin).toHaveBeenCalledWith({ email: 'test@example.com', password: 'password123', remember: false, }) }) it('should display error message on login failure', async () => { const errorMessage = 'Invalid credentials' mockLogin.mockRejectedValueOnce(new Error(errorMessage)) const { getByPlaceholderText, getByRole, getByText } = renderWithProviders() const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const submitButton = getByRole('button', { name: /sign in/i }) await userEvent.type(emailInput, 'test@example.com') await userEvent.type(passwordInput, 'password123') await userEvent.click(submitButton) expect(getByText(errorMessage)).toBeInTheDocument() }) it('should toggle password visibility', async () => { const { getByPlaceholderText, getByTestId } = renderWithProviders() const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const toggleButton = passwordInput.parentElement?.querySelector('button') expect(passwordInput.type).toBe('password') if (toggleButton) { await userEvent.click(toggleButton) expect(passwordInput.type).toBe('text') await userEvent.click(toggleButton) expect(passwordInput.type).toBe('password') } }) it('should handle remember me checkbox', async () => { mockLogin.mockResolvedValueOnce(undefined) const { getByRole, getByLabelText } = renderWithProviders() const rememberCheckbox = getByRole('checkbox', { name: /remember me/i, }) as HTMLInputElement expect(rememberCheckbox.checked).toBe(false) await userEvent.click(rememberCheckbox) expect(rememberCheckbox.checked).toBe(true) }) it('should show loading state during submission', async () => { mockLogin.mockImplementationOnce( () => new Promise((resolve) => { setTimeout(resolve, 200) }) ) const { getByPlaceholderText, getByRole, getByText, queryByText } = renderWithProviders() const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const submitButton = getByRole('button', { name: /sign in/i }) as HTMLButtonElement await userEvent.type(emailInput, 'test@example.com') await userEvent.type(passwordInput, 'password123') await userEvent.click(submitButton) // The loading state is set during submission // After the promise resolves, it should revert to normal state expect(mockLogin).toHaveBeenCalled() }) it('should have link to signup page', () => { const { getByRole } = renderWithProviders() const signupLink = getByRole('link', { name: /sign up/i }) expect(signupLink).toHaveAttribute('href', '/register') }) it('should clear error when user tries again', async () => { mockLogin.mockRejectedValueOnce(new Error('Login failed')).mockResolvedValueOnce(undefined) const { getByPlaceholderText, getByRole, getByText, queryByText } = renderWithProviders() const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement const passwordInput = getByPlaceholderText('••••••••') as HTMLInputElement const submitButton = getByRole('button', { name: /sign in/i }) await userEvent.type(emailInput, 'test@example.com') await userEvent.type(passwordInput, 'password123') await userEvent.click(submitButton) await waitFor(() => { expect(getByText('Login failed')).toBeInTheDocument() }) mockLogin.mockResolvedValueOnce(undefined) await userEvent.click(submitButton) await waitFor(() => { expect(queryByText('Login failed')).not.toBeInTheDocument() }) }) })