99 lines
3.0 KiB
TypeScript
99 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 { playerStateSchema } from "@deadhead/schema";
|
|
import { pilotLevel } from "@deadhead/sim";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
useTestApp,
|
|
signUp,
|
|
call,
|
|
setCredits,
|
|
insertDispatch,
|
|
makeOwner,
|
|
addShip,
|
|
addPilot,
|
|
} from "../support";
|
|
const randomUUID = () => globalThis.crypto.randomUUID();
|
|
|
|
const testApp = useTestApp();
|
|
|
|
describe("full player state", () => {
|
|
it("reflects one ship in flight and one idle, and validates against its schema", async () => {
|
|
const { app, clock } = testApp();
|
|
const guest = await signUp(app);
|
|
const { shipId: flyingShipId } = await makeOwner(app, guest.avatarId);
|
|
await setCredits(app, 9000);
|
|
|
|
// A second ship at the Moon crewed by a hired pilot with some XP and a skill.
|
|
const idleShipId = randomUUID();
|
|
const hiredId = randomUUID();
|
|
await addShip(app, {
|
|
id: idleShipId,
|
|
modelId: "freighter",
|
|
name: "Slow Ox",
|
|
locationId: "moon",
|
|
});
|
|
await addPilot(app, {
|
|
id: hiredId,
|
|
name: "Rae Okafor",
|
|
xp: 260,
|
|
skills: { "heavy-cargo": 1 },
|
|
skillPointsSpent: 1,
|
|
assignedShipId: idleShipId,
|
|
});
|
|
const record = await insertDispatch(app, {
|
|
shipId: flyingShipId,
|
|
pilotId: guest.avatarId,
|
|
departAt: clock.now,
|
|
});
|
|
|
|
const response = await call(app, guest, "GET", "/api/state");
|
|
expect(response.statusCode).toBe(200);
|
|
const state = playerStateSchema.parse(response.json());
|
|
|
|
expect(state.company.credits).toBe(9000);
|
|
expect(state.tutorial).toBeNull();
|
|
expect(state.bays.map((b) => b.locationId)).toEqual(["earth"]);
|
|
|
|
const flying = state.ships.find((s) => s.id === flyingShipId)!;
|
|
const idle = state.ships.find((s) => s.id === idleShipId)!;
|
|
expect(flying).toMatchObject({
|
|
status: "in-flight",
|
|
locationId: null,
|
|
dispatchId: record.id,
|
|
pilotId: guest.avatarId,
|
|
});
|
|
expect(idle).toMatchObject({
|
|
status: "idle",
|
|
locationId: "moon",
|
|
dispatchId: null,
|
|
pilotId: hiredId,
|
|
modelId: "freighter",
|
|
});
|
|
|
|
const avatar = state.pilots.find((p) => p.id === guest.avatarId)!;
|
|
const hired = state.pilots.find((p) => p.id === hiredId)!;
|
|
expect(avatar).toMatchObject({
|
|
status: "in-flight",
|
|
locationId: null,
|
|
assignedShipId: flyingShipId,
|
|
});
|
|
expect(hired).toMatchObject({
|
|
status: "idle",
|
|
locationId: "moon",
|
|
assignedShipId: idleShipId,
|
|
xp: 260,
|
|
level: pilotLevel(260, content.config),
|
|
skills: { "heavy-cargo": 1 },
|
|
});
|
|
expect(hired.level).toBe(2);
|
|
expect(hired.skillPointsAvailable).toBe(2 * content.config.skillPointsPerLevel - 1);
|
|
|
|
expect(state.activeDispatches).toEqual([
|
|
expect.objectContaining({ id: record.id, status: "in-flight", arrivalAt: record.arrivalAt }),
|
|
]);
|
|
expect(state.summaries).toEqual([]);
|
|
expect(state.locations).toHaveLength(content.locations.length);
|
|
});
|
|
});
|