import { describe, expect, it } from "vitest"; import { requireDungeonDefinition } from "./dungeonRegistry"; import { MAX_SYNCHRONOUS_PARTY_NAVIGATION_TRIANGLES, partyObjectivesForNavigation, shouldLoadPartyNavigation, } from "./partyNavigationPolicy"; import type { DungeonDefinition } from "./dungeonTypes"; import type { ManastormStageAssetPackage } from "./manastormStageAssets"; function manastormPackageWithNavigationTriangles( triangleCount: number | undefined, ): Pick { return { navigation: { id: "navigation", url: "/navigation.glb", checksum: "0".repeat(64), compression: "none", triangleCount, }, }; } function dungeonWithNavigation( status: DungeonDefinition["validation"]["status"], triangleCount: number, navigation?: DungeonDefinition["validation"]["navigation"], ): Pick { return { assets: { visual: [], collision: [], navigation: { id: "navigation", fileName: "navigation.glb", triangleCount }, }, validation: { status, navigation, blockers: [], warnings: [] }, }; } describe("party navigation loading policy", () => { it("keeps reviewed, budgeted dungeon navigation enabled", () => { const wailingCaverns = requireDungeonDefinition("wailing-caverns"); expect(shouldLoadPartyNavigation("dungeon", wailingCaverns, null)).toBe(true); }); it("does not schedule Shadowfang Keep's unvalidated oversized navigation graph", () => { const shadowfangKeep = requireDungeonDefinition("shadowfang-keep"); expect(shadowfangKeep.validation.status).toBe("unvalidated"); expect(shadowfangKeep.assets.navigation?.triangleCount).toBeGreaterThan( MAX_SYNCHRONOUS_PARTY_NAVIGATION_TRIANGLES, ); expect(shouldLoadPartyNavigation("dungeon", shadowfangKeep, null)).toBe(false); }); it("keeps unvalidated regular dungeons on breadcrumb following even under budget", () => { expect(shouldLoadPartyNavigation( "dungeon", dungeonWithNavigation("unvalidated", 1_000), null, )).toBe(false); }); it("loads an independently reviewed dungeon navigation graph", () => { expect(shouldLoadPartyNavigation( "dungeon", dungeonWithNavigation("unvalidated", 1_000, "green"), null, )).toBe(true); }); it("protects Manastorm from oversized or unmeasured synchronous graphs", () => { const fallbackDungeon = requireDungeonDefinition("wailing-caverns"); expect(shouldLoadPartyNavigation( "manastorm", fallbackDungeon, manastormPackageWithNavigationTriangles(MAX_SYNCHRONOUS_PARTY_NAVIGATION_TRIANGLES), )).toBe(true); expect(shouldLoadPartyNavigation( "manastorm", fallbackDungeon, manastormPackageWithNavigationTriangles(MAX_SYNCHRONOUS_PARTY_NAVIGATION_TRIANGLES + 1), )).toBe(false); expect(shouldLoadPartyNavigation( "manastorm", fallbackDungeon, manastormPackageWithNavigationTriangles(undefined), )).toBe(false); }); it("exposes objectives only after a usable navigation graph is ready", () => { const objectives = [{ id: "boss", name: "Boss", position: [1, 2, 3] as const }]; expect(partyObjectivesForNavigation(false, objectives)).toEqual([]); expect(partyObjectivesForNavigation(true, objectives)).toBe(objectives); }); });