import { describe, expect, it } from "vitest"; import type { z } from "zod"; import { cargoTypeSchema, gameConfigSchema, locationSchema, shipModelSchema, skillSchema, } from "../src/index"; const validLocation = { id: "earth", name: "Earth", type: "atmospheric-world", landingRequirement: "atmospheric", body: "earth", launchCostMultiplier: 3, startsDiscovered: true, bayLeasePrice: 5000, produces: ["standard"], demands: ["heavy"], }; const validShipModel = { id: "courier", name: "Courier", archetype: "courier", price: 20000, cruiseSpeedKmPerGameHour: 300000, cargoCapacityTonnes: 10, fuelRangeMillionKm: 5, hullRating: 1, landingClass: "atmospheric", overheadGameHours: 2, fuelCostPerMillionKm: 100, }; const validCargoType = { id: "standard", name: "Standard", basePayPerTonnePerMillionKm: 10, tierPayMultiplier: 1, requiredSkillId: null, }; const validSkill = { id: "long-haul", name: "Long Haul", maxLevel: 5, description: "Access to longer routes.", }; const validGameConfig = { timeCompression: 60, epoch: { realStart: "2026-01-01T00:00:00Z", ephemerisDate: "2100-01-01T00:00:00Z" }, startingCredits: 0, tutorialPayoutShare: 0.2, contractBoardSize: 8, tutorialBoardSize: 50, contractBoardPeriodRealMinutes: 60, firstContactChance: 0.1, firstContactPayoutMultiplier: 2, contractMassTonnes: { min: 1, max: 100 }, longHaulCutoffsMillionKm: [100, 200, 300, 400, 500], xpPerDelivery: { base: 10, perMillionKm: 0.1, perCargoTier: 5 }, pilotLevelXpThresholds: [100, 250, 500], skillPointsPerLevel: 1, pilotHireCost: 1000, pilotPayPerDelivery: 100, }; const cases: [string, z.ZodType, Record][] = [ ["Location", locationSchema, validLocation], ["ShipModel", shipModelSchema, validShipModel], ["CargoType", cargoTypeSchema, validCargoType], ["Skill", skillSchema, validSkill], ["GameConfig", gameConfigSchema, validGameConfig], ]; describe.each(cases)("%s schema", (_name, schema, valid) => { it("accepts a valid example", () => { expect(schema.safeParse(valid).success).toBe(true); }); it.each(Object.keys(valid))("rejects an object missing %s", (field) => { const missing = { ...valid }; delete missing[field]; expect(schema.safeParse(missing).success).toBe(false); }); }); describe("GameConfig refinements", () => { it("rejects a mass range with min above max", () => { const config = { ...validGameConfig, contractMassTonnes: { min: 50, max: 10 } }; expect(gameConfigSchema.safeParse(config).success).toBe(false); }); it("rejects Long Haul cut-offs that are not increasing", () => { const config = { ...validGameConfig, longHaulCutoffsMillionKm: [100, 100, 300] }; expect(gameConfigSchema.safeParse(config).success).toBe(false); }); });