import { describe, expect, it } from "vitest"; import { defineToolcraft, fireEvent, renderControlsPanelWithSchema, screen } from "../testing/controls-panel-test-utils"; describe("ControlsPanel gradient control", () => { it.each([ ["linear", "Linear"], ["radial", "Radial"], ["angular", "Angular"], ["diamond", "Diamond"], ] as const)("preserves %s gradient type in the gradient select", (gradientType, label) => { const schema = defineToolcraft({ canvas: { enabled: true }, panels: { controls: { sections: [ { controls: { gradient: { defaultValue: { angle: 138, gradientType, stops: [ { color: "#111111", position: "0%" }, { color: "#14B8FF", position: "45%" }, { color: "#F472B6", position: "76%" }, ], }, label: "Gradient", target: "style.gradient", type: "gradient", }, }, title: "Gradient", }, ], title: "Generation Controls", }, }, }); const { container } = renderControlsPanelWithSchema(schema); const gradientSelect = container.querySelector('[data-slot="select-trigger"]'); expect(gradientSelect?.textContent).toContain(label); }); it("commits gradient stop position inputs on blur or Enter with a separated percent suffix", () => { const schema = defineToolcraft({ canvas: { enabled: true }, panels: { controls: { sections: [ { controls: { gradient: { defaultValue: { angle: 90, gradientType: "linear", stops: [ { color: "#111111", position: "0%" }, { color: "#FFFFFF", position: "100%" }, ], }, label: "Gradient", target: "style.gradient", type: "gradient", }, }, title: "Gradient", }, ], title: "Generation Controls", }, }, }); renderControlsPanelWithSchema(schema); const firstPositionInput = screen.getByLabelText( "Stop 1 position", ) as HTMLInputElement; const secondPositionInput = screen.getByLabelText( "Stop 2 position", ) as HTMLInputElement; const firstPositionGroup = firstPositionInput.closest('[data-slot="input-group"]'); const firstOpacityInput = screen.getByLabelText("Stop 1 opacity"); const stopsList = firstPositionInput.closest('[data-slot="gradient-stops-list"]'); const gradientControlItem = stopsList?.closest( "[data-control-item-compound-context]", ); const firstStopGrid = firstPositionInput.closest('[data-slot="field"]') ?.querySelector('[data-slot="gradient-stop-row-grid"]'); expect(firstPositionInput.value).toBe("0"); expect(firstPositionGroup?.textContent).toContain("%"); expect(stopsList?.className).not.toContain("border-y"); expect(gradientControlItem).toBeNull(); expect(firstPositionInput.className.split(/\s+/)).toContain("pl-[5px]"); expect(firstOpacityInput.className.split(/\s+/)).toContain("pl-[5px]"); expect(firstStopGrid?.className).toContain("grid-cols-[3.5rem_minmax(0,1fr)_1.5rem]"); fireEvent.change(firstPositionInput, { target: { value: "25" } }); expect(JSON.parse(screen.getByTestId("gradient-value").textContent ?? "{}")).toMatchObject({ stops: [ { position: "0%" }, { position: "100%" }, ], }); fireEvent.blur(firstPositionInput); expect(JSON.parse(screen.getByTestId("gradient-value").textContent ?? "{}")).toMatchObject({ stops: [ { position: "25%" }, { position: "100%" }, ], }); fireEvent.change(secondPositionInput, { target: { value: "75" } }); expect(JSON.parse(screen.getByTestId("gradient-value").textContent ?? "{}")).toMatchObject({ stops: [ { position: "25%" }, { position: "100%" }, ], }); fireEvent.keyDown(secondPositionInput, { code: "Enter", key: "Enter" }); expect(JSON.parse(screen.getByTestId("gradient-value").textContent ?? "{}")).toMatchObject({ stops: [ { position: "25%" }, { position: "75%" }, ], }); }); });