165 lines
5.0 KiB
TypeScript
165 lines
5.0 KiB
TypeScript
import type { ResolutionSummary, Ship } from "@deadhead/schema";
|
|
import { screen, waitFor, within } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { describe, expect, it } from "vitest";
|
|
import { fakeApi, renderApp, samplePlayerState, shipExtras } from "./render";
|
|
|
|
const ship: Ship = {
|
|
id: "s1",
|
|
modelId: "courier",
|
|
name: "Dusty Mule",
|
|
status: "idle",
|
|
locationId: "mars",
|
|
dispatchId: null,
|
|
lastArrivalAt: 0,
|
|
...shipExtras("courier"),
|
|
pilotId: "avatar",
|
|
};
|
|
|
|
const summaries: ResolutionSummary[] = [
|
|
{
|
|
dispatchId: "d1",
|
|
shipId: "s1",
|
|
pilotId: "avatar",
|
|
originId: "earth",
|
|
destinationId: "mars",
|
|
tutorial: false,
|
|
credits: 51_200,
|
|
deadhead: false,
|
|
independent: false,
|
|
fuelCost: 0,
|
|
topUp: null,
|
|
goodId: "consumer-goods",
|
|
massTonnes: 12,
|
|
shipper: "Pacific Orbital Logistics",
|
|
loanRepayment: 0,
|
|
pilotPay: 0,
|
|
pilotXp: 32,
|
|
discoveredLocationId: "mars",
|
|
scriptedId: null,
|
|
restEndsAt: null,
|
|
resolvedAt: 1,
|
|
},
|
|
{
|
|
dispatchId: "d2",
|
|
shipId: "loaner",
|
|
pilotId: "avatar",
|
|
originId: "moon",
|
|
destinationId: "earth",
|
|
tutorial: true,
|
|
credits: 240,
|
|
deadhead: false,
|
|
independent: false,
|
|
fuelCost: 0,
|
|
topUp: null,
|
|
goodId: "consumer-goods",
|
|
massTonnes: 12,
|
|
shipper: "Pacific Orbital Logistics",
|
|
loanRepayment: 0,
|
|
pilotPay: 0,
|
|
pilotXp: 10,
|
|
discoveredLocationId: null,
|
|
scriptedId: null,
|
|
restEndsAt: null,
|
|
resolvedAt: 2,
|
|
},
|
|
];
|
|
|
|
describe("while you were away", () => {
|
|
it("names what was delivered, how much, for whom and where (CR-007)", async () => {
|
|
const delivery: ResolutionSummary = {
|
|
...summaries[0]!,
|
|
destinationId: "moon",
|
|
goodId: "medical-supplies",
|
|
massTonnes: 6,
|
|
shipper: "Meridian Health",
|
|
discoveredLocationId: null,
|
|
};
|
|
renderApp(
|
|
fakeApi({
|
|
getPlayerState: () =>
|
|
samplePlayerState({ tutorial: null, ships: [ship], summaries: [delivery] }),
|
|
}),
|
|
);
|
|
const dialog = await screen.findByRole("dialog", { name: "While you were away" });
|
|
expect(within(dialog).getAllByRole("listitem")[0]).toHaveTextContent(
|
|
"Delivered 6 t Medical Supplies for Meridian Health to the Moon",
|
|
);
|
|
});
|
|
|
|
it("shows a deadhead as an empty flight with its fuel, not as a +0 payout", async () => {
|
|
const deadhead: ResolutionSummary = {
|
|
...summaries[0]!,
|
|
dispatchId: "d3",
|
|
destinationId: "moon",
|
|
deadhead: true,
|
|
independent: false,
|
|
fuelCost: 230,
|
|
topUp: null,
|
|
goodId: null,
|
|
massTonnes: null,
|
|
shipper: null,
|
|
credits: 0,
|
|
pilotXp: 0,
|
|
discoveredLocationId: null,
|
|
};
|
|
renderApp(
|
|
fakeApi({
|
|
getPlayerState: () =>
|
|
samplePlayerState({ tutorial: null, ships: [ship], summaries: [deadhead] }),
|
|
}),
|
|
);
|
|
const dialog = await screen.findByRole("dialog", { name: "While you were away" });
|
|
const entry = within(dialog).getAllByRole("listitem")[0]!;
|
|
expect(entry).toHaveTextContent("Dusty Mule");
|
|
expect(entry).toHaveTextContent("Earth → Moon");
|
|
expect(entry).toHaveTextContent("Deadhead · 230 cr fuel");
|
|
expect(entry).not.toHaveTextContent("+0 cr");
|
|
expect(entry).not.toHaveTextContent("XP");
|
|
expect(entry).not.toHaveTextContent("Delivered");
|
|
});
|
|
|
|
it("lists each completed delivery, and dismissing acknowledges them and hides the dialog", async () => {
|
|
let acknowledged = false;
|
|
const api = fakeApi({
|
|
getPlayerState: () =>
|
|
samplePlayerState({
|
|
tutorial: null,
|
|
ships: [ship],
|
|
summaries: acknowledged ? [] : summaries,
|
|
}),
|
|
acknowledgeSummaries: ({ dispatchIds }) => {
|
|
acknowledged = true;
|
|
return { acknowledged: dispatchIds.length };
|
|
},
|
|
});
|
|
renderApp(api);
|
|
|
|
const dialog = await screen.findByRole("dialog", { name: "While you were away" });
|
|
const items = within(dialog).getAllByRole("listitem");
|
|
expect(items).toHaveLength(2);
|
|
|
|
expect(items[0]).toHaveTextContent("Dusty Mule");
|
|
expect(items[0]).toHaveTextContent("Earth → Mars");
|
|
expect(items[0]).toHaveTextContent("+51,200 cr");
|
|
expect(items[0]).toHaveTextContent("+32 XP");
|
|
expect(items[0]).toHaveTextContent("Discovered Mars!");
|
|
|
|
expect(items[1]).toHaveTextContent("Company loaner");
|
|
expect(items[1]).toHaveTextContent("Moon → Earth");
|
|
expect(items[1]).not.toHaveTextContent("Discovered");
|
|
|
|
await userEvent.click(within(dialog).getByRole("button", { name: "Got it" }));
|
|
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
await waitFor(() =>
|
|
expect(api.call).toHaveBeenCalledWith("acknowledgeSummaries", { dispatchIds: ["d1", "d2"] }),
|
|
);
|
|
});
|
|
|
|
it("does not show the dialog when there is nothing to report", async () => {
|
|
renderApp(fakeApi({ getPlayerState: () => samplePlayerState() }));
|
|
await screen.findByRole("heading", { level: 1, name: "Dashboard" });
|
|
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
});
|
|
});
|