import { describe, expect, it } from "vitest"; import { mediaSourceModule } from "../../../modules/built-ins/media-source/media-source-module"; import { defineToolcraft, fireEvent, renderControlsPanel, renderControlsPanelWithSchema, screen, } from "../testing/controls-panel-test-utils"; describe("ControlsPanel state and reset behavior", () => { it("binds control changes and reset actions to runtime state", () => { renderControlsPanel(); const promptInput = screen.getByDisplayValue("Initial prompt"); fireEvent.change(promptInput, { target: { value: "Updated prompt" } }); expect(screen.getByTestId("prompt-value").textContent).toBe( "Updated prompt", ); const enabledField = screen.getByText("Enabled").closest('[role="group"]'); const enabledSwitch = enabledField?.querySelector('[role="switch"]'); fireEvent.click(enabledSwitch as HTMLElement); expect(screen.getByTestId("enabled-value").textContent).toBe("false"); fireEvent.click(screen.getByRole("button", { name: "Reset controls" })); expect(screen.getByTestId("prompt-value").textContent).toBe( "Initial prompt", ); expect(screen.getByTestId("enabled-value").textContent).toBe("true"); }); it("resets only controls from the selected section header action", () => { const schema = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: false }, panels: { controls: { sections: [ { id: "test-section-1", controls: { toneName: { applicability: { mode: "always" as const }, defaultValue: "Soft", label: "Tone name", target: "tone.name", type: "text", }, }, title: "Tone", }, { id: "test-section-2", controls: { prompt: { applicability: { mode: "always" as const }, defaultValue: "Poster", label: "Prompt", target: "generation.prompt", type: "text", }, }, title: "Output", }, ], title: "Controls", }, }, }, modules: [], }); const { container } = renderControlsPanelWithSchema(schema); fireEvent.change(screen.getByDisplayValue("Soft"), { target: { value: "Sharp" }, }); fireEvent.change(screen.getByDisplayValue("Poster"), { target: { value: "Banner" }, }); const toneHeader = screen .getByText("Tone") .closest('[data-slot="control-section-header"]'); const headerButtons = Array.from(toneHeader?.querySelectorAll("button") ?? []); const resetIndex = headerButtons.findIndex((button) => button.hasAttribute("data-control-section-reset-button")); const collapseIndex = headerButtons.findIndex((button) => button.hasAttribute("data-control-section-collapse-button")); expect(resetIndex).toBeGreaterThanOrEqual(0); expect(collapseIndex).toBeGreaterThan(resetIndex); fireEvent.click(screen.getByRole("button", { name: "Reset Tone section" })); const values = JSON.parse( screen.getByTestId("values-json").textContent ?? "{}", ); expect(values["tone.name"]).toBe("Soft"); expect(values["generation.prompt"]).toBe("Banner"); expect( container.querySelector("[data-control-section-reset-button]"), ).toBeTruthy(); }); it("clears file upload previews from the selected section reset action", () => { const schema = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true, upload: true }, panels: { controls: { sections: [ { id: "test-section-3", controls: { source: { applicability: { mode: "always" as const }, defaultValue: null, label: "Image", target: "media.source", type: "fileDrop", }, }, title: "Source Image", }, ], title: "Controls", }, }, }, modules: [mediaSourceModule()], }); renderControlsPanelWithSchema( schema, {}, { mediaAssets: [ { sourceSize: { height: 300, unit: "px", width: 400 }, assetKind: "image", lifecycle: "ready", resourceRef: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'/%3E", fileName: "source.svg", id: "media-1", layerId: "layer-1", mimeType: "image/svg+xml", position: { x: 0, y: 0 }, size: { height: 300, unit: "px", width: 400 }, sourceTarget: "media.source", }, ], }, ); expect(screen.getByRole("img", { name: "source.svg" })).toBeTruthy(); expect(screen.getByTestId("media-count").textContent).toBe("1"); fireEvent.click( screen.getByRole("button", { name: "Reset Source Image section" }), ); expect(screen.queryByRole("img", { name: "source.svg" })).toBeNull(); expect(screen.getByTestId("media-count").textContent).toBe("0"); }); });