import { describe, expect, it } from "vitest"; import campaign from "../../dungeon-pipeline/dungeon-campaign.json"; import { requireDungeonDefinition } from "./dungeonRegistry"; import type { DungeonDifficultyVariant, DungeonSourceRecipe } from "./dungeonTypes"; const recipeModules = import.meta.glob( "../../dungeon-pipeline/recipes/*.json", { eager: true, import: "default" }, ); const TBC_DUNGEON_IDS = campaign.dungeons .filter((dungeon) => dungeon.source === "burning-crusade") .map((dungeon) => dungeon.slug); function requireRecipe(dungeonId: string): DungeonSourceRecipe { const path = `../../dungeon-pipeline/recipes/${dungeonId}.json`; const recipe = recipeModules[path]; if (!recipe) throw new Error(`Missing Burning Crusade recipe: ${path}`); return recipe; } function expectSelectableDifficultyContract( label: string, variants: readonly DungeonDifficultyVariant[], ): void { const normal = variants.find((variant) => variant.id === "normal"); const heroic = variants.find((variant) => variant.id === "heroic"); expect(normal, `${label}:normal`).toMatchObject({ difficulty: "normal", spawnMask: 1, }); expect(heroic, `${label}:heroic`).toMatchObject({ difficulty: "heroic", spawnMask: 2, levelRange: [70, 70], }); expect(new Set(variants.map((variant) => variant.id)).size, `${label}:unique-ids`) .toBe(variants.length); } describe("Burning Crusade difficulty contract", () => { it("advertises selectable normal and level-70 heroic variants in every recipe and compiled definition", () => { expect(TBC_DUNGEON_IDS).toHaveLength(14); for (const dungeonId of TBC_DUNGEON_IDS) { const recipe = requireRecipe(dungeonId); const definition = requireDungeonDefinition(dungeonId); expect(recipe.slug, dungeonId).toBe(dungeonId); expect(recipe.expansion, dungeonId).toBe("burning-crusade"); expectSelectableDifficultyContract(`${dungeonId}:recipe`, recipe.difficultyVariants); expectSelectableDifficultyContract(`${dungeonId}:runtime`, definition.difficultyVariants); } }); it("only uses encounter difficulty guards that players can select", () => { for (const dungeonId of TBC_DUNGEON_IDS) { const definition = requireDungeonDefinition(dungeonId); const selectableDifficultyIds = new Set( definition.difficultyVariants.map((variant) => variant.id), ); for (const encounter of definition.encounters ?? []) { for (const rule of encounter.rules) { for (const guard of rule.guards ?? []) { if (guard.kind !== "difficulty") continue; expect(guard.difficultyIds.length, `${dungeonId}:${encounter.id}:${rule.id}`) .toBeGreaterThan(0); for (const difficultyId of guard.difficultyIds) { expect( selectableDifficultyIds.has(difficultyId), `${dungeonId}:${encounter.id}:${rule.id}:${difficultyId}`, ).toBe(true); } } } } } }); });