Login.test.tsx (1692B)
1 import { describe, it, expect, vi, beforeEach } from "vitest"; 2 import { render, screen, fireEvent, waitFor } from "@testing-library/react"; 3 import { Login } from "./Login"; 4 import { useAuthStore } from "../../store/auth"; 5 6 beforeEach(() => { 7 useAuthStore.setState({ 8 authenticated: false, 9 configured: false, 10 loading: false, 11 error: null, 12 }); 13 vi.restoreAllMocks(); 14 vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ 15 ok: true, 16 json: async () => ({}), 17 })); 18 }); 19 20 describe("Login", () => { 21 it("renders login form", () => { 22 render(<Login />); 23 expect(screen.getByText("Theo Agent Dashboard")).toBeInTheDocument(); 24 expect(screen.getByLabelText("Password")).toBeInTheDocument(); 25 expect(screen.getByText("Sign In")).toBeInTheDocument(); 26 }); 27 28 it("shows error when auth store has error", () => { 29 useAuthStore.setState({ error: "Invalid password" }); 30 render(<Login />); 31 expect(screen.getByText("Invalid password")).toBeInTheDocument(); 32 }); 33 34 it("shows loading state", () => { 35 useAuthStore.setState({ loading: true }); 36 render(<Login />); 37 expect(screen.getByText("Signing in...")).toBeInTheDocument(); 38 }); 39 40 it("disables submit when password is empty", () => { 41 render(<Login />); 42 expect(screen.getByText("Sign In")).toBeDisabled(); 43 }); 44 45 it("calls login on form submit", async () => { 46 const loginSpy = vi.spyOn(useAuthStore.getState(), "login"); 47 render(<Login />); 48 fireEvent.change(screen.getByLabelText("Password"), { target: { value: "secret" } }); 49 fireEvent.click(screen.getByText("Sign In")); 50 await waitFor(() => { 51 expect(loginSpy).toHaveBeenCalledWith("secret"); 52 }); 53 }); 54 });