82 lines
3.1 KiB
TypeScript
82 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { shipModelSchema, shipModels, gameConfig } from "../src/index";
|
|
|
|
const ship = (id: string) => shipModels.find((s) => s.id === id)!;
|
|
|
|
describe("ship models", () => {
|
|
it("all pass the schema", () => {
|
|
for (const model of shipModels) {
|
|
expect(() => shipModelSchema.parse(model)).not.toThrow();
|
|
}
|
|
});
|
|
|
|
// CR-012 §2 replaces the Step 2.3 ordering tests.
|
|
const order = (
|
|
key: "price" | "cruiseSpeedKmPerGameHour" | "cargoCapacityTonnes",
|
|
ids: string[],
|
|
) =>
|
|
ids
|
|
.slice(1)
|
|
.forEach((id, i) =>
|
|
expect(ship(id)[key], `${ids[i]} < ${id}`).toBeGreaterThan(ship(ids[i]!)[key]),
|
|
);
|
|
const purchasable = shipModels.filter((m) => m.purchasable);
|
|
const handling = (id: string) =>
|
|
ship(id).handlingGameHoursPerTonne ?? gameConfig.handlingGameHoursPerTonne;
|
|
|
|
it("has five purchasable models plus the loaner, all atmospheric", () => {
|
|
expect(shipModels.map((s) => s.id)).toEqual([
|
|
"courier",
|
|
"lighter",
|
|
"clipper",
|
|
"freighter",
|
|
"bulk-hauler",
|
|
"company-courier",
|
|
]);
|
|
for (const model of shipModels) {
|
|
expect(model.landingClass).toBe("atmospheric");
|
|
expect(model.role.length).toBeGreaterThan(10);
|
|
}
|
|
expect(ship("lighter").purchasable && ship("clipper").purchasable).toBe(true);
|
|
});
|
|
|
|
it("orders price Courier < Lighter < Clipper < Freighter < Bulk Hauler", () => {
|
|
order("price", ["courier", "lighter", "clipper", "freighter", "bulk-hauler"]);
|
|
});
|
|
|
|
it("makes the Clipper fastest, the Bulk Hauler slowest, and the Lighter slower than the Freighter", () => {
|
|
const speeds = shipModels.map((m) => m.cruiseSpeedKmPerGameHour);
|
|
expect(ship("clipper").cruiseSpeedKmPerGameHour).toBe(Math.max(...speeds));
|
|
expect(ship("bulk-hauler").cruiseSpeedKmPerGameHour).toBe(
|
|
Math.min(...purchasable.map((m) => m.cruiseSpeedKmPerGameHour)),
|
|
);
|
|
order("cruiseSpeedKmPerGameHour", ["bulk-hauler", "lighter", "freighter"]);
|
|
});
|
|
|
|
it("orders capacity Courier < Clipper < Lighter < Freighter < Bulk Hauler", () => {
|
|
order("cargoCapacityTonnes", ["courier", "clipper", "lighter", "freighter", "bulk-hauler"]);
|
|
const lighterShare =
|
|
ship("lighter").cargoCapacityTonnes / ship("freighter").cargoCapacityTonnes;
|
|
expect(lighterShare).toBeGreaterThanOrEqual(0.75);
|
|
expect(lighterShare).toBeLessThanOrEqual(0.9);
|
|
});
|
|
|
|
it("gives the Lighter the fastest loading and the Clipper costly fuel", () => {
|
|
for (const m of shipModels) {
|
|
if (m.id !== "lighter") expect(handling("lighter")).toBeLessThan(handling(m.id));
|
|
}
|
|
expect(ship("clipper").fuelCostPerMillionKm).toBeGreaterThan(
|
|
ship("courier").fuelCostPerMillionKm,
|
|
);
|
|
expect(ship("clipper").fuelCostPerMillionKm).toBeGreaterThan(
|
|
ship("freighter").fuelCostPerMillionKm,
|
|
);
|
|
});
|
|
|
|
it("gives every ship model its own map sprite key (CR-003)", () => {
|
|
const sprites = shipModels.map((x) => x.sprite);
|
|
for (const sprite of sprites) expect(sprite).toMatch(/^[a-z][a-z-]*$/);
|
|
expect(new Set(sprites).size).toBe(sprites.length);
|
|
});
|
|
});
|