import { describe, expect, it } from "vitest"; import { blockRegistry, resolveBlock, validatePageBlocks } from "./registry"; const id = "7d9be7bb-185f-43e8-a5c1-43a05acdebec"; describe("block registry", () => { it("provides validation and migration for every schema", () => { for (const definition of Object.values(blockRegistry)) { expect(definition.currentVersion).toBe(1); expect(definition.migrations[0]).toBeTypeOf("function"); } }); it("migrates and validates a legacy block", () => { const resolution = resolveBlock({ id, type: "callout", schemaVersion: 0, sortOrder: 0, config: { body: "จังหวะนี้ควรเก็บพลังงานไว้", tone: "tip" }, }); expect(resolution.kind).toBe("ready"); if (resolution.kind === "ready") { expect(resolution.block.schemaVersion).toBe(1); expect(resolution.block.responsiveLayout).toMatchObject({ width: "content", }); } }); it("keeps unknown and future blocks safe", () => { expect( resolveBlock({ id, type: "future-widget", schemaVersion: 1, config: {}, sortOrder: 0 }), ).toMatchObject({ kind: "unsupported", reason: "unknown-type" }); expect( resolveBlock({ id, type: "callout", schemaVersion: 99, config: {}, sortOrder: 0 }), ).toMatchObject({ kind: "unsupported", reason: "future-version" }); }); it("rejects unsafe or malformed configuration without throwing", () => { const resolution = resolveBlock({ id, type: "links", schemaVersion: 1, sortOrder: 0, config: { links: [ { id: "2b21ac85-eb39-4f4d-89ce-a26929417981", label: "ไม่ปลอดภัย", href: "javascript:alert(1)", }, ], }, }); expect(resolution.kind).toBe("invalid"); }); it("enforces chart series and an immutable accessible table fallback", () => { const base = { id, type: "comparison-chart", schemaVersion: 1, sortOrder: 0, config: { dataSourceId: "495248af-d20a-4e59-be25-a982398df917", categoryField: "name", series: [{ field: "damage", label: "ดาเมจ", color: "chart-1" }], presentation: "horizontal-bar", normalization: "raw", sort: "authored", showValues: true, showLegend: false, }, } as const; const valid = resolveBlock(base); expect(valid.kind).toBe("ready"); if (valid.kind === "ready") { expect(valid.block.config.tableFallback).toBe(true); } expect( resolveBlock({ ...base, config: { ...base.config, tableFallback: false }, }).kind, ).toBe("invalid"); expect( resolveBlock({ ...base, config: { ...base.config, series: Array.from({ length: 7 }, (_, index) => ({ field: `value_${index}`, label: `Series ${index}`, color: "chart-1", })), }, }).kind, ).toBe("invalid"); }); it("detects duplicate stable ids while preserving author order", () => { const results = validatePageBlocks([ { id, type: "separator", schemaVersion: 1, config: {}, sortOrder: 2, }, { id, type: "separator", schemaVersion: 1, config: {}, sortOrder: 1, }, ]); expect(results[0].kind).toBe("ready"); expect(results[1].kind).toBe("invalid"); }); });