deadhead-space-freight-tycoon/packages/engine/test/ported/tutorial-v2.test.ts

87 lines
3.1 KiB
TypeScript

// Ported from apps/server/test (CR-014 Step 14.5): now runs on the engine.
import { content } from "@deadhead/content";
import { errorResponseSchema } from "@deadhead/schema";
import { describe, expect, it } from "vitest";
import {
useTestApp,
signUp,
call,
getState,
setCredits,
tutorialBoard,
flyTutorialRun,
} from "../support";
const testApp = useTestApp();
describe("tutorial flow v2", () => {
it("starts a guest with the starting cushion, the Company Courier loaner at Earth and no runs", async () => {
const { app } = testApp();
const guest = await signUp(app);
const state = await getState(app, guest);
expect(state.company).toMatchObject({
credits: content.config.startingCredits,
loanBalance: 0,
});
expect(state.tutorial).toEqual({
loanerLocationId: "earth",
runInFlight: false,
runsCompleted: 0,
dealAvailable: false,
});
expect(state.pilots[0]).toMatchObject({ isAvatar: true, locationId: "earth" });
expect(state.goals).toEqual([]);
});
it("counts each resolved run and gives every run a fresh three-contract board", async () => {
const guest = await signUp(testApp().app);
const first = await tutorialBoard(testApp().app, guest);
expect(first).toHaveLength(3);
const state = await flyTutorialRun(testApp(), guest);
expect(state.tutorial).toMatchObject({ runsCompleted: 1, loanerLocationId: "moon" });
const second = await tutorialBoard(testApp().app, guest);
expect(second).toHaveLength(3);
for (const c of second) expect([c.originId, c.destinationId]).toEqual(["moon", "earth"]);
expect(second.map((c) => c.id)).not.toEqual(first.map((c) => c.id));
});
it("offers Unmarked crates on the third run's board", async () => {
const guest = await signUp(testApp().app);
await flyTutorialRun(testApp(), guest);
await flyTutorialRun(testApp(), guest);
const third = await tutorialBoard(testApp().app, guest);
expect(third.find((c) => c.scriptedId === "unmarked-crates")).toBeDefined();
});
it("makes the deal available after four runs ending at Earth, not after three", async () => {
const guest = await signUp(testApp().app);
for (let run = 1; run <= 3; run++) await flyTutorialRun(testApp(), guest);
const afterThree = await getState(testApp().app, guest);
expect(afterThree.tutorial).toMatchObject({
runsCompleted: 3,
loanerLocationId: "moon",
dealAvailable: false,
});
const afterFour = await flyTutorialRun(testApp(), guest);
expect(afterFour.tutorial).toMatchObject({
runsCompleted: 4,
loanerLocationId: "earth",
runInFlight: false,
dealAvailable: true,
});
});
it("blocks hiring pilots during the tutorial", async () => {
const { app } = testApp();
const guest = await signUp(app);
await setCredits(testApp().app, 1_000_000);
const response = await call(app, guest, "POST", "/api/pilots", { locationId: "earth" });
expect(response.statusCode).toBe(409);
expect(errorResponseSchema.parse(response.json()).error.code).toBe("tutorial-active");
expect((await getState(app, guest)).pilots).toHaveLength(1);
});
});