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): 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) => 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(); }); });