import { describe, it, expect, vi } from "vitest"; vi.mock("~/lib/auth.server", () => ({ auth: { api: { getSession: vi.fn() } }, })); vi.mock("~/lib/cloudinary.server", () => ({ deleteCloudinaryImageByUrl: vi.fn() })); vi.mock("~/lib/email.server", () => ({ sendEmail: vi.fn(), wrapInEmailTemplate: vi.fn(), emailParagraph: vi.fn(), escapeHtml: vi.fn(), })); vi.mock("~/models/user", () => ({ findUserById: vi.fn(), findUserByUsername: vi.fn(), isUserInActiveDraft: vi.fn(), updateUser: vi.fn(), anonymizeUserAccount: vi.fn(), USERNAME_RE: /^[a-zA-Z0-9_-]{3,30}$/, })); vi.mock("~/models/account", () => ({ findLinkedAccountsByUserId: vi.fn() })); vi.mock("~/models/team", () => ({ findTeamsByOwnerId: vi.fn(), removeTeamOwner: vi.fn() })); vi.mock("~/models/commissioner", () => ({ removeAllCommissionersByUserId: vi.fn() })); import { loader } from "../settings"; import { auth } from "~/lib/auth.server"; type LoaderArgs = Parameters[0]; function loaderArgs(section?: string): LoaderArgs { const path = section ? `/settings/${section}` : "/settings"; return { params: { section }, request: new Request(`http://localhost${path}`), context: {}, } as unknown as LoaderArgs; } describe("/settings loader section handling", () => { it("redirects an unknown section back to /settings", async () => { const result = (await loader(loaderArgs("bogus"))) as Response; expect(result).toBeInstanceOf(Response); expect(result.status).toBe(302); expect(result.headers.get("Location")).toBe("/settings"); // The bad section short-circuits before we ever touch the session. expect(auth.api.getSession).not.toHaveBeenCalled(); }); it("does not redirect a valid section before auth runs", async () => { vi.mocked(auth.api.getSession).mockResolvedValue(null as never); const result = (await loader(loaderArgs("account"))) as Response; // Falls through to the auth check, which redirects to login (not /settings). expect(result.headers.get("Location")).toBe("/login?redirectTo=/settings"); expect(auth.api.getSession).toHaveBeenCalled(); }); });