deadhead-space-freight-tycoon/apps/web/test/dev-tools.test.tsx

110 lines
4.3 KiB
TypeScript

import type { Dispatch } 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";
describe("developer tools in Settings (Step 10K.11)", () => {
it("advances the clock, adds credits and finishes flights", async () => {
const now = Date.now();
const flight = {
id: "d1",
shipId: "loaner",
pilotId: "avatar",
contract: null,
originId: "earth",
destinationId: "moon",
tutorial: true,
departureAt: now - 60_000,
arrivalAt: now + 5 * 60_000,
distanceMillionKm: 0.4,
fuelCost: 0,
fuelBurnedFu: 0,
expectedPayout: 0,
seed: 1,
status: "in-flight",
resolvedAt: null,
} as unknown as Dispatch;
const api = fakeApi({
getPlayerState: () => samplePlayerState({ activeDispatches: [flight] }),
devAdvanceClock: ({ advanceMs }) => ({ offsetMs: advanceMs, realTime: now + advanceMs }),
devAddCredits: ({ amount }) => ({
company: { id: "co1", name: "D", credits: amount, loanBalance: 0 },
}),
});
renderApp(api, "/settings");
const dev = await screen.findByRole("region", { name: "Developer" });
await userEvent.click(within(dev).getByRole("button", { name: "Advance 10 minutes" }));
await waitFor(() =>
expect(api.call).toHaveBeenCalledWith("devAdvanceClock", { advanceMs: 600_000 }),
);
await userEvent.click(within(dev).getByRole("button", { name: "Advance 1 hour" }));
await waitFor(() =>
expect(api.call).toHaveBeenCalledWith("devAdvanceClock", { advanceMs: 3_600_000 }),
);
await userEvent.click(within(dev).getByRole("button", { name: "Add 10,000 credits" }));
await waitFor(() => expect(api.call).toHaveBeenCalledWith("devAddCredits", { amount: 10_000 }));
await userEvent.click(within(dev).getByRole("button", { name: "Finish all flights" }));
await waitFor(() => {
const advances = api.call.mock.calls.filter(([name]) => name === "devAdvanceClock");
const last = advances.at(-1)![1] as { advanceMs: number };
// To just past the last arrival (5 minutes away), give or take the test's own runtime.
expect(last.advanceMs).toBeGreaterThan(5 * 60_000 - 5_000);
expect(last.advanceMs).toBeLessThan(5 * 60_000 + 5_000);
});
});
it("levels a pilot, maxes a ship's upgrades, moves it and discovers everywhere", async () => {
const base = samplePlayerState({ tutorial: null });
const state = {
...base,
ships: [
{
id: "s1",
modelId: "courier",
name: "Dusty Mule",
status: "idle" as const,
locationId: "earth",
dispatchId: null,
lastArrivalAt: 0,
...shipExtras("courier"),
pilotId: "avatar",
},
],
pilots: [{ ...base.pilots[0]!, assignedShipId: "s1" }],
};
const api = fakeApi({
getPlayerState: () => state,
devPilot: () => state,
devShip: () => state,
devDiscoverAll: () => state,
});
renderApp(api, "/settings");
const dev = await screen.findByRole("region", { name: "Developer" });
await userEvent.click(within(dev).getByRole("button", { name: "Level up" }));
await waitFor(() =>
expect(api.call).toHaveBeenCalledWith("devPilot", { pilotId: "avatar", action: "level-up" }),
);
await userEvent.click(within(dev).getByRole("button", { name: "Max upgrades" }));
await waitFor(() =>
expect(api.call).toHaveBeenCalledWith("devShip", { shipId: "s1", action: "max-upgrades" }),
);
// Already at Earth: pick the Moon, then move.
expect(within(dev).getByRole("button", { name: "Move here" })).toBeDisabled();
await userEvent.selectOptions(within(dev).getByLabelText("Move to"), "moon");
await userEvent.click(within(dev).getByRole("button", { name: "Move here" }));
await waitFor(() =>
expect(api.call).toHaveBeenCalledWith("devShip", {
shipId: "s1",
action: "move",
locationId: "moon",
}),
);
await userEvent.click(within(dev).getByRole("button", { name: "Discover everywhere" }));
await waitFor(() => expect(api.call).toHaveBeenCalledWith("devDiscoverAll", {}));
});
});