deadhead-space-freight-tycoon/packages/engine/test/start.test.ts

98 lines
3.2 KiB
TypeScript

import { content } from "@deadhead/content";
import { describe, expect, it } from "vitest";
import { GameEngine, MemoryBackend, SaveStorage, type RandomSource } from "../src/index";
import { companyName } from "../src/game/names";
import { TEST_NOW } from "./support";
/** Deterministic ids and seeds, so the starting state can be compared exactly. */
function fixedRandom(seed: number): RandomSource {
let n = 0;
return { id: () => `id-${++n}`, seed: () => seed };
}
function engineOn(backend: MemoryBackend, seed = 1234) {
return new GameEngine({
storage: new SaveStorage(backend),
clock: { now: () => TEST_NOW },
random: fixedRandom(seed),
});
}
describe("company creation on the device (Step 14.8)", () => {
it("starts from empty storage with exactly CR-001's starting state", async () => {
const backend = new MemoryBackend();
const engine = engineOn(backend);
await expect(engine.call("getPlayerState", {})).rejects.toMatchObject({ code: "unauthorized" });
const { state } = await engine.call("createGuest", {});
expect(state).toEqual({
playerId: "id-1",
company: {
id: "id-2",
name: companyName(1234),
credits: content.config.startingCredits,
loanBalance: 0,
},
ships: [],
pilots: [
{
id: "id-3",
name: "Captain",
isAvatar: true,
isVeteran: false,
xp: 0,
level: 0,
skills: {},
skillPointsAvailable: 0,
assignedShipId: null,
status: "idle",
locationId: "earth",
dutyHours: 0,
dutyLimit: content.config.dutyLimitGameHours,
resting: false,
restEndsAt: null,
mode: "manual",
orders: {
destinationIds: null,
cargoClassIds: content.cargoTypes.map((c) => c.id),
takePriority: true,
minProfit: 0,
homeLocationId: "earth",
},
},
],
bays: [],
locations: content.locations.map((l) => ({ id: l.id, discovered: l.startsDiscovered })),
tutorial: {
loanerLocationId: "earth",
runInFlight: false,
runsCompleted: 0,
dealAvailable: false,
},
activeDispatches: [],
summaries: [],
goals: [],
dispatchOffice: {
owned: false,
spendingFloor: content.config.independentPilots.defaultSpendingFloor,
},
});
});
it("opens the same company after a reload", async () => {
const backend = new MemoryBackend();
const created = await engineOn(backend).call("createGuest", {});
// A new engine on the same storage: the app reloaded.
const reopened = engineOn(backend, 9999);
expect(await reopened.call("getPlayerState", {})).toEqual(created.state);
expect(await reopened.call("createGuest", {})).toEqual(created);
});
it("gives each new company its own world seed", async () => {
const a = await engineOn(new MemoryBackend(), 1).call("createGuest", {});
const b = await engineOn(new MemoryBackend(), 2).call("createGuest", {});
expect(a.state.company.name).toBe(companyName(1));
expect(b.state.company.name).toBe(companyName(2));
});
});