99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
import type { Pilot, ResolutionSummary } from "@deadhead/schema";
|
|
import { screen, within } from "@testing-library/react";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { useClock } from "../src/clock/clock";
|
|
import { formatLocalTime } from "../src/screens/DispatchSheet";
|
|
import { fakeApi, renderApp, samplePlayerState } from "./render";
|
|
|
|
const NOW = Date.parse("2100-01-01T00:00:00Z");
|
|
|
|
const pilot = (id: string, name: string, extra: Partial<Pilot> = {}): Pilot => ({
|
|
id,
|
|
name,
|
|
isAvatar: false,
|
|
isVeteran: false,
|
|
xp: 0,
|
|
level: 0,
|
|
skills: {},
|
|
skillPointsAvailable: 0,
|
|
assignedShipId: null,
|
|
status: "idle",
|
|
locationId: "earth",
|
|
dutyHours: 0,
|
|
dutyLimit: 12,
|
|
resting: false,
|
|
restEndsAt: null,
|
|
...extra,
|
|
});
|
|
|
|
const summary = (extra: Partial<ResolutionSummary>): ResolutionSummary => ({
|
|
dispatchId: "d1",
|
|
shipId: "s1",
|
|
pilotId: "p-rae",
|
|
originId: "earth",
|
|
destinationId: "moon",
|
|
tutorial: false,
|
|
credits: 500,
|
|
deadhead: 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: NOW,
|
|
...extra,
|
|
});
|
|
|
|
const pilots = [
|
|
pilot("p-rae", "Rae Okafor", { resting: true, restEndsAt: NOW + 40 * 60_000 }),
|
|
pilot("p-jun", "Jun Sato", { resting: true, restEndsAt: NOW + 9 * 60_000 }),
|
|
pilot("p-cy", "Cy Fresh"),
|
|
];
|
|
|
|
describe("rest in summaries and on HQ (Step 10D.9)", () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers({ toFake: ["Date", "setInterval", "clearInterval"] });
|
|
vi.setSystemTime(NOW);
|
|
useClock.setState({ offsetMs: 0, synced: true, now: NOW });
|
|
});
|
|
afterEach(() => vi.useRealTimers());
|
|
|
|
it("says in the away summary that a pilot is resting, only for trips that ended in rest", async () => {
|
|
const restEndsAt = NOW + 40 * 60_000;
|
|
renderApp(
|
|
fakeApi({
|
|
getPlayerState: () =>
|
|
samplePlayerState({
|
|
tutorial: null,
|
|
pilots,
|
|
summaries: [
|
|
summary({ dispatchId: "d1", restEndsAt }),
|
|
summary({ dispatchId: "d2", pilotId: "p-cy" }),
|
|
],
|
|
}),
|
|
}),
|
|
"/",
|
|
);
|
|
const dialog = await screen.findByRole("dialog", { name: "While you were away" });
|
|
const [rested, plain] = within(dialog).getAllByRole("listitem");
|
|
expect(rested).toHaveTextContent(`Rae Okafor is resting until ${formatLocalTime(restEndsAt)}`);
|
|
expect(plain).not.toHaveTextContent("resting");
|
|
});
|
|
|
|
it("shows how many pilots are resting and who wakes first", async () => {
|
|
renderApp(
|
|
fakeApi({ getPlayerState: () => samplePlayerState({ tutorial: null, pilots }) }),
|
|
"/",
|
|
);
|
|
const card = await screen.findByLabelText("Pilot rest");
|
|
expect(card).toHaveTextContent("Pilots resting: 2");
|
|
expect(card).toHaveTextContent("Jun Sato wakes in 9m 00s");
|
|
});
|
|
});
|