import { content } from "@deadhead/content"; import { errorResponseSchema } from "@deadhead/schema"; import { describe, expect, it } from "vitest"; import { setCredits, useTestDatabase } from "./db"; import { call, getState, signUp, useTestApp } from "./game"; import { flyTutorialRun, tutorialBoard } from "./tutorial-flow"; const database = useTestDatabase(); const testApp = useTestApp(database); 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(database().db, guest.playerId, 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); }); });