import { content } from "@deadhead/content"; import type { GoalState } from "@deadhead/schema"; import { screen, waitFor, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, expect, it } from "vitest"; import { fakeApi, renderApp, samplePlayerState } from "./render"; const title = (id: string) => content.onboardingGoal(id)!.title; function statesWith(ready: string[], claimed: string[] = []): GoalState[] { return content.onboardingGoals.map((g) => ({ id: g.id, status: claimed.includes(g.id) ? "claimed" : ready.includes(g.id) ? "ready" : "incomplete", })); } const owner = (goals: GoalState[]) => samplePlayerState({ tutorial: null, company: { id: "c", name: "D", credits: 100, loanBalance: 4000 }, goals, }); describe("goals on HQ", () => { it("shows only the next three unclaimed goals, with rewards", async () => { renderApp(fakeApi({ getPlayerState: () => owner(statesWith([])) })); const card = await screen.findByRole("region", { name: "Goals" }); const items = within(card).getAllByRole("listitem"); expect(items).toHaveLength(3); expect(items[0]).toHaveTextContent(title("first-own-delivery")); expect(items[0]).toHaveTextContent( `+${content.onboardingGoal("first-own-delivery")!.reward.toLocaleString("en-US")} cr`, ); expect(items[2]).toHaveTextContent(title("second-ship")); }); it("shows Claim only on ready goals", async () => { renderApp(fakeApi({ getPlayerState: () => owner(statesWith(["first-skill-point"])) })); const card = await screen.findByRole("region", { name: "Goals" }); const buttons = within(card).getAllByRole("button", { name: "Claim" }); expect(buttons).toHaveLength(1); expect(buttons[0]!.closest("li")).toHaveTextContent(title("first-skill-point")); }); it("claims through the endpoint, and the next goal moves into view", async () => { let claimed = false; const api = fakeApi({ getPlayerState: () => owner( claimed ? statesWith([], ["first-own-delivery"]) : statesWith(["first-own-delivery"]), ), claimGoal: () => { claimed = true; return { company: { id: "c", name: "D", credits: 400, loanBalance: 4000 } }; }, }); renderApp(api); const card = await screen.findByRole("region", { name: "Goals" }); expect(card).not.toHaveTextContent(title("first-hire")); await userEvent.click(within(card).getByRole("button", { name: "Claim" })); expect(api.call).toHaveBeenCalledWith("claimGoal", { goalId: "first-own-delivery" }); await waitFor(() => expect(card).toHaveTextContent(title("first-hire"))); expect(card).not.toHaveTextContent(title("first-own-delivery")); }); it("is not shown during the tutorial", async () => { renderApp(fakeApi({ getPlayerState: () => samplePlayerState() })); await screen.findByRole("heading", { level: 1, name: "HQ" }); expect(screen.queryByRole("region", { name: "Goals" })).not.toBeInTheDocument(); }); });