deadhead-space-freight-tycoon/apps/server/test/contract-dispatch-landing.t...

70 lines
2.4 KiB
TypeScript

import { randomUUID } from "node:crypto";
import { errorResponseSchema } from "@deadhead/schema";
import { describe, expect, it, vi } from "vitest";
import { dispatches, pilots, ships } from "../src/db/schema";
import { makeOwner, setCredits, TEST_NOW, useTestDatabase } from "./db";
import { call, putBoard, signUp, testContract, useTestApp } from "./game";
// Every base-game ship is atmospheric (decision 0.5.1), so `cannot-land` needs
// a test-only vacuum ship in the content the server sees.
vi.mock("@deadhead/content", async (importOriginal) => {
const original = await importOriginal<typeof import("@deadhead/content")>();
const courier = original.content.shipModel("courier")!;
const shipModels = [
...original.content.shipModels,
{ ...courier, id: "test-vacuum", landingClass: "vacuum" as const },
];
return {
...original,
content: {
...original.content,
shipModels,
shipModel: (id: string) => shipModels.find((s) => s.id === id),
},
};
});
const database = useTestDatabase();
const testApp = useTestApp(database);
describe("contract dispatch landing check", () => {
it("rejects cannot-land and changes nothing", async () => {
const { app } = testApp();
const { db } = database();
const guest = await signUp(app);
await makeOwner(db, guest.playerId, guest.avatarId);
await setCredits(db, guest.playerId, 10_000);
// A vacuum-only ship at the Moon, crewed by a pilot, offered a Moon→Earth job.
const shipId = randomUUID();
await db.insert(ships).values({
id: shipId,
playerId: guest.playerId,
modelId: "test-vacuum",
name: "Moon Crawler",
locationId: "moon",
createdAt: TEST_NOW,
});
const pilotId = randomUUID();
await db.insert(pilots).values({
id: pilotId,
playerId: guest.playerId,
name: "Vac Pilot",
assignedShipId: shipId,
createdAt: TEST_NOW,
});
const contract = testContract({ originId: "moon", destinationId: "earth" });
await putBoard(db, guest.playerId, [contract]);
const response = await call(app, guest, "POST", "/api/dispatches", {
kind: "contract",
contractId: contract.id,
shipId,
pilotId,
});
expect(response.statusCode).toBe(409);
expect(errorResponseSchema.parse(response.json()).error.code).toBe("cannot-land");
expect(await db.select().from(dispatches)).toEqual([]);
});
});