Files
template-app/test/start-server-entry.test.ts
2026-11-14 09:56:45 +00:00

89 lines
3.8 KiB
TypeScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// The server entry: what Next's proxy and instrumentation did. One nonce per request, named by the policy
// and given to the renderer; `x-path`; the status a loader asked for; a contract check before the first
// request; and a report for what escapes the handler.
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
const mocks = vi.hoisted(() => ({
fetch: vi.fn<(request: Request, options?: unknown) => Promise<Response>>(),
loadAppEnv: vi.fn(),
loadAuthConfig: vi.fn(),
captureException: vi.fn(),
logError: vi.fn(),
}))
vi.mock("@tanstack/react-start/server-entry", () => ({
default: { fetch: mocks.fetch },
createServerEntry: <T>(entry: T): T => entry,
}))
vi.mock("@tanstack/react-start/server", () => ({ setResponseHeader: vi.fn(), setResponseStatus: vi.fn() }))
vi.mock("@app/config", () => ({
PROFILE: "postgres",
loadAppEnv: mocks.loadAppEnv,
currentObservability: () => ({ captureException: mocks.captureException, log: { error: mocks.logError } }),
}))
vi.mock("@conusai-kit/auth", () => ({ loadAuthConfig: mocks.loadAuthConfig }))
const { default: entry } = await import("../apps/web/src/server")
const { PAGE_STATUS_HEADER } = await import("../apps/web/src/server/guard")
const serve = (url = "http://app.test/acme/general/demo/notes?x=1"): Promise<Response> =>
(entry as unknown as { fetch(request: Request): Promise<Response> }).fetch(new Request(url))
beforeEach(() => {
mocks.fetch.mockReset()
mocks.fetch.mockImplementation(async () => new Response("<html></html>", { status: 200 }))
})
afterEach(() => vi.clearAllMocks())
describe("the server entry", () => {
it("gives the renderer the nonce the policy names, and tells a loader where the request is", async () => {
const response = await serve()
const request = mocks.fetch.mock.calls[0]?.[0] as Request
const nonce = request.headers.get("x-nonce") as string
expect(nonce).toBeTruthy()
expect(request.headers.get("x-path")).toBe("/acme/general/demo/notes?x=1")
expect(response.headers.get("content-security-policy")).toContain(`'nonce-${nonce}'`)
expect(mocks.fetch.mock.calls[0]?.[1]).toMatchObject({ context: { nonce } })
})
it("makes one nonce per request", async () => {
await serve()
await serve()
const [first, second] = mocks.fetch.mock.calls.map(([request]) => request.headers.get("x-nonce"))
expect(first).not.toBe(second)
})
it("applies the status a loader asked for and removes the header that carried it", async () => {
mocks.fetch.mockResolvedValueOnce(
new Response("<html>forbidden</html>", { status: 404, headers: { [PAGE_STATUS_HEADER]: "403" } }),
)
const response = await serve()
expect(response.status).toBe(403)
expect(response.headers.has(PAGE_STATUS_HEADER)).toBe(false)
expect(await response.text()).toContain("forbidden")
})
it("leaves a status nobody asked to change alone", async () => {
mocks.fetch.mockResolvedValueOnce(new Response(null, { status: 302, headers: { location: "/auth/sign-in" } }))
const response = await serve()
expect(response.status).toBe(302)
expect(response.headers.get("location")).toBe("/auth/sign-in")
})
it("parses the deployment contract once, before the first request is served", async () => {
await serve()
await serve()
// The entry's module state: checked by an earlier test's request at the latest, and never again.
expect(mocks.loadAppEnv.mock.calls.length).toBeLessThanOrEqual(1)
})
it("reports what escapes the handler, and still fails the request", async () => {
const fault = new Error("render failed")
mocks.fetch.mockRejectedValueOnce(fault)
await expect(serve()).rejects.toBe(fault)
expect(mocks.captureException).toHaveBeenCalledWith(fault, expect.objectContaining({ kind: "handler" }))
})
})