import { describe, expect, it } from "vitest"; import { CLASSES, type ClassId } from "../app/characterCatalog"; import { COA_ABILITIES_BY_CLASS, COA_CLASS_RESOURCES, COA_TRIGGERED_ABILITIES_BY_SPELL_ID, } from "./coaAbilityCatalog"; import { COA_RUNTIME_ABILITIES_BY_CLASS, COA_RUNTIME_CLASS_RESOURCES, COA_RUNTIME_TRIGGERED_ABILITIES_BY_SPELL_ID, } from "./coaAbilityRuntimeCatalog"; import generatedTalentRuntime from "./generated/talentRuntimeCatalog.json"; import { TALENT_NODES, allocateTalentPoint, normalizeTalentRanks, talentTreesForClass, } from "./talentCatalog"; import { runtimeAllocateTalentPoint, runtimeNormalizeTalentRanks, } from "./talentRuntimeCatalog"; describe("compact combat runtime catalogs", () => { it("preserves every derived COA ability and resource profile", () => { expect(COA_RUNTIME_ABILITIES_BY_CLASS).toEqual(COA_ABILITIES_BY_CLASS); expect(COA_RUNTIME_CLASS_RESOURCES).toEqual(COA_CLASS_RESOURCES); expect(COA_RUNTIME_TRIGGERED_ABILITIES_BY_SPELL_ID).toEqual(COA_TRIGGERED_ABILITIES_BY_SPELL_ID); }); it("preserves every talent field used by runtime allocation and modifiers", () => { const expected = TALENT_NODES.map((node) => ({ id: node.id, treeId: node.treeId, index: node.index, row: node.row, maxRank: node.maxRank, name: node.name, prerequisites: node.prerequisites, rankDescriptions: node.rankDescriptions, system: node.system, abilityEssenceCost: node.abilityEssenceCost, talentEssenceCost: node.talentEssenceCost, requiredClassPoints: node.requiredClassPoints, requiredSpecPoints: node.requiredSpecPoints, requiredLevel: node.requiredLevel, isPassive: node.isPassive, })); expect(generatedTalentRuntime.nodes).toEqual(JSON.parse(JSON.stringify(expected))); }); it("matches normalization and first legal allocation for every playable class", () => { for (const definition of CLASSES) { const classId = definition.id as ClassId; expect(runtimeNormalizeTalentRanks(classId, 80, {})).toEqual(normalizeTalentRanks(classId, 80, {})); const node = talentTreesForClass(classId) .flatMap((tree) => TALENT_NODES.filter((candidate) => candidate.treeId === tree.id)) .find((candidate) => allocateTalentPoint({}, classId, candidate.id, 80).ok); if (!node) continue; expect(runtimeAllocateTalentPoint({}, classId, node.id, 80)).toEqual( allocateTalentPoint({}, classId, node.id, 80), ); } }); });