deadhead-space-freight-tycoon/apps/web/test/shop-summary-hq.test.tsx

94 lines
3.2 KiB
TypeScript

import type { Ship } from "@deadhead/schema";
import { screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { useClock } from "../src/clock/clock";
import { fakeApi, renderApp, samplePlayerState, shipExtras } from "./render";
const NOW = Date.parse("2100-01-01T00:00:00Z");
const ship = (id: string, name: string, overrides: Partial<Ship>): Ship => ({
id,
name,
modelId: "freighter",
status: "idle",
locationId: "earth",
dispatchId: null,
pilotId: null,
lastArrivalAt: 0,
...shipExtras("freighter"),
...overrides,
});
describe("the shop in summaries and on HQ (Step 10I.8)", () => {
beforeEach(() => {
vi.useFakeTimers({ toFake: ["Date", "setInterval", "clearInterval"] });
vi.setSystemTime(NOW);
useClock.setState({ offsetMs: 0, synced: true, now: NOW });
});
afterEach(() => vi.useRealTimers());
it("says a ship is out of the shop for an upgrade that finished, and acknowledges it", async () => {
const api = fakeApi({
getPlayerState: () =>
samplePlayerState({
tutorial: null,
ships: [
ship("s1", "Slow Ox", {
upgrades: { engines: 2 },
shop: { upgradeId: "engines", level: 2, until: NOW - 60_000 },
}),
ship("s2", "Busy Ox", {
upgrades: { "cargo-bay": 1 },
inShopUntil: NOW + 60_000,
shop: { upgradeId: "cargo-bay", level: 1, until: NOW + 60_000 },
}),
],
}),
});
renderApp(api, "/");
const dialog = await screen.findByRole("dialog", { name: /While you were away/ });
await waitFor(() =>
expect(dialog).toHaveTextContent("Slow Ox is out of the shop: Engine Tuning level 2"),
);
expect(dialog).not.toHaveTextContent("Busy Ox");
await userEvent.click(within(dialog).getByRole("button", { name: "Done" }));
await waitFor(() =>
expect(api.call).toHaveBeenCalledWith("acknowledgeSummaries", {
dispatchIds: [],
shipIds: ["s1"],
}),
);
});
it("lists ships in the shop on HQ, soonest first, with countdowns", async () => {
renderApp(
fakeApi({
getPlayerState: () =>
samplePlayerState({
tutorial: null,
ships: [
ship("s1", "Late Ox", {
inShopUntil: NOW + 25 * 60_000,
shop: { upgradeId: "engines", level: 2, until: NOW + 25 * 60_000 },
}),
ship("s2", "Soon Ox", {
inShopUntil: NOW + 4 * 60_000,
shop: { upgradeId: "cargo-bay", level: 1, until: NOW + 4 * 60_000 },
}),
ship("s3", "Free Ox", {}),
],
}),
}),
"/",
);
const card = await screen.findByLabelText("In the shop");
expect(card).toHaveTextContent("In the shop: 2");
const [first, second] = within(card).getAllByRole("listitem");
expect(first).toHaveTextContent("Soon Ox · Cargo Bay Expansion 1 · ready in 4m 00s");
expect(second).toHaveTextContent("Late Ox · Engine Tuning 2 · ready in 25m 00s");
expect(card).not.toHaveTextContent("Free Ox");
});
});