// Ported from apps/server/test (CR-014 Step 14.5): request and response checks // from the route catalog, now on engine commands. (Malformed JSON bodies and // HTTP 404s for unknown URLs no longer exist.) import { errorResponseSchema, type RouteResponse } from "@deadhead/schema"; import { describe, expect, it } from "vitest"; import { GameEngine, MemoryBackend, SaveStorage } from "../../src/index"; import { useTestApp, signUp, call } from "../support"; const testApp = useTestApp(); const expectValidationError = (response: { statusCode: number; json(): unknown }) => { expect(response.statusCode).toBe(400); expect(errorResponseSchema.parse(response.json()).error.code).toBe("validation-error"); }; describe("request validation from the command catalog", () => { it("rejects unexpected fields on a command that takes none", async () => { expectValidationError( await call(testApp().app, null, "POST", "/api/guest", { surprise: true }), ); }); it("rejects unexpected parameters before anything else", async () => { expectValidationError(await call(testApp().app, null, "GET", "/api/state?evil=1")); }); it("still answers valid requests", async () => { expect((await call(testApp().app, null, "GET", "/api/time")).statusCode).toBe(200); }); it("refuses an unknown command with not-found", async () => { await expect(testApp().app.call("nope" as never, {} as never)).rejects.toMatchObject({ code: "not-found", }); }); }); describe("response validation", () => { const engine = (validateResponses: boolean) => new GameEngine({ storage: new SaveStorage(new MemoryBackend()), clock: { now: () => 0 }, validateResponses, // A handler that breaks the state response schema. overrides: { getPlayerState: () => ({ playerId: 42 }) as unknown as RouteResponse<"getPlayerState">, }, }); it("fails a response that violates its schema when checking is on", async () => { const app = engine(true); await signUp(app); await expect(app.call("getPlayerState", {})).rejects.toThrow(/violates its schema/); }); it("does not check responses when checking is off (production)", async () => { const app = engine(false); await signUp(app); await expect(app.call("getPlayerState", {})).resolves.toEqual({ playerId: 42 }); }); });