import React from "react"; import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { LoginForm } from "@/components/auth/login-form"; import { useAuth, useEmailValidation } from "@/hooks/use-auth"; // Mock the hooks jest.mock("@/hooks/use-auth"); jest.mock("@/service/landing/landing", () => ({ listRole: jest.fn().mockResolvedValue({ data: { data: [ { id: 1, name: "Admin" }, { id: 2, name: "User" }, ], }, }), })); // Mock next-intl jest.mock("next-intl", () => ({ useTranslations: () => (key: string, options?: any) => { const defaults = { logInPlease: "Log In Please", acc: "Acc", register: "Register", password: "Password", rememberMe: "Remember Me", forgotPass: "Forgot Pass", next: "Next", categoryReg: "Category Reg", selectOne: "Select One", signIn: "Sign In", }; return options?.defaultValue || defaults[key] || key; }, })); const mockUseAuth = useAuth as jest.MockedFunction; const mockUseEmailValidation = useEmailValidation as jest.MockedFunction; describe("LoginForm", () => { const mockLogin = jest.fn(); const mockValidateEmail = jest.fn(); const mockOnSuccess = jest.fn(); const mockOnError = jest.fn(); beforeEach(() => { jest.clearAllMocks(); mockUseAuth.mockReturnValue({ login: mockLogin, logout: jest.fn(), refreshToken: jest.fn(), isAuthenticated: false, user: null, loading: false, error: null, }); mockUseEmailValidation.mockReturnValue({ validateEmail: mockValidateEmail, loading: false, error: null, }); }); it("renders login form with all required fields", () => { render( ); expect(screen.getByText("Log In Please")).toBeInTheDocument(); expect(screen.getByLabelText(/username/i)).toBeInTheDocument(); expect(screen.getByLabelText(/password/i)).toBeInTheDocument(); expect(screen.getByRole("button", { name: /selanjutnya/i })).toBeInTheDocument(); }); it("shows validation errors for invalid input", async () => { render( ); const submitButton = screen.getByRole("button", { name: /selanjutnya/i }); fireEvent.click(submitButton); await waitFor(() => { expect(screen.getByText("Username is required")).toBeInTheDocument(); expect(screen.getByText("Password is required")).toBeInTheDocument(); }); }); it("handles successful form submission", async () => { mockValidateEmail.mockResolvedValue("success"); render( ); const usernameInput = screen.getByLabelText(/username/i); const passwordInput = screen.getByLabelText(/password/i); const submitButton = screen.getByRole("button", { name: /selanjutnya/i }); fireEvent.change(usernameInput, { target: { value: "testuser" } }); fireEvent.change(passwordInput, { target: { value: "password123" } }); fireEvent.click(submitButton); await waitFor(() => { expect(mockValidateEmail).toHaveBeenCalledWith({ username: "testuser", password: "password123", }); }); }); it("handles email validation step", async () => { mockValidateEmail.mockResolvedValue("setup"); render( ); const usernameInput = screen.getByLabelText(/username/i); const passwordInput = screen.getByLabelText(/password/i); const submitButton = screen.getByRole("button", { name: /selanjutnya/i }); fireEvent.change(usernameInput, { target: { value: "testuser" } }); fireEvent.change(passwordInput, { target: { value: "password123" } }); fireEvent.click(submitButton); await waitFor(() => { expect(mockOnError).toHaveBeenCalledWith("Email setup required"); }); }); it("handles OTP step", async () => { mockValidateEmail.mockResolvedValue("otp"); render( ); const usernameInput = screen.getByLabelText(/username/i); const passwordInput = screen.getByLabelText(/password/i); const submitButton = screen.getByRole("button", { name: /selanjutnya/i }); fireEvent.change(usernameInput, { target: { value: "testuser" } }); fireEvent.change(passwordInput, { target: { value: "password123" } }); fireEvent.click(submitButton); await waitFor(() => { expect(mockOnError).toHaveBeenCalledWith("OTP verification required"); }); }); it("toggles password visibility", () => { render( ); const passwordInput = screen.getByLabelText(/password/i); const toggleButton = screen.getByLabelText(/show password/i); expect(passwordInput).toHaveAttribute("type", "password"); fireEvent.click(toggleButton); expect(passwordInput).toHaveAttribute("type", "text"); expect(screen.getByLabelText(/hide password/i)).toBeInTheDocument(); fireEvent.click(toggleButton); expect(passwordInput).toHaveAttribute("type", "password"); }); it("handles remember me checkbox", () => { render( ); const rememberMeCheckbox = screen.getByRole("checkbox", { name: /remember me/i }); expect(rememberMeCheckbox).toBeChecked(); fireEvent.click(rememberMeCheckbox); expect(rememberMeCheckbox).not.toBeChecked(); }); it("opens registration dialog", () => { render( ); const registerLink = screen.getByText("Register"); fireEvent.click(registerLink); expect(screen.getByText("Category Reg")).toBeInTheDocument(); expect(screen.getByText("Select One")).toBeInTheDocument(); expect(screen.getByLabelText("Admin")).toBeInTheDocument(); expect(screen.getByLabelText("User")).toBeInTheDocument(); }); it("handles loading state", async () => { mockUseEmailValidation.mockReturnValue({ validateEmail: mockValidateEmail, loading: true, error: null, }); render( ); const submitButton = screen.getByRole("button", { name: /processing/i }); expect(submitButton).toBeDisabled(); }); it("handles error state", async () => { mockValidateEmail.mockRejectedValue(new Error("Validation failed")); render( ); const usernameInput = screen.getByLabelText(/username/i); const passwordInput = screen.getByLabelText(/password/i); const submitButton = screen.getByRole("button", { name: /selanjutnya/i }); fireEvent.change(usernameInput, { target: { value: "testuser" } }); fireEvent.change(passwordInput, { target: { value: "password123" } }); fireEvent.click(submitButton); await waitFor(() => { expect(mockOnError).toHaveBeenCalledWith("Validation failed"); }); }); });