/* @vitest-environment jsdom */ import { act, fireEvent, render, screen } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { LoginForm } from "@/components/auth/login-form"; const replaceMock = vi.fn(); const refreshMock = vi.fn(); const getSearchParamMock = vi.fn(); vi.mock("next/navigation", () => ({ useRouter: () => ({ replace: replaceMock, refresh: refreshMock, }), useSearchParams: () => ({ get: getSearchParamMock, }), })); describe("LoginForm", () => { beforeEach(() => { vi.useRealTimers(); vi.restoreAllMocks(); replaceMock.mockReset(); refreshMock.mockReset(); getSearchParamMock.mockReset(); getSearchParamMock.mockImplementation((key: string) => { if (key === "next") return "/"; return null; }); }); it("toggles password visibility from the eye button", () => { render(); const passwordInput = screen.getByPlaceholderText("Password") as HTMLInputElement; expect(passwordInput.type).toBe("password"); fireEvent.click(screen.getByRole("button", { name: "Show password" })); expect(passwordInput.type).toBe("text"); fireEvent.click(screen.getByRole("button", { name: "Hide password" })); expect(passwordInput.type).toBe("password"); }); it("shows a retry countdown on the submit button after invalid credentials", async () => { vi.useFakeTimers(); vi.stubGlobal( "fetch", vi.fn().mockResolvedValue({ ok: false, status: 401, headers: new Headers(), json: async () => ({ error: "Invalid username or password" }), }), ); render(); fireEvent.change(screen.getByPlaceholderText("Username"), { target: { value: "admin" }, }); fireEvent.change(screen.getByPlaceholderText("Password"), { target: { value: "wrong-password" }, }); fireEvent.click(screen.getByRole("button", { name: /sign in/i })); await act(async () => { await Promise.resolve(); }); expect(screen.getByText("Invalid username or password")).toBeTruthy(); expect( (screen.getByRole("button", { name: /try again in 3s/i }) as HTMLButtonElement).disabled, ).toBe(true); await act(async () => { await vi.advanceTimersByTimeAsync(1_000); }); expect( screen.getByRole("button", { name: /try again in [12]s/i }), ).toBeTruthy(); }); });