deadhead-space-freight-tycoon/apps/web/test/contract-card.test.tsx

85 lines
2.6 KiB
TypeScript

import type { Contract, Ship } from "@deadhead/schema";
import { screen, within } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { realTimeOf } from "../src/components/Goods";
import { fakeApi, renderApp, samplePlayerState, shipExtras } from "./render";
const NOW = Date.now();
const job = (overrides: Partial<Contract>): Contract => ({
id: "j",
originId: "earth",
destinationId: "moon",
cargoTypeId: "high-value",
goodId: "medical-supplies",
shipper: "Meridian Health",
priority: false,
deliveryWindowGameHours: null,
tier: 1,
massTonnes: 6,
payout: 3_210,
requiredSkill: { skillId: "expensive-cargo", level: 1 },
requiredLongHaulLevel: 0,
offeredAt: NOW,
expiresAt: NOW + 600_000,
firstContact: false,
...overrides,
});
const ship = (modelId: string): Ship => ({
id: modelId,
modelId,
name: `My ${modelId}`,
status: "idle",
locationId: "earth",
dispatchId: null,
pilotId: null,
lastArrivalAt: 0,
...shipExtras(modelId),
});
function render(contracts: Contract[], ships: Ship[]) {
renderApp(
fakeApi({
getPlayerState: () =>
samplePlayerState({ tutorial: null, bays: [{ id: "b", locationId: "earth" }], ships }),
getContractBoard: () => ({ contracts, periodEndsAt: NOW + 600_000 }),
}),
"/contracts?location=earth",
);
}
const card = async (payout: string) => (await screen.findByText(payout)).closest("li")!;
describe("contract card (CR-007)", () => {
it("shows the good, its class and tier, the shipper, mass and requirement", async () => {
render([job({})], [ship("courier")]);
const c = await card("3,210 cr");
expect(within(c).getByRole("heading", { name: "Medical Supplies" })).toBeInTheDocument();
expect(c).toHaveTextContent("High-Value · T1");
expect(c).toHaveTextContent("Meridian Health · 6 t");
expect(c).toHaveTextContent("Needs Expensive Cargo 1");
expect(c).not.toHaveTextContent("Priority");
});
it("shows a Priority window in game hours, and real time on tap", async () => {
render(
[
job({
goodId: "machine-parts",
cargoTypeId: "heavy",
priority: true,
deliveryWindowGameHours: 5,
}),
],
[ship("courier")],
);
const c = await card("3,210 cr");
// A Priority good can have its own name.
expect(within(c).getByRole("heading", { name: "Emergency Parts" })).toBeInTheDocument();
// The window follows the countdown preference: real time by default (CR-011).
expect(c).toHaveTextContent(`Priority · within ${realTimeOf(5)}`);
expect(c).not.toHaveTextContent("Too slow");
});
});