import { mount, flushPromises } from "@vue/test-utils"; import { describe, expect, it, vi, beforeEach, beforeAll, afterAll } from "vitest"; import LoginPage from "~/pages/auth/login.vue"; // Mock the auth store const authStoreMocks = vi.hoisted(() => ({ signIn: vi.fn(), lastError: null, })); vi.mock("~/stores/auth", () => ({ useAuthStore: () => authStoreMocks, })); // Make useAuthStore available globally for the component globalThis.useAuthStore = () => authStoreMocks; // Mock UI components vi.mock("@/components/ui/button", () => ({ Button: { props: ["variant", "type"], template: '', }, })); vi.mock("@/components/ui/input", () => ({ Input: { props: ["modelValue", "id", "type", "placeholder", "required"], emits: ["update:modelValue"], template: ``, }, })); vi.mock("@/components/ui/card", () => ({ Card: { template: "
" }, CardHeader: { template: "
" }, CardTitle: { template: "

" }, CardDescription: { template: "

" }, CardContent: { template: "
" }, })); vi.mock("@/components/ui/field", () => ({ Field: { props: ["variant"], template: "
", }, FieldGroup: { template: "
" }, FieldLabel: { template: "" }, FieldDescription: { template: "" }, })); vi.mock("lucide-vue-next", () => ({ Frown: { template: "" }, })); describe("LoginPage", () => { beforeAll(() => { const shouldSuppress = (args: string[]) => { const msg = args.join(" "); return msg.includes(" is an experimental feature"); }; const spyMethods = ["warn", "error", "log", "info"] as const; for (const method of spyMethods) { const original = console[method]; vi.spyOn(console, method).mockImplementation((...args) => { if (shouldSuppress(args)) return; original(...args); }); } }); afterAll(() => { vi.restoreAllMocks(); }); beforeEach(() => { vi.clearAllMocks(); authStoreMocks.lastError = null; }); it("renders the login form correctly", async () => { const wrapper = mount({ components: { LoginPage }, template: "", }); await flushPromises(); expect(wrapper.text()).toContain("Login"); expect(wrapper.text()).toContain("Enter your email below to login"); expect(wrapper.find('input[type="email"]').exists()).toBe(true); expect(wrapper.find('input[type="password"]').exists()).toBe(true); expect(wrapper.text()).toContain("Don't have an account?"); expect(wrapper.text()).toContain("Create account"); }); it("submits the form with correct credentials", async () => { const wrapper = mount({ components: { LoginPage }, template: "", }); await flushPromises(); // Fill the form const emailInput = wrapper.find('input[id="email"]'); const passwordInput = wrapper.find('input[id="password"]'); await emailInput.setValue("test@example.com"); await passwordInput.setValue("password123"); // Submit the form await wrapper.find("form").trigger("submit"); expect(authStoreMocks.signIn).toHaveBeenCalledWith("test@example.com", "password123"); }); it("displays error message when lastError is set", async () => { authStoreMocks.lastError = "Invalid credentials"; const wrapper = mount({ components: { LoginPage }, template: "", }); await flushPromises(); expect(wrapper.text()).toContain("Invalid credentials"); }); it("contains links to Terms of Service and Privacy Policy", async () => { const wrapper = mount({ components: { LoginPage }, template: "", }); await flushPromises(); expect(wrapper.text()).toContain("Terms of Service"); expect(wrapper.text()).toContain("Privacy Policy"); }); });