120 lines
3.8 KiB
TypeScript
120 lines
3.8 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 near closest approach in the first two game years (~82M km, decision 0.5.68). */
|
|
const gameStart = realToGame(Date.parse(content.config.epoch.realStart), content.config);
|
|
const NOW = gameToReal(gameStart + 23 * 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),
|
|
);
|
|
expect(distance).toBeLessThan(95);
|
|
|
|
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();
|
|
});
|
|
});
|