// Ported from apps/server/test (CR-014 Step 14.5): now runs on the engine. import { content } from "@deadhead/content"; import { errorResponseSchema, shipResponseSchema } from "@deadhead/schema"; import { checkRoute, effectiveStats, realToGame, wouldStrand } from "@deadhead/sim"; import { describe, expect, it } from "vitest"; import { TEST_NOW, useTestApp, call, getState, edit, setCredits, signUpOwner } from "../support"; const testApp = useTestApp(); describe("Lighter and Clipper (Step 10L.6)", () => { for (const modelId of ["lighter", "clipper"]) { it(`buys a ${modelId} at the chosen HQ`, async () => { const { app } = testApp(); const owner = await signUpOwner(app); const price = content.shipModel(modelId)!.price; await setCredits(testApp().app, price); const response = await call(app, owner, "POST", "/api/ships", { modelId, bayId: owner.earthBayId, }); expect(response.statusCode).toBe(200); const { ship } = shipResponseSchema.parse(response.json()); expect(ship).toMatchObject({ modelId, status: "idle", locationId: "earth" }); expect((await getState(app, owner)).company.credits).toBe(0); }); } it("refuses a deadhead that would strand the ship, changing nothing", async () => { const { app, clock } = testApp(); const owner = await signUpOwner(app); await setCredits(app, 100_000); // A Freighter with maxed tanks at the Moon, with Jupiter discovered but not // Mars or Ceres (CR-015 fixed map): Jupiter is in range from the Moon // (667 × 1.3 ≥ 792), but from Jupiter (667 × 1.0) neither Earth nor the Moon is. await edit(app, (save) => { Object.assign( save.ships.find((s) => s.id === owner.shipId)!, { modelId: "freighter", locationId: "moon", upgrades: { "fuel-tanks": 3 }, }, ); save.discoveredLocations.push({ locationId: "jupiter-cloud-platform", discoveredAt: TEST_NOW, }); }); // The scenario as the sim sees it. const freighter = effectiveStats(content.shipModel("freighter")!, { "fuel-tanks": 3 }, content); const [moon, jupiter] = [ content.location("moon")!, content.location("jupiter-cloud-platform")!, ]; const now = realToGame(clock.now, content.config); expect(checkRoute(freighter, moon, jupiter, now).ok).toBe(true); const discovered = new Set(["earth", "moon", "jupiter-cloud-platform"]); expect(wouldStrand(freighter, moon, jupiter, 0, now, discovered, content)).toBe(true); const before = await getState(app, owner); const response = await call(app, owner, "POST", "/api/dispatches", { kind: "reposition", shipId: owner.shipId, pilotId: owner.avatarId, destinationId: "jupiter-cloud-platform", }); expect(response.statusCode).toBe(409); expect(errorResponseSchema.parse(response.json()).error.code).toBe("would-strand"); const after = await getState(app, owner); expect(after.company.credits).toBe(before.company.credits); expect(after.ships).toEqual(before.ships); expect(after.activeDispatches).toEqual([]); }); });