import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import path from "node:path"; import test from "node:test"; import { fileURLToPath } from "node:url"; const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const catalogFile = path.join( projectRoot, "scripts/runewaker-pipeline/snapshots/runewaker-npc-spell-catalog.json", ); test("every executable RuneWaker damage family carries source-shaped formula evidence", async () => { const catalog = JSON.parse(await readFile(catalogFile, "utf8")); const executable = catalog.spells.filter((spell) => spell.mappingStatus === "damage-family"); assert.equal(executable.length, catalog.damageFamilyCount); for (const spell of executable) { const primary = spell.components.find((component) => component.directHpDamage); assert.ok(primary, `spell ${spell.spellId} has no primary damage component`); assert.equal(spell.runtime.formula.spellId, spell.spellId); assert.equal(spell.runtime.formula.componentId, primary.id); assert.equal(spell.runtime.formula.damagePower, primary.damagePower); assert.equal(spell.runtime.formula.fixedValue, primary.fixedValue); assert.equal(spell.runtime.formula.dotBase, primary.dotBase); assert.equal(spell.runtime.formula.provenance.physicalFunctionLine, 3366); assert.equal(spell.runtime.formula.provenance.magicFunctionLine, 3651); if (spell.runtime.formula.powerKind === "source-ratio") { assert.ok(Math.abs(primary.damagePower) <= 4); assert.equal(spell.runtime.damageMultiplier, spell.runtime.formula.runtimeBaselineMultiplier); } } assert.equal(catalog.safety.unavailableNativeInputsDefaulted, false); assert.equal(catalog.safety.pointValuedDamageUsesLabeledScaledAdapter, true); });