import {
cleanup,
fireEvent,
render,
screen,
waitFor,
} from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import { defineToolcraft } from "../../schema/define-toolcraft";
import { ToolcraftRoot } from "./toolcraft-root";
import { useToolcraft } from "./use-toolcraft";
function Probe() {
const { dispatch, state } = useToolcraft();
return (
);
}
function ResetProbe() {
const { dispatch, state } = useToolcraft();
return (
);
}
function PanelPersistenceProbe() {
const { dispatch, state } = useToolcraft();
return (
);
}
function createPersistentSchema() {
return defineToolcraft({
base: {
identity: { id: "root-test", title: "Root Test" },
canvas: { enabled: true },
panels: {
controls: {
sections: [
{
id: "test-section-1",
controls: {
opacity: {
applicability: { mode: "always" as const },
defaultValue: 75,
target: "selectedLayer.opacity",
type: "slider",
},
},
},
],
title: "Controls",
},
},
persistence: {
storage: "localStorage",
},
},
modules: [],
});
}
function createHistorySchema(history = true) {
return defineToolcraft({
base: {
identity: { id: "runtime-test", title: "Toolcraft App" },
canvas: { enabled: true },
panels: {
controls: {
sections: [
{
id: "test-section-2",
controls: {
opacity: {
applicability: { mode: "always" as const },
defaultValue: 75,
target: "selectedLayer.opacity",
type: "slider",
},
},
},
],
title: "Controls",
},
},
toolbar: { history },
},
modules: [],
});
}
afterEach(() => {
cleanup();
window.localStorage.clear();
});
describe("ToolcraftRoot", () => {
it("provides editor state and dispatch to children", async () => {
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "75" }));
expect(await screen.findByRole("button", { name: "50" })).toBeTruthy();
});
it("restores persisted values before first render", () => {
const schema = createPersistentSchema();
window.localStorage.setItem(
"toolcraft:root-test:state:v2",
JSON.stringify({
state: { values: { "selectedLayer.opacity": 33 } },
version: 2,
}),
);
render(
,
);
expect(screen.getByRole("button", { name: "33" })).toBeTruthy();
});
it("persists runtime values and reset results through schema policy", async () => {
const schema = createPersistentSchema();
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "75" }));
await waitFor(() => {
expect(
JSON.parse(
window.localStorage.getItem("toolcraft:root-test:state:v2") ?? "{}",
),
).toMatchObject({
state: { values: { "selectedLayer.opacity": 50 } },
version: 2,
});
});
fireEvent.click(screen.getByRole("button", { name: "Reset" }));
await waitFor(() => {
expect(
JSON.parse(
window.localStorage.getItem("toolcraft:root-test:state:v2") ?? "{}",
),
).toMatchObject({
state: { values: { "selectedLayer.opacity": 75 } },
version: 2,
});
});
});
it("restores dragged panel offsets from the app persistence policy before first render", async () => {
const schema = createPersistentSchema();
const firstRender = render(
,
);
fireEvent.click(screen.getByRole("button", { name: "0,0" }));
await waitFor(() => {
expect(
JSON.parse(
window.localStorage.getItem("toolcraft:root-test:state:v2") ?? "{}",
),
).toMatchObject({
state: { panels: { controls: { offset: { x: 72, y: -24 } } } },
version: 2,
});
});
firstRender.unmount();
render(
,
);
expect(screen.getByRole("button", { name: "72,-24" })).toBeTruthy();
});
it("binds runtime undo and redo to keyboard shortcuts when history is enabled", async () => {
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "75" }));
expect(await screen.findByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(document, { key: "z", metaKey: true });
expect(screen.getByRole("button", { name: "75" })).toBeTruthy();
fireEvent.keyDown(document, { key: "z", metaKey: true, shiftKey: true });
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(document, { key: "z", ctrlKey: true });
expect(screen.getByRole("button", { name: "75" })).toBeTruthy();
fireEvent.keyDown(document, { key: "y", ctrlKey: true });
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
});
it("binds runtime history shortcuts from focused non-text inputs", async () => {
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "75" }));
expect(await screen.findByRole("button", { name: "50" })).toBeTruthy();
const slider = screen.getByRole("slider", { name: "Opacity slider" });
const checkbox = screen.getByRole("checkbox", {
name: "Include background",
});
fireEvent.keyDown(slider, { key: "z", metaKey: true });
expect(screen.getByRole("button", { name: "75" })).toBeTruthy();
fireEvent.keyDown(slider, { key: "z", metaKey: true, shiftKey: true });
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(checkbox, { key: "z", ctrlKey: true });
expect(screen.getByRole("button", { name: "75" })).toBeTruthy();
fireEvent.keyDown(checkbox, { key: "y", ctrlKey: true });
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
});
it("does not hijack undo shortcuts while the user is typing into editable controls", async () => {
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "75" }));
expect(await screen.findByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(screen.getByRole("textbox", { name: "Text value" }), {
key: "z",
metaKey: true,
});
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(screen.getByRole("textbox", { name: "Notes" }), {
key: "z",
metaKey: true,
});
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(screen.getByRole("combobox", { name: "Mode" }), {
key: "z",
metaKey: true,
});
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(screen.getByRole("textbox", { name: "Editable value" }), {
key: "z",
metaKey: true,
});
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
});
it("does not register history shortcuts when toolbar history is disabled", async () => {
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "75" }));
expect(await screen.findByRole("button", { name: "50" })).toBeTruthy();
fireEvent.keyDown(document, { key: "z", metaKey: true });
expect(screen.getByRole("button", { name: "50" })).toBeTruthy();
});
});