deadhead-space-freight-tycoon/apps/web/test/effective-stats-ui.test.tsx

122 lines
4.0 KiB
TypeScript

import { content } from "@deadhead/content";
import type { Contract, Pilot, Ship } from "@deadhead/schema";
import { gameToReal, realToGame, routeDistance } from "@deadhead/sim";
import { screen, 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";
/** Mars at its closest in 16 game years (~59M km, month 176; decision 0.5.68). */
const gameStart = realToGame(Date.parse(content.config.epoch.realStart), content.config);
const NOW = gameToReal(gameStart + 176 * 30.44 * 24 * 3_600_000, content.config);
const courier = (upgrades: Record<string, number>): Ship => ({
id: "s1",
modelId: "courier",
name: "Dusty Mule",
status: "idle",
locationId: "earth",
dispatchId: null,
pilotId: "p1",
lastArrivalAt: 0,
...shipExtras("courier", upgrades),
});
const pilot: Pilot = {
id: "p1",
name: "Rae Okafor",
isAvatar: false,
isVeteran: false,
xp: 0,
level: 0,
skills: {},
skillPointsAvailable: 0,
assignedShipId: "s1",
status: "idle",
locationId: "earth",
dutyHours: 0,
dutyLimit: 12,
resting: false,
restEndsAt: null,
};
/** 22 t: one tonne more than a base Courier's 20, within a Cargo Bay 1 Courier's 23. */
const job: Contract = {
id: "c22",
originId: "earth",
destinationId: "moon",
cargoTypeId: "standard",
goodId: "consumer-goods",
shipper: "Pacific Orbital Logistics",
priority: false,
deliveryWindowGameHours: null,
tier: 0,
massTonnes: 22,
payout: 1234,
requiredSkill: null,
requiredLongHaulLevel: 0,
offeredAt: NOW,
expiresAt: NOW + 30 * 60_000,
firstContact: false,
};
const api = (upgrades: Record<string, number>) =>
fakeApi({
getPlayerState: () =>
samplePlayerState({
tutorial: null,
company: { id: "c", name: "D", credits: 1_000_000, loanBalance: 0 },
bays: [{ id: "b", locationId: "earth" }],
ships: [courier(upgrades)],
pilots: [pilot],
locations: content.locations.map((l) => ({
id: l.id,
discovered: ["earth", "moon", "mars"].includes(l.id),
})),
}),
getContractBoard: () => ({ contracts: [job], periodEndsAt: NOW + 600_000 }),
});
describe("effective stats in the client (Step 10I.7)", () => {
beforeEach(() => {
vi.useFakeTimers({ toFake: ["Date", "setInterval", "clearInterval"] });
vi.setSystemTime(NOW);
useClock.setState({ offsetMs: 0, synced: true, now: NOW });
});
afterEach(() => vi.useRealTimers());
it("drops the Too heavy badge once the cargo bay is expanded", async () => {
const { unmount } = renderApp(api({}), "/contracts?location=earth");
expect((await screen.findByText("1,234 cr")).closest("li")!).toHaveTextContent("Too heavy");
unmount();
renderApp(api({ "cargo-bay": 1 }), "/contracts?location=earth");
expect((await screen.findByText("1,234 cr")).closest("li")!).not.toHaveTextContent("Too heavy");
});
it("lets the deadhead picker reach Mars only with upgraded fuel tanks", async () => {
const distance = routeDistance(
content.location("earth")!,
content.location("mars")!,
realToGame(NOW, content.config),
);
// Between a level-2 Courier's reach (145) and a maxed one's (215) on the fixed map.
expect(distance).toBeGreaterThan(145);
expect(distance).toBeLessThan(215);
const open = async () => {
const card = (await screen.findByText("Dusty Mule")).closest("li")!;
await userEvent.click(within(card).getByRole("button", { name: /Deadhead/ }));
return within(screen.getByRole("dialog", { name: "Deadhead Dusty Mule" })).getByRole(
"button",
{ name: "Mars" },
);
};
const { unmount } = renderApp(api({}), "/fleet");
expect(await open()).toBeDisabled();
unmount();
renderApp(api({ "fuel-tanks": 3 }), "/fleet");
expect(await open()).toBeEnabled();
});
});