import { randomUUID } from "node:crypto"; import { dispatchResponseSchema, errorResponseSchema } from "@deadhead/schema"; import { describe, expect, it } from "vitest"; import { bays } from "../src/db/schema"; import { makeOwner, setCredits, TEST_NOW, useTestDatabase } from "./db"; import { call, getState, signUp, useTestApp } from "./game"; const database = useTestDatabase(); const testApp = useTestApp(database); async function ownerWithMoonBay(withMoonBay = true) { const { app } = testApp(); const { db } = database(); const guest = await signUp(app); const shipId = await makeOwner(db, guest.playerId, guest.avatarId); await setCredits(db, guest.playerId, 10_000); if (withMoonBay) { await db.insert(bays).values({ id: randomUUID(), playerId: guest.playerId, locationId: "moon", createdAt: TEST_NOW, }); } return { guest, shipId }; } describe("reposition dispatch", () => { it("flies the ship empty to another bay, costing only fuel", async () => { const { app, clock } = testApp(); const { guest, shipId } = await ownerWithMoonBay(); const response = await call(app, guest, "POST", "/api/dispatches", { kind: "reposition", shipId, pilotId: guest.avatarId, destinationId: "moon", }); expect(response.statusCode).toBe(200); const { dispatch } = dispatchResponseSchema.parse(response.json()); expect(dispatch).toMatchObject({ contract: null, expectedPayout: 0, destinationId: "moon" }); expect(dispatch.fuelCost).toBeGreaterThan(0); clock.now = dispatch.arrivalAt; const state = await getState(app, guest); expect(state.ships[0]).toMatchObject({ status: "idle", locationId: "moon" }); expect(state.pilots[0]).toMatchObject({ status: "idle", locationId: "moon", xp: 0 }); expect(state.company.credits).toBe(10_000 - dispatch.fuelCost); }); it("refuses a destination without a player bay and changes nothing", async () => { const { app } = testApp(); const { guest, shipId } = await ownerWithMoonBay(false); const response = await call(app, guest, "POST", "/api/dispatches", { kind: "reposition", shipId, pilotId: guest.avatarId, destinationId: "moon", }); expect(response.statusCode).toBe(409); expect(errorResponseSchema.parse(response.json()).error.code).toBe("no-bay-at-destination"); const state = await getState(app, guest); expect(state.company.credits).toBe(10_000); expect(state.ships[0]!.status).toBe("idle"); }); });