import { describe, expect, it } from "vitest"; import { timelineModule } from "../modules/built-ins/timeline/timeline-module"; import { defineToolcraft } from "./define-toolcraft"; import type { ToolcraftCanvasRenderScaleSchema } from "./types"; const authoredRenderScaleStep: ToolcraftCanvasRenderScaleSchema = { step: 0.5 }; const authoredRenderScaleDefaultValue = { defaultValue: 1, step: 0.5 }; const authoredRenderScaleEnabled = { enabled: true, step: 0.5 }; const authoredRenderScaleMax = { max: 1, step: 0.5 }; const authoredRenderScaleMin = { min: 1, step: 0.5 }; // @ts-expect-error Authored render scale cannot select its resolved default value. const authoredRenderScaleDefaultValueAssignment: ToolcraftCanvasRenderScaleSchema = authoredRenderScaleDefaultValue; // @ts-expect-error Authored render scale is always enabled when provided. const authoredRenderScaleEnabledAssignment: ToolcraftCanvasRenderScaleSchema = { ...authoredRenderScaleEnabled, }; // @ts-expect-error Authored render scale cannot change the canonical maximum. const authoredRenderScaleMaxAssignment: ToolcraftCanvasRenderScaleSchema = authoredRenderScaleMax; // @ts-expect-error Authored render scale cannot change the canonical minimum. const authoredRenderScaleMinAssignment: ToolcraftCanvasRenderScaleSchema = { ...authoredRenderScaleMin, }; void authoredRenderScaleStep; void authoredRenderScaleDefaultValue; void authoredRenderScaleEnabled; void authoredRenderScaleMax; void authoredRenderScaleMin; void authoredRenderScaleDefaultValueAssignment; void authoredRenderScaleEnabledAssignment; void authoredRenderScaleMaxAssignment; void authoredRenderScaleMinAssignment; describe("defineToolcraft runtime setup render scale and timeline controls", () => { it("appends raster render scale to the technical setup controls when enabled", () => { const app = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true, renderScale: true, size: { height: 900, unit: "px", width: 1440 }, sizing: { mode: "editable-output" }, }, panels: { controls: { sections: [], title: "Controls", }, }, }, modules: [], }); const setupSection = app.panels.controls?.sections[1]; expect(app.canvas.renderScale).toEqual({ defaultValue: 2, enabled: true, max: 2, min: 1, step: 0.25, }); expect(app.assembly.capabilities).toContain("canvas.renderScale"); expect(Object.keys(setupSection?.controls ?? {})).toEqual([ "infinityCanvas", "workspaceBackground", "canvasAspectRatio", "canvasWidth", "canvasHeight", "canvasRenderScale", ]); expect(setupSection?.controls.canvasRenderScale).toMatchObject({ applicability: { mode: "always" as const }, defaultValue: 2, label: "Resolution scale", markerCount: 5, max: 2, min: 1, step: 0.25, target: "canvas.renderScale", type: "slider", variant: "discrete", }); }); it("uses a continuous visual slider for a high-cardinality render scale", () => { const app = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft fixture" }, canvas: { enabled: true, renderScale: { step: 0.01 }, size: { height: 900, unit: "px", width: 1440 }, sizing: { mode: "editable-output" }, }, panels: { controls: { sections: [], title: "Controls", }, }, }, modules: [], }); const renderScaleControl = app.panels.controls?.sections[1]?.controls.canvasRenderScale; expect(renderScaleControl).toMatchObject({ applicability: { mode: "always" as const }, defaultValue: 2, max: 2, min: 1, step: 0.01, target: "canvas.renderScale", type: "slider", variant: "continuous", }); expect(renderScaleControl).not.toHaveProperty("markerCount"); expect(app.canvas.renderScale).toEqual({ defaultValue: 2, enabled: true, max: 2, min: 1, step: 0.01, }); }); it("places timeline last when no managed background controls exist", () => { const app = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true, renderScale: true, size: { height: 900, unit: "px", width: 1440 }, sizing: { mode: "editable-output" }, }, panels: { controls: { sections: [], title: "Controls", }, }, }, modules: [ timelineModule({ mode: "playback", }), ], }); const setupSection = app.panels.controls?.sections[1]; expect(Object.keys(setupSection?.controls ?? {})).toEqual([ "infinityCanvas", "workspaceBackground", "canvasAspectRatio", "canvasWidth", "canvasHeight", "canvasRenderScale", "timelineExtended", ]); expect(setupSection?.controls.timelineExtended).toMatchObject({ applicability: { mode: "always" as const }, defaultValue: false, label: "Timeline", target: "panels.timeline.extended", type: "switch", }); expect(setupSection?.controls.timelineExtended).not.toHaveProperty( "description", ); expect(setupSection?.controls.infinityCanvas).not.toHaveProperty( "description", ); expect(setupSection?.layoutGroups).toEqual([ { columns: 2, controls: ["canvasWidth", "canvasHeight"], layout: "inline", }, ]); }); it("uses the canonical authored raster scale with a custom step", () => { const app = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true, renderScale: { step: 0.5 }, size: { height: 900, unit: "px", width: 1440 }, sizing: { mode: "fixed-output" }, }, panels: { controls: { sections: [], title: "Controls", }, }, }, modules: [ timelineModule({ mode: "playback", }), ], }); const setupSection = app.panels.controls?.sections[1]; expect(Object.keys(setupSection?.controls ?? {})).toEqual([ "workspaceBackground", "canvasRenderScale", "timelineExtended", ]); expect(setupSection?.controls.canvasRenderScale).toMatchObject({ applicability: { mode: "always" as const }, defaultValue: 2, max: 2, min: 1, step: 0.5, target: "canvas.renderScale", type: "slider", }); expect(app.canvas.renderScale).toEqual({ defaultValue: 2, enabled: true, max: 2, min: 1, step: 0.5, }); expect(setupSection?.controls.timelineExtended).toMatchObject({ applicability: { mode: "always" as const }, defaultValue: false, label: "Timeline", target: "panels.timeline.extended", type: "switch", }); expect(setupSection?.controls.timelineExtended).not.toHaveProperty( "description", ); expect(setupSection?.layoutGroups ?? []).toEqual([]); }); it("rejects an authored step that cannot reach the canonical maximum", () => { expect(() => defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true, renderScale: { step: 0.3 }, }, panels: {}, }, modules: [], }), ).toThrow( "Canvas render scale step must divide the canonical range exactly.", ); }); it.each([ [ 0, /Canvas render scale step must be a finite value between 0\.01 and 1\./u, ], [Number.NaN, /serializable plain data.*non-finite numbers/u], ])("rejects invalid authored step %s", (step, error) => { expect(() => defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true, renderScale: { step }, }, panels: {}, }, modules: [], }), ).toThrow(error); }); });