import { act, cleanup, render } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { ToolcraftExternalStore } from "../../state/toolcraft-external-store";
import { ToolcraftRoot } from "./toolcraft-root";
import {
CaptureStore,
createValuesPersistenceSchema,
} from "./toolcraft-root-persistence-test-utils";
const storageKey = "toolcraft:root-test-committed-values:state:v2";
afterEach(() => {
vi.useRealTimers();
cleanup();
window.localStorage.clear();
});
describe("ToolcraftRoot current persistence version", () => {
it("hydrates the exact current snapshot", () => {
const schema = createValuesPersistenceSchema();
let store: ToolcraftExternalStore | undefined;
window.localStorage.setItem(
storageKey,
JSON.stringify({
state: { values: { "selectedLayer.opacity": 33 } },
version: 2,
}),
);
render(
{
store = nextStore;
}}
/>
,
);
expect(store?.getCommittedState().values["selectedLayer.opacity"]).toBe(33);
});
it.each([
{ trigger: "timer", version: 1 },
{ trigger: "pagehide", version: 1 },
{ trigger: "unmount", version: 1 },
{ trigger: "timer", version: 3 },
{ trigger: "pagehide", version: 3 },
{ trigger: "unmount", version: 3 },
] as const)(
"blocks malformed version $version hydration and preserves bytes on $trigger",
({ trigger, version }) => {
vi.useFakeTimers();
const schema = createValuesPersistenceSchema();
const raw = JSON.stringify({
state: version === 1 ? "malformed-v1" : null,
version,
});
let store: ToolcraftExternalStore | undefined;
window.localStorage.setItem(storageKey, raw);
const rendered = render(
{
store = nextStore;
}}
/>
,
);
const capturedStore = store;
if (!capturedStore) {
throw new Error("Expected ToolcraftRoot to publish its store");
}
act(() => {
capturedStore.dispatch({
target: "selectedLayer.opacity",
type: "controls.setValue",
value: 50,
});
});
if (trigger === "timer") {
act(() => {
vi.advanceTimersByTime(1_000);
});
} else if (trigger === "pagehide") {
act(() => {
window.dispatchEvent(new Event("pagehide"));
});
} else {
rendered.unmount();
}
expect(
capturedStore.getCommittedState().values["selectedLayer.opacity"],
).toBe(50);
expect(window.localStorage.getItem(storageKey)).toBe(raw);
if (trigger !== "unmount") {
rendered.unmount();
}
},
);
});