import { describe, expect, it } from "vitest"; import type { ToolcraftCollectionItemControlType } from "./collection-item-controls"; import { defineToolcraft } from "./define-toolcraft"; import type { ToolcraftControlSchema } from "./types"; const SCREENSHOT_LABELS = ["Default", "Ink Drops", "Solar", "Background"]; const BOUNDARY_LABELS = ["Ink Drops", "Default", "Solar", "RGB"]; function createAppSchema(control: ToolcraftControlSchema) { return { canvas: { enabled: true }, panels: { controls: { sections: [ { controls: { appearanceMode: control }, title: "Appearance", }, ], title: "Controls", }, }, }; } function createModeControl( type: string, labels: readonly string[], ): ToolcraftControlSchema { return { defaultValue: "default", options: labels.map((label) => ({ label, value: label.toLowerCase().replaceAll(" ", "-"), })), target: "appearance.mode", type, }; } function createCollectionModeControl( type: ToolcraftCollectionItemControlType, labels: readonly string[], parentType = "collectionActions", ): ToolcraftControlSchema { return { defaultValue: ["default"], itemControl: { defaultValue: "default", label: "Mode", options: labels.map((label) => ({ label, value: label.toLowerCase().replaceAll(" ", "-"), })), type, }, itemLabel: "Mode", label: "Modes", minItems: 1, target: "appearance.modes", type: parentType, }; } function getAppearanceModeControl(app: ReturnType) { return app.panels.controls?.sections.find( (section) => section.title === "Appearance", )?.controls.appearanceMode; } describe("defineToolcraft segmented control fit", () => { it("rejects the overwide screenshot labels before render", () => { expect(() => defineToolcraft( createAppSchema(createModeControl("segmented", SCREENSHOT_LABELS)), ), ).toThrow( /Toolcraft control validation \[segmented-control-fit\] for target "appearance\.mode": .*select dropdown/u, ); }); it("accepts the simultaneous four-option, nine-character, 24-character boundary", () => { const control = createModeControl("segmented", BOUNDARY_LABELS); const app = defineToolcraft(createAppSchema(control)); const resolvedControl = getAppearanceModeControl(app); expect(resolvedControl?.type).toBe("segmented"); expect(control.type).toBe("segmented"); }); it("accepts the screenshot labels on a select without converting the control", () => { const control = createModeControl("select", SCREENSHOT_LABELS); const app = defineToolcraft(createAppSchema(control)); const resolvedControl = getAppearanceModeControl(app); expect(resolvedControl?.type).toBe("select"); expect(control.type).toBe("select"); }); it("rejects an overwide collectionActions segmented itemControl before render", () => { expect(() => defineToolcraft( createAppSchema( createCollectionModeControl("segmented", SCREENSHOT_LABELS), ), ), ).toThrow(/\[segmented-control-fit\]/u); }); it("reports the collection parent target and itemControl select guidance", () => { expect(() => defineToolcraft( createAppSchema( createCollectionModeControl("segmented", SCREENSHOT_LABELS), ), ), ).toThrow( /Toolcraft control validation \[segmented-control-fit\] for target "appearance\.modes" itemControl: .*select dropdown/u, ); }); it("keeps a boundary-fit collectionActions itemControl segmented without mutating input", () => { const control = createCollectionModeControl("segmented", BOUNDARY_LABELS); const inputSnapshot = structuredClone(control); const app = defineToolcraft(createAppSchema(control)); const resolvedControl = getAppearanceModeControl(app); expect(resolvedControl?.itemControl?.type).toBe("segmented"); expect(control).toEqual(inputSnapshot); }); it("keeps overwide collectionActions select itemControl unchanged", () => { const control = createCollectionModeControl("select", SCREENSHOT_LABELS); const inputSnapshot = structuredClone(control); const app = defineToolcraft(createAppSchema(control)); const resolvedControl = getAppearanceModeControl(app); expect(resolvedControl?.itemControl?.type).toBe("select"); expect(control).toEqual(inputSnapshot); }); it("applies segmented item fit validation to sourceCollection", () => { expect(() => defineToolcraft( createAppSchema( createCollectionModeControl( "segmented", SCREENSHOT_LABELS, "sourceCollection", ), ), ), ).toThrow( /Toolcraft control validation \[segmented-control-fit\] for target "appearance\.modes" itemControl: .*select dropdown/u, ); }); it.each(["type", "target"] as const)( "preserves required %s validation ownership", (fieldName) => { const control = createModeControl("segmented", SCREENSHOT_LABELS); Object.defineProperty(control, fieldName, { configurable: true, enumerable: false, value: control[fieldName], }); expect(() => defineToolcraft(createAppSchema(control))).toThrow( new RegExp(`\\[control-${fieldName}\\]`, "u"), ); }, ); it("preserves runtime-boundary validation ownership", () => { const control = { ...createModeControl("segmented", SCREENSHOT_LABELS), assetKind: "model", } as unknown as ToolcraftControlSchema; expect(() => defineToolcraft(createAppSchema(control))).toThrow( /\[model-filedrop-type\]/u, ); }); });