From ec61432ec01356294a851c55ee79cac5f56d37c7 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 21 Apr 2026 18:38:19 -0600 Subject: [PATCH] test(chess/modifiers): add depth-3 composition and depth-4 rejection tests --- .../src/modifiers/custom/validate.test.ts | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/packages/chess/src/modifiers/custom/validate.test.ts b/packages/chess/src/modifiers/custom/validate.test.ts index 8b2145c..27c19d3 100644 --- a/packages/chess/src/modifiers/custom/validate.test.ts +++ b/packages/chess/src/modifiers/custom/validate.test.ts @@ -144,6 +144,10 @@ describe("validateCustomDescriptor", () => { }); it("enforces max nesting depth of 3 container levels", () => { + // Level 1: on-turn-start + // Level 2: conditional + // Level 3: on-capture + // Level 4: on-damaged (Exceeds max depth of 3) const deeplyNested = { kind: "on-turn-start", params: { @@ -192,6 +196,119 @@ describe("validateCustomDescriptor", () => { } }); + it("accepts depth-3 composition (exactly 3 levels)", () => { + // Level 1: conditional + // Level 2: on-move + // Level 3: add-to-attribute (Not a container, so depth is 3) + const depth3Valid = { + kind: "conditional", + params: { + condition: { type: "always" }, + then: [ + { + kind: "on-move", + params: { + primitives: [ + { + kind: "add-to-attribute", + params: { attr: "HpBonus", delta: 1 }, + }, + ], + }, + }, + ], + }, + }; + + const descriptor = makeDescriptor(); + Object.defineProperty(descriptor, "primitives", { + value: [depth3Valid], + }); + + const result = validateCustomDescriptor(descriptor); + expect(result).toEqual({ ok: true }); + }); + + it("rejects depth-4 composition (exceeds max depth of 3)", () => { + // Level 1: conditional + // Level 2: on-move + // Level 3: conditional + // Level 4: on-capture (exceeds depth 3) -> the error triggers on the container definition + const depth4Invalid = { + kind: "conditional", + params: { + condition: { type: "always" }, + then: [ + { + kind: "on-move", + params: { + primitives: [ + { + kind: "conditional", + params: { + condition: { type: "always" }, + then: [ + { + kind: "on-capture", + params: { primitives: [] } + }, + ] + } + }, + ], + }, + }, + ], + }, + }; + + const descriptor = makeDescriptor(); + Object.defineProperty(descriptor, "primitives", { + value: [depth4Invalid], + }); + + const result = validateCustomDescriptor(descriptor); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.errors.some((e) => e.code === "descriptor.primitives.depth.exceeded")).toBe( + true, + ); + } + }); + + it("accepts mixed old/new kinds at depth 3", () => { + // Level 1: on-captured (new kind) + // Level 2: conditional (old kind) + // Level 3: add-aura (old kind) + const mixedDepth3Valid = { + kind: "on-captured", + params: { + primitives: [ + { + kind: "conditional", + params: { + condition: { type: "always" }, + then: [ + { + kind: "add-aura", + params: { radius: 1, targetAttr: "HpBonus", delta: 1 }, + }, + ], + }, + }, + ], + }, + }; + + const descriptor = makeDescriptor(); + Object.defineProperty(descriptor, "primitives", { + value: [mixedDepth3Valid], + }); + + const result = validateCustomDescriptor(descriptor); + expect(result).toEqual({ ok: true }); + }); + it("enforces max primitive count of 50", () => { const descriptor = makeDescriptor(); Object.defineProperty(descriptor, "primitives", {