113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
import type { Dispatch, Pilot, Ship } from "@deadhead/schema";
|
|
import { screen, within } from "@testing-library/react";
|
|
import { describe, expect, it } from "vitest";
|
|
import { fuelPriceOf, formatFuelPrice } from "../src/components/Fuel";
|
|
import { fakeApi, renderApp, samplePlayerState, shipExtras } from "./render";
|
|
|
|
const ship = (id: string, name: string, overrides: Partial<Ship> = {}): Ship => ({
|
|
id,
|
|
modelId: "courier",
|
|
name,
|
|
status: "idle",
|
|
locationId: "earth",
|
|
dispatchId: null,
|
|
lastArrivalAt: 0,
|
|
...shipExtras("courier"),
|
|
pilotId: null,
|
|
...overrides,
|
|
});
|
|
|
|
const avatar = samplePlayerState().pilots[0]!;
|
|
const spare: Pilot = { ...avatar, id: "p2", name: "Rae Okafor", isAvatar: false, level: 2 };
|
|
|
|
const inbound: Dispatch = {
|
|
id: "d1",
|
|
shipId: "s-fly",
|
|
pilotId: "avatar",
|
|
contract: null,
|
|
originId: "moon",
|
|
destinationId: "earth",
|
|
tutorial: false,
|
|
departureAt: Date.now() - 60_000,
|
|
arrivalAt: Date.now() + 180_000,
|
|
distanceMillionKm: 0.39,
|
|
fuelCost: 50,
|
|
fuelBurnedFu: 0,
|
|
expectedPayout: 0,
|
|
seed: 1,
|
|
status: "in-flight",
|
|
resolvedAt: null,
|
|
};
|
|
|
|
function render(bays: { id: string; locationId: string }[]) {
|
|
renderApp(
|
|
fakeApi({
|
|
getPlayerState: () =>
|
|
samplePlayerState({
|
|
tutorial: null,
|
|
bays,
|
|
ships: [
|
|
ship("s1", "Dusty Mule"),
|
|
ship("s2", "Moon Moth", { locationId: "moon" }),
|
|
ship("s-fly", "Swift Heron", {
|
|
status: "in-flight",
|
|
locationId: null,
|
|
dispatchId: "d1",
|
|
}),
|
|
],
|
|
pilots: [
|
|
{ ...avatar, assignedShipId: "s-fly", status: "in-flight", locationId: null },
|
|
spare,
|
|
],
|
|
activeDispatches: [inbound],
|
|
}),
|
|
}),
|
|
"/hqs",
|
|
);
|
|
}
|
|
|
|
describe("HQs screen (CR-020)", () => {
|
|
it("shows each HQ's ships, inbound flights, spare pilots and fuel price", async () => {
|
|
render([{ id: "b1", locationId: "earth" }]);
|
|
const hq = await screen.findByRole("listitem", { name: "HQ at Earth" });
|
|
expect(hq).toHaveTextContent(`Fuel: ${formatFuelPrice(fuelPriceOf("earth"))}`);
|
|
const ships = within(hq).getByRole("region", { name: "Ships at Earth" });
|
|
expect(ships).toHaveTextContent("Dusty Mule");
|
|
expect(ships).not.toHaveTextContent("Moon Moth");
|
|
expect(within(hq).getByRole("region", { name: "Inbound to Earth" })).toHaveTextContent(
|
|
"Swift Heron from Moon",
|
|
);
|
|
expect(within(hq).getByRole("region", { name: "Pilots at Earth" })).toHaveTextContent(
|
|
"Rae OkaforLevel 2",
|
|
);
|
|
expect(within(hq).getByRole("link", { name: "View contracts" })).toHaveAttribute(
|
|
"href",
|
|
"/contracts?location=earth",
|
|
);
|
|
expect(within(hq).getByRole("link", { name: "Hire pilots" })).toHaveAttribute(
|
|
"href",
|
|
"/pilots",
|
|
);
|
|
});
|
|
|
|
it("lists one card per HQ", async () => {
|
|
render([
|
|
{ id: "b1", locationId: "earth" },
|
|
{ id: "b2", locationId: "moon" },
|
|
]);
|
|
expect(await screen.findByRole("listitem", { name: "HQ at Moon" })).toHaveTextContent(
|
|
"Moon Moth",
|
|
);
|
|
expect(screen.getAllByRole("listitem", { name: /^HQ at / })).toHaveLength(2);
|
|
});
|
|
|
|
it("points to Places when the player has no HQ", async () => {
|
|
render([]);
|
|
expect(await screen.findByText("You don't have an HQ yet.")).toBeInTheDocument();
|
|
expect(screen.getByRole("link", { name: "Lease one in Places" })).toHaveAttribute(
|
|
"href",
|
|
"/locations",
|
|
);
|
|
});
|
|
});
|