deadhead-space-freight-tycoon/packages/engine/test/completable-boards.test.ts

104 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { content } from "@deadhead/content";
import { boardPeriodMs } from "@deadhead/sim";
import { describe, expect, it } from "vitest";
import { encodeSave } from "../src/index";
import {
addPilot,
addShip,
readSave,
setCredits,
signUpOwner,
TEST_NOW,
useTestApp,
} from "./support";
const testApp = useTestApp();
const COURIER_HOLD = content.shipModel("courier")!.cargoCapacityTonnes;
const PERIOD = boardPeriodMs(content.config);
describe("completable boards in the engine (Step 19.3, decisions 0.5.114–0.5.117)", () => {
it("hides a heavy job once the only ship that could take it has left", async () => {
const { app, clock } = testApp();
await signUpOwner(app);
await addShip(app, { id: "f1", modelId: "freighter", name: "Big Wren" });
await addPilot(app, { id: "p1", name: "Ada", assignedShipId: "f1" });
const before = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
const heavy = before.filter((c) => c.massTonnes > COURIER_HOLD);
expect(heavy.length).toBeGreaterThan(0);
// The Freighter flies empty to the Moon; the Courier is still at Earth.
await app.call("createDispatch", {
kind: "reposition",
shipId: "f1",
pilotId: "p1",
destinationId: "moon",
});
clock.now += 1_000;
const after = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
expect(after.filter((c) => c.massTonnes > COURIER_HOLD)).toEqual([]);
// What the Courier can take is still there, unchanged.
expect(after).toEqual(before.filter((c) => c.massTonnes <= COURIER_HOLD));
});
it("adds a bigger ship's jobs at the next board period, not mid-period", async () => {
const { app, clock } = testApp();
const owner = await signUpOwner(app);
const first = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
expect(first.every((c) => c.massTonnes <= COURIER_HOLD)).toBe(true);
await setCredits(app, content.shipModel("freighter")!.price);
const { ship } = await app.call("buyShip", { modelId: "freighter", bayId: owner.earthBayId });
await addPilot(app, { id: "p1", name: "Ada", assignedShipId: ship.id });
clock.now += 1_000;
expect((await app.call("getContractBoard", { locationId: "earth" })).contracts).toEqual(first);
// Next period: the board is made for the Courier and the Freighter.
clock.now = (Math.floor(TEST_NOW / PERIOD) + 1) * PERIOD + 1_000;
let heavy = 0;
for (let period = 0; period < 5; period++, clock.now += PERIOD) {
const board = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
heavy += board.filter((c) => c.massTonnes > COURIER_HOLD).length;
}
expect(heavy).toBeGreaterThan(0);
});
it("stores the qualifying fleet with each board it generates", async () => {
const { app } = testApp();
await signUpOwner(app);
await app.call("getContractBoard", { locationId: "earth" });
const [board] = (await readSave(app)).contractBoards.filter((b) => b.kind === "location");
expect(board!.fleet).toEqual([
{
modelId: "courier",
skills: {},
upgrades: {},
fuelFu: content.shipModel("courier")!.tankCapacityFu,
},
]);
});
it("opens an older save with no stored boards, and regenerates them on view", async () => {
const { app } = testApp();
await signUpOwner(app);
const before = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
const old = await readSave(app);
expect(old.contractBoards.length).toBeGreaterThan(0);
// As version 3 wrote it: boards without a fleet snapshot.
const v3 = {
...old,
saveVersion: 3,
contractBoards: old.contractBoards.map(({ fleet: _fleet, ...rest }) => rest),
};
const device = testApp().app;
await device.call("importSave", { code: await encodeSave(v3 as never) });
expect((await readSave(device)).contractBoards).toEqual([]);
// The same inputs regenerate the same board.
expect((await device.call("getContractBoard", { locationId: "earth" })).contracts).toEqual(
before,
);
expect((await readSave(device)).contractBoards).toHaveLength(1);
});
});