127 lines
3.9 KiB
TypeScript
127 lines
3.9 KiB
TypeScript
import { content } from "@deadhead/content";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
upgradeCost,
|
|
upgradeShopMs,
|
|
validateDispatch,
|
|
validateUpgrade,
|
|
type Contract,
|
|
type PilotState,
|
|
type ShipState,
|
|
type UpgradeProposal,
|
|
} from "../src/index";
|
|
|
|
/** Fuel enough for any leg in these tests (decision 0.5.94), bought at 10 cr/fu. */
|
|
const PLENTY = { fuelFu: 10_000, avgPrice: 10 };
|
|
|
|
const now = Date.parse("2100-01-01T00:30:00Z");
|
|
const freighter = content.shipModel("freighter")!;
|
|
const engines = content.upgrade("engines")!;
|
|
const ship: ShipState = {
|
|
id: "s1",
|
|
modelId: "freighter",
|
|
locationId: "earth",
|
|
inFlight: false,
|
|
tank: PLENTY,
|
|
};
|
|
const valid: UpgradeProposal = {
|
|
ship,
|
|
upgrade: engines,
|
|
atHq: true,
|
|
tutorialActive: false,
|
|
credits: 1_000_000,
|
|
now,
|
|
};
|
|
const reason = (proposal: UpgradeProposal) => {
|
|
const result = validateUpgrade(proposal, content);
|
|
return result.ok ? "valid" : result.reason;
|
|
};
|
|
|
|
describe("upgrade cost and shop time (Step 10I.3)", () => {
|
|
it("costs 10 % of a Freighter's price at level 1 and 35 % at level 3", () => {
|
|
expect(upgradeCost(freighter, 1, content.config)).toBe(freighter.price * 0.1);
|
|
expect(upgradeCost(freighter, 3, content.config)).toBe(freighter.price * 0.35);
|
|
expect(upgradeShopMs(2, content.config)).toBe(20 * 60_000);
|
|
});
|
|
|
|
it("starts the next level, with its cost and shop time", () => {
|
|
expect(
|
|
validateUpgrade({ ...valid, ship: { ...ship, upgrades: { engines: 1 } } }, content),
|
|
).toEqual({
|
|
ok: true,
|
|
level: 2,
|
|
cost: upgradeCost(freighter, 2, content.config),
|
|
shopUntil: now + upgradeShopMs(2, content.config),
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("upgrade validation (Step 10I.3)", () => {
|
|
it("accepts a valid upgrade", () => expect(reason(valid)).toBe("valid"));
|
|
it("refuses during the tutorial", () =>
|
|
expect(reason({ ...valid, tutorialActive: true })).toBe("tutorial-active"));
|
|
it("refuses the company loaner", () =>
|
|
expect(reason({ ...valid, ship: { ...ship, modelId: "company-courier" } })).toBe(
|
|
"not-upgradable",
|
|
));
|
|
it("refuses a ship in flight", () =>
|
|
expect(reason({ ...valid, ship: { ...ship, inFlight: true } })).toBe("ship-not-idle"));
|
|
it("refuses a ship already in the shop", () =>
|
|
expect(reason({ ...valid, ship: { ...ship, inShopUntil: now + 1000 } })).toBe("ship-in-shop"));
|
|
it("refuses away from an HQ", () => expect(reason({ ...valid, atHq: false })).toBe("not-at-hq"));
|
|
it("refuses a maxed upgrade", () =>
|
|
expect(reason({ ...valid, ship: { ...ship, upgrades: { engines: 3 } } })).toBe(
|
|
"upgrade-maxed",
|
|
));
|
|
it("refuses without the credits", () =>
|
|
expect(reason({ ...valid, credits: upgradeCost(freighter, 1, content.config) - 1 })).toBe(
|
|
"insufficient-funds",
|
|
));
|
|
});
|
|
|
|
describe("ships in the shop can't fly (Step 10I.3)", () => {
|
|
const pilot: PilotState = {
|
|
id: "p1",
|
|
isAvatar: false,
|
|
assignedShipId: "s1",
|
|
inFlight: false,
|
|
skills: {},
|
|
restEndsAt: null,
|
|
};
|
|
const contract: Contract = {
|
|
id: "c1",
|
|
originId: "earth",
|
|
destinationId: "moon",
|
|
cargoTypeId: "standard",
|
|
goodId: "consumer-goods",
|
|
shipper: "Pacific Orbital Logistics",
|
|
priority: false,
|
|
deliveryWindowGameHours: null,
|
|
tier: 0,
|
|
massTonnes: 10,
|
|
payout: 2000,
|
|
requiredSkill: null,
|
|
requiredLongHaulLevel: 0,
|
|
offeredAt: now,
|
|
expiresAt: now + 3_600_000,
|
|
firstContact: false,
|
|
};
|
|
const at = (time: number, shopUntil: number) =>
|
|
validateDispatch(
|
|
{
|
|
ship: { ...ship, inShopUntil: shopUntil },
|
|
pilot,
|
|
contract,
|
|
tutorial: false,
|
|
now: time,
|
|
},
|
|
content,
|
|
);
|
|
|
|
it("fails ship-in-shop one second before in-shop-until and passes at it", () => {
|
|
const until = now + 10 * 60_000;
|
|
expect(at(until - 1000, until)).toEqual({ ok: false, reason: "ship-in-shop" });
|
|
expect(at(until, until)).toEqual({ ok: true });
|
|
});
|
|
});
|