forked from phenom/healer-man
Update class mechanics, stat rulesets, and CoA reference catalogs
This commit is contained in:
1 parent
b16821e92e
commit
39458d5de6
221 files changed
+2584962
-568
No files matched your search
@@ -0,0 +1,67 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { lookupReference, publishSnapshot, readSnapshot, stableJson } from "./snapshot.mjs";
|
||||
|
||||
function fixture() {
|
||||
return {
|
||||
baseline: { kind: "local-july", capturedAt: "2026-07-25" },
|
||||
classes: [{ classId: 12, gameId: "barbarian", className: "Barbarian", tabs: [{ tabId: 31, tabName: "Brutality" }] }],
|
||||
nodes: [{ id: 1, classId: 12, tabId: 31, name: "Ancestral Strike", rankDescriptions: [{ rank: 1, spellId: 100 }] }],
|
||||
spells: [{ id: 100, name: "Ancestral Strike" }, { id: 101, name: "Ancestral Strike", rank: "Rank 2" }],
|
||||
abilities: [{ key: "c12:ancestralstrike", classId: 12, name: "Ancestral Strike", spellIds: [100], rankSpellIds: [100, 101], nodeIds: [1] }],
|
||||
};
|
||||
}
|
||||
|
||||
test("stable serialization ignores object insertion order", () => {
|
||||
assert.equal(stableJson({ b: 2, a: { y: 1, x: 2 } }), stableJson({ a: { x: 2, y: 1 }, b: 2 }));
|
||||
});
|
||||
|
||||
test("snapshot rebuild is deterministic and corruption does not advance the pointer", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "coa-reference-"));
|
||||
try {
|
||||
const first = publishSnapshot({ outputRoot: root, reference: fixture(), report: { warnings: [] }, markdown: "# Audit" });
|
||||
const second = publishSnapshot({ outputRoot: root, reference: fixture(), report: { warnings: [] }, markdown: "# Audit" });
|
||||
assert.equal(first.snapshotId, second.snapshotId);
|
||||
assert.deepEqual(readSnapshot(root).reference, fixture());
|
||||
const pointer = fs.readFileSync(path.join(root, "current.json"), "utf8");
|
||||
fs.writeFileSync(path.join(first.directory, "reference.json"), "{}\n");
|
||||
assert.throws(() => readSnapshot(root), /Corrupt reference/);
|
||||
assert.throws(() => publishSnapshot({ outputRoot: root, reference: fixture(), report: { warnings: [] }, markdown: "# Audit" }), /Corrupt reference/);
|
||||
assert.equal(fs.readFileSync(path.join(root, "current.json"), "utf8"), pointer);
|
||||
} finally {
|
||||
assert.ok(root.startsWith(`${path.resolve(os.tmpdir())}${path.sep}`));
|
||||
fs.rmSync(root, { recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid pointer cannot escape snapshot directory", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "coa-reference-"));
|
||||
try {
|
||||
fs.writeFileSync(path.join(root, "current.json"), '{"snapshotId":"../outside"}\n');
|
||||
assert.throws(() => readSnapshot(root), /Invalid reference snapshot pointer/);
|
||||
} finally {
|
||||
assert.ok(root.startsWith(`${path.resolve(os.tmpdir())}${path.sep}`));
|
||||
fs.rmSync(root, { recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("lookup supports class names, trees, rank spell IDs and ability names", () => {
|
||||
assert.equal(lookupReference(fixture(), { class: "Barbarian", tree: "Brutality", ability: "ancestral" }).spells.length, 2);
|
||||
assert.equal(lookupReference(fixture(), { class: "12", spell: "101" }).spells[0].id, 101);
|
||||
assert.throws(() => lookupReference(fixture(), { class: "unknown" }), /Unknown CoA class/);
|
||||
assert.throws(() => lookupReference(fixture(), { tree: "unknown" }), /Unknown tree/);
|
||||
assert.throws(() => lookupReference(fixture(), { spell: "999" }), /not in this reference/);
|
||||
});
|
||||
|
||||
test("class lookup follows triggered spell dependencies without treating them as learned abilities", () => {
|
||||
const reference = fixture();
|
||||
reference.spells[0].dbc = { effects: [{ triggerSpellId: 102 }] };
|
||||
reference.spells.push({ id: 102, name: "Hidden strike", dbc: { effects: [{ triggerSpellId: 100 }] } });
|
||||
const result = lookupReference(reference, { class: "barbarian", spell: "102" });
|
||||
assert.equal(result.spells[0].id, 102);
|
||||
assert.equal(result.abilities.length, 0);
|
||||
assert.equal(result.nodes.length, 0);
|
||||
});
|
||||
Reference in new issue
Block a user