// 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 five runs ending at the Moon, not after four (CR-017)", async () => { const guest = await signUp(testApp().app); for (let run = 1; run <= 4; run++) await flyTutorialRun(testApp(), guest); const afterFour = await getState(testApp().app, guest); expect(afterFour.tutorial).toMatchObject({ runsCompleted: 4, loanerLocationId: "earth", dealAvailable: false, }); const afterFive = await flyTutorialRun(testApp(), guest); expect(afterFive.tutorial).toMatchObject({ runsCompleted: 5, loanerLocationId: "moon", 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); }); });