import { describe, expect, test } from "bun:test"; import { createProductionHandlers, type ProdManifest } from "../src/prod.ts"; /** * Production-only regression test for server.fn() RPC. The browser runtime * posts server-function calls to `/__wrnexus/rpc`. Dev intercepts that path * with a handler built from `createRpcHandler` (index.ts). Production had no * such route: the request fell through to `isRpcPath`/`handleRpcRequest` — * the *inter-app service* RPC, gated by an internal-caller header a browser * never sends — and 404'd. See `resolveProdServerFunctions` in prod.ts. */ // Shape emitted by the compiler for a `.wrn` file with server functions // (packages/compiler/src/server-codegen.ts): a plain functions object plus a // manifest array of `{ component, function, parameters?, returnType? }`. function serverModule(component: string) { return { __wrnexusServerFunctions: { async greet(name: string) { return `hello ${name}`; }, }, __wrnexusRpcManifest: [ { component, function: "greet", parameters: [{ name: "name", type: "string", optional: false }], returnType: "string", }, ], }; } function manifest(): ProdManifest { return { pages: [], api: [], realtime: [], middleware: [], components: [{ name: "Greeter", mod: serverModule("Greeter") }], layouts: [], }; } const CSRF_TOKEN = "test-token"; const CSRF_HEADERS = { origin: "http://localhost", cookie: `wrn-csrf=${CSRF_TOKEN}`, "x-csrf-token": CSRF_TOKEN, }; function rpcRequest(body: unknown, headers: Record = CSRF_HEADERS): Request { return new Request("http://localhost/__wrnexus/rpc", { method: "POST", headers: { "content-type": "application/json", ...headers }, body: JSON.stringify(body), }); } describe("production server.fn() RPC (/__wrnexus/rpc)", () => { test("a valid call to an existing server function succeeds, not 404", async () => { const handlers = createProductionHandlers(manifest(), {}); const req = rpcRequest({ component: "Greeter", function: "greet", args: ["world"] }); const res = await handlers.fetch(req, {} as never); expect(res).toBeDefined(); expect(res!.status).toBe(200); const body = await res!.json(); expect(body).toMatchObject({ ok: true, value: "hello world" }); }); test("a request without a valid CSRF token is rejected", async () => { const handlers = createProductionHandlers(manifest(), {}); const req = rpcRequest( { component: "Greeter", function: "greet", args: ["world"] }, { "content-type": "application/json" }, ); const res = await handlers.fetch(req, {} as never); expect(res).toBeDefined(); expect(res!.status).toBe(403); const body = await res!.json(); expect(body.ok).toBe(false); }); test("an unknown component fails cleanly (404), not with an internal error", async () => { const handlers = createProductionHandlers(manifest(), {}); const req = rpcRequest({ component: "NoSuchComponent", function: "greet", args: [] }); const res = await handlers.fetch(req, {} as never); expect(res).toBeDefined(); expect(res!.status).toBe(404); const body = await res!.json(); expect(body.ok).toBe(false); }); test("an unknown function on a known component fails cleanly (404)", async () => { const handlers = createProductionHandlers(manifest(), {}); const req = rpcRequest({ component: "Greeter", function: "notARealFunction", args: [] }); const res = await handlers.fetch(req, {} as never); expect(res).toBeDefined(); expect(res!.status).toBe(404); const body = await res!.json(); expect(body.ok).toBe(false); }); });