76 lines
3.0 KiB
TypeScript
76 lines
3.0 KiB
TypeScript
// 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, 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 } = 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")!,
|
||
];
|
||
expect(checkRoute(freighter, moon, jupiter, content.config).ok).toBe(true);
|
||
const discovered = new Set(["earth", "moon", "jupiter-cloud-platform"]);
|
||
expect(wouldStrand(freighter, jupiter, 0, 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([]);
|
||
});
|
||
});
|