deadhead-space-freight-tycoon/apps/web/test/needs-you.test.tsx

72 lines
2.7 KiB
TypeScript

import type { PlayerState, RadioCall, Ship } from "@deadhead/schema";
import { screen, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import { needsYou } from "../src/components/NeedsYou";
import { tabAttention } from "../src/layout/attention";
import { fakeApi, renderApp, samplePlayerState, shipExtras } from "./render";
const base = samplePlayerState();
const avatar = base.pilots[0]!;
const ship: Ship = {
id: "s1",
modelId: "courier",
name: "Restless Sparrow",
status: "idle",
locationId: "earth",
dispatchId: null,
lastArrivalAt: 0,
...shipExtras("courier"),
pilotId: "avatar",
};
const owner = (overrides: Partial<PlayerState> = {}): PlayerState =>
samplePlayerState({
tutorial: null,
ships: [ship],
bays: [{ id: "b", locationId: "earth" }],
pilots: [{ ...avatar, assignedShipId: "s1", skillPointsAvailable: 2 }],
goals: [{ id: "buy-a-ship", status: "ready" }],
...overrides,
} as Partial<PlayerState>);
const call = { dispatchId: "d1", eventId: "debris-field", pilotId: avatar.id } as RadioCall;
describe("Needs you (decision 0.5.168)", () => {
it("orders radio calls, ready ships, skill points, then goals", () => {
const items = needsYou(owner({ radioCalls: [{ ...call, windowEndsAt: 1 }] }));
expect(items.map((i) => i.kind)).toEqual(["radio", "ready", "skills", "goal"]);
});
it("badges count what the list holds, tab by tab", () => {
const state = owner({ radioCalls: [{ ...call, windowEndsAt: 1 }] });
const items = needsYou(state);
const badges = tabAttention(state);
expect(badges).toEqual({ "/": 2, "/contracts": 1, "/fleet": 2 });
const total = items.reduce((sum, i) => sum + i.count, 0);
expect(Object.values(badges).reduce((sum, n) => sum + n, 0)).toBe(total);
});
it("names who has skill points and opens Crew", async () => {
renderApp(fakeApi({ getPlayerState: () => owner() }));
const list = await screen.findByRole("region", { name: "Needs you" });
await userEvent.click(within(list).getByRole("link", { name: /2 skill points to spend/ }));
expect(await screen.findByRole("heading", { level: 1, name: "Crew" })).toBeInTheDocument();
});
it("sends a ready ship to the jobs where it is", async () => {
renderApp(
fakeApi({
getPlayerState: () => owner(),
getContractBoard: () => ({ contracts: [], periodEndsAt: Date.now() + 60_000 }) as never,
}),
);
const list = await screen.findByRole("region", { name: "Needs you" });
expect(within(list).getByRole("link", { name: /Restless Sparrow is ready/ })).toHaveAttribute(
"href",
"/contracts?location=earth",
);
});
});