deadhead-space-freight-tycoon/apps/web/test/goals.test.tsx

73 lines
3.0 KiB
TypeScript

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("market-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("priority-contract"));
await userEvent.click(within(card).getByRole("button", { name: "Claim" }));
expect(api.call).toHaveBeenCalledWith("claimGoal", { goalId: "first-own-delivery" });
await waitFor(() => expect(card).toHaveTextContent(title("priority-contract")));
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: "Bridge" });
expect(screen.queryByRole("region", { name: "Goals" })).not.toBeInTheDocument();
});
});