test(layouts): suggestedPresets references must resolve to registered presets

Phase F.2 (audit portion) of the rule-variants epic.

Adds a suite to premades.test.ts that walks every layout's
`suggestedPresets` and verifies each referenced id resolves to a
registered preset. Catches rename / deletion drift before a
dangling chip surfaces in the lobby UI.

Current audit is green: all 7 suggestedPresets entries across
dual-classic, knightmate, pawns-only, and monster reference real
ids. (UI 'suggested rules chip' rendering is a separate follow-up
bundled with the Phase F.3 RulesDrawer work.)

Tests: 1651 passing (was 1650, +1 new audit test).
This commit is contained in:
Joey Yakimowich-Payne 2026-04-21 09:04:54 -06:00
commit 50f7b37e12
No known key found for this signature in database

View file

@ -10,6 +10,8 @@ import { LAYOUT_REGISTRY } from "./registry.js";
import { validateLayout } from "./validate.js";
import { EMPTY_LAYOUT } from "./empty.js";
import "./index.js"; // trigger registration of every premade
import { PRESET_REGISTRY } from "../presets/registry.js";
import "../presets/index.js"; // trigger preset registration
describe("LAYOUT_REGISTRY — premade roster", () => {
it("includes every expected id", () => {
@ -79,3 +81,24 @@ describe("premade piece counts", () => {
});
}
});
// Phase F.2: every entry in a layout's `suggestedPresets` must
// reference a REAL registered preset id. Catches renames / deletions
// before the UI surfaces a dangling chip.
describe("suggestedPresets → preset-id integrity", () => {
it("every suggestedPresets entry references a registered preset", () => {
const presetIds = new Set(PRESET_REGISTRY.getAll().map((p) => p.id));
const dangling: string[] = [];
for (const layout of LAYOUT_REGISTRY.list()) {
const suggested = layout.suggestedPresets ?? [];
for (const ref of suggested) {
if (!presetIds.has(ref)) {
dangling.push(`"${layout.id}" → "${ref}" (unknown preset)`);
}
}
}
expect(dangling).toEqual([]);
});
});