// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // What a loader does with a refusal on TanStack Start (F10): a real 302, 404 or 403, set before anything // streams. Start has no `forbidden()`, so the 403 is a not-found with `data.forbidden` plus the header the // server entry turns into the status. import { AppError } from "@conusai-kit/core" import { isNotFound, isRedirect } from "@tanstack/react-router" import { beforeEach, describe, expect, it, vi } from "vitest" const start = vi.hoisted(() => ({ setResponseStatus: vi.fn<(status: number) => void>(), setResponseHeader: vi.fn<(name: string, value: string) => void>(), })) vi.mock("@tanstack/react-start/server", () => start) const { orFallback, PAGE_STATUS_HEADER, pageForbidden, pageNotFound, signInHref, toSignIn } = await import( "../apps/web/src/server/guard" ) const refusal = (status: number): AppError => new AppError({ type: "/problems/refused", code: "refused", title: "Refused", status }) const thrownBy = async (run: () => unknown): Promise => { try { await run() } catch (error) { return error } throw new Error("it did not throw") } beforeEach(() => { start.setResponseStatus.mockClear() start.setResponseHeader.mockClear() }) describe("signInHref", () => { it("names where to come back to, and nothing for the home page", () => { expect(signInHref("/acme/general/demo/notes?x=1")).toBe( "/auth/sign-in?return_to=%2Facme%2Fgeneral%2Fdemo%2Fnotes%3Fx%3D1", ) expect(signInHref("/")).toBe("/auth/sign-in") expect(signInHref("/", "denied")).toBe("/auth/sign-in?error=denied") }) }) describe("the status pages", () => { it("answers a signed-out visitor with a 302 to sign in and back", async () => { const error = (await thrownBy(() => toSignIn("/a/b/c/notes"))) as { options: { href: string; statusCode: number } } expect(isRedirect(error)).toBe(true) expect(error.options.href).toBe("/auth/sign-in?return_to=%2Fa%2Fb%2Fc%2Fnotes") expect(error.options.statusCode).toBe(302) }) it("answers not found with 404, in the status and in the header the server entry applies", async () => { expect(isNotFound(await thrownBy(() => pageNotFound()))).toBe(true) expect(start.setResponseStatus).toHaveBeenCalledWith(404) expect(start.setResponseHeader).toHaveBeenCalledWith(PAGE_STATUS_HEADER, "404") }) it("answers forbidden with 403 and marks the not-found as the forbidden page", async () => { const error = (await thrownBy(() => pageForbidden())) as { data: unknown } expect(isNotFound(error)).toBe(true) expect(error.data).toEqual({ forbidden: true }) expect(start.setResponseHeader).toHaveBeenCalledWith(PAGE_STATUS_HEADER, "403") }) }) describe("orFallback", () => { it("passes an answer through", async () => { await expect(orFallback("/here", async () => "rows")).resolves.toBe("rows") expect(start.setResponseStatus).not.toHaveBeenCalled() }) it.each([ [404, "404"], [403, "403"], ])("turns a procedure's %i into that page", async (status, header) => { const error = await thrownBy(() => orFallback("/here", () => Promise.reject(refusal(status)))) expect(isNotFound(error)).toBe(true) expect(start.setResponseHeader).toHaveBeenCalledWith(PAGE_STATUS_HEADER, header) }) it("turns a procedure's 401 into the way to sign in", async () => { expect(isRedirect(await thrownBy(() => orFallback("/here", () => Promise.reject(refusal(401)))))).toBe(true) }) it("leaves anything else to the error boundary", async () => { const fault = new Error("database down") expect(await thrownBy(() => orFallback("/here", () => Promise.reject(fault)))).toBe(fault) expect(await thrownBy(() => orFallback("/here", () => Promise.reject(refusal(500))))).toBeInstanceOf(AppError) expect(start.setResponseStatus).not.toHaveBeenCalled() }) })