import { describe, expect, it } from "vitest"; import { imageExportModule } from "../../../modules/built-ins/image-export/image-export-module"; import { videoExportModule } from "../../../modules/built-ins/video-export/video-export-module"; import { svgExportModule } from "../../../modules/built-ins/svg-export/svg-export-module"; import type { ToolcraftExternalStore } from "../../../state/toolcraft-external-store"; import type { ToolcraftInitialState } from "../../../state/types"; import { useToolcraftStore } from "../../app-shell/toolcraft-store-context"; import { act, ControlsPanel, defineToolcraft, fireEvent, React, render, screen, ToolcraftRoot, vi, } from "../testing/controls-panel-test-utils"; function setup(initialState?: ToolcraftInitialState) { const schema = defineToolcraft({ base: { identity: { id: "export-label-test", title: "Export labels" }, canvas: { enabled: true }, panels: { controls: { title: "Controls", sections: [{ id: "custom-actions", actionGroup: "secondary", controls: { custom: { applicability: { mode: "always" }, type: "panelActions", target: "custom.actions", actions: [{ label: "Export Report", value: "custom.report" }], }, }, }], }, }, }, modules: [imageExportModule(), videoExportModule(), svgExportModule()], }); let captured: ToolcraftExternalStore | undefined; function CaptureStore() { captured = useToolcraftStore(); return null; } const onPanelAction = vi.fn(); render( , ); if (!captured) throw new Error("Expected the runtime store"); const store = captured; const setFormat = (target: string, value: string) => act(() => { store.dispatch({ type: "controls.setValue", target, value }); }); return { store, setFormat, onPanelAction }; } describe("runtime export format labels", () => { it("shows one still-export button alongside video", () => { setup(); for (const name of ["Export PNG", "Export MP4"]) { expect(screen.getByRole("button", { name })).toBeTruthy(); } expect(screen.queryByRole("button", { name: "Export Video" })).toBeNull(); expect(screen.queryByRole("button", { name: "Export SVG" })).toBeNull(); }); it("updates only the corresponding label and preserves the button identity", () => { const { setFormat } = setup(); const image = screen.getByRole("button", { name: "Export PNG" }); const video = screen.getByRole("button", { name: "Export MP4" }); setFormat("export.image.format", "jpg"); expect(screen.getByRole("button", { name: "Export JPG" })).toBe(image); expect(screen.getByRole("button", { name: "Export MP4" })).toBe(video); setFormat("export.video.format", "webm"); expect(screen.getByRole("button", { name: "Export WebM" })).toBe(video); expect(screen.getByRole("button", { name: "Export JPG" })).toBe(image); setFormat("export.image.format", "svg"); expect(screen.getByRole("button", { name: "Export SVG" })).toBe(image); expect(screen.queryByRole("button", { name: "Export JPG" })).toBeNull(); setFormat("export.image.format", "png"); setFormat("export.video.format", "mp4"); expect(screen.getByRole("button", { name: "Export PNG" })).toBe(image); expect(screen.getByRole("button", { name: "Export MP4" })).toBe(video); }); it("reads restored formats on the first render", () => { setup({ values: { "export.image.format": "jpg", "export.video.format": "webm" }, }); expect(screen.getByRole("button", { name: "Export JPG" })).toBeTruthy(); expect(screen.getByRole("button", { name: "Export WebM" })).toBeTruthy(); }); it("hides resolution for SVG and restores its dormant value", () => { const { store, setFormat } = setup(); const formatRow = () => screen.getByRole("combobox", { name: /^(PNG|JPG|SVG)$/ }) .closest('[data-control-layout="inline"]'); expect(formatRow()?.getAttribute("data-control-layout-columns")).toBe("2"); setFormat("export.image.resolution", "8k"); expect(screen.getByRole("combobox", { name: "8K" })).toBeTruthy(); setFormat("export.image.format", "svg"); expect(screen.queryByRole("combobox", { name: "8K" })).toBeNull(); expect(formatRow()?.getAttribute("data-control-layout-columns")).toBe("2"); expect(store.getState().values["export.image.resolution"]).toBe("8k"); setFormat("export.image.format", "jpg"); expect(screen.getByRole("combobox", { name: "8K" })).toBeTruthy(); expect(formatRow()?.getAttribute("data-control-layout-columns")).toBe("2"); }); it("restores SVG with one button and hidden resolution", () => { setup({ values: { "export.image.format": "svg", "export.image.resolution": "8k" } }); expect(screen.getAllByRole("button", { name: "Export SVG" })).toHaveLength(1); expect(screen.queryByRole("button", { name: "Export PNG" })).toBeNull(); expect(screen.queryByRole("combobox", { name: "8K" })).toBeNull(); }); it("tracks Undo, Redo and reset through the same runtime values", () => { const { store, setFormat } = setup(); setFormat("export.image.format", "jpg"); act(() => store.dispatch({ type: "history.undo" })); expect(screen.getByRole("button", { name: "Export PNG" })).toBeTruthy(); act(() => store.dispatch({ type: "history.redo" })); expect(screen.getByRole("button", { name: "Export JPG" })).toBeTruthy(); setFormat("export.video.format", "webm"); act(() => store.dispatch({ type: "controls.reset" })); expect(screen.getByRole("button", { name: "Export PNG" })).toBeTruthy(); expect(screen.getByRole("button", { name: "Export MP4" })).toBeTruthy(); }); it("does not rename or reroute custom export-named actions", () => { const { setFormat, onPanelAction } = setup(); setFormat("export.image.format", "jpg"); setFormat("export.video.format", "webm"); fireEvent.click(screen.getByRole("button", { name: "Export Report" })); expect(onPanelAction).toHaveBeenCalledWith( expect.objectContaining({ action: expect.objectContaining({ label: "Export Report", value: "custom.report", }), }), ); }); it("follows canonical control normalization instead of advertising unsupported formats", () => { const { store, setFormat } = setup(); setFormat("export.image.format", "gif"); expect(store.getState().values["export.image.format"]).toBe("png"); expect(screen.getByRole("button", { name: "Export PNG" })).toBeTruthy(); setFormat("export.video.format", "mov"); expect(store.getState().values["export.video.format"]).toBe("mp4"); expect(screen.getByRole("button", { name: "Export MP4" })).toBeTruthy(); }); });