import { StrictMode, useLayoutEffect } from "react";
import { act, cleanup, render, screen } from "@testing-library/react";
import { afterEach, expect, it, vi } from "vitest";
import { createToolcraftPersistenceSnapshot } from "../../composition/public-persistence";
import { createToolcraftState } from "../../state/create-template-state";
import type { ToolcraftExternalStore } from "../../state/toolcraft-external-store";
import { ToolcraftRoot } from "./toolcraft-root";
import {
CaptureStore,
createValuesPersistenceSchema,
} from "./toolcraft-root-persistence-test-utils";
import { useToolcraftPersistenceStatus } from "./use-toolcraft-persistence";
const storageKey = "toolcraft:root-test-committed-values:state:v2";
function Status() {
return (
);
}
afterEach(() => {
cleanup();
vi.useRealTimers();
window.localStorage.clear();
});
it("protects the snapshot read at bootstrap before the first persistence effect", () => {
vi.useFakeTimers();
const schema = createValuesPersistenceSchema();
const newer = JSON.stringify(
createToolcraftPersistenceSnapshot(
createToolcraftState(schema, { values: { "selectedLayer.opacity": 25 } }),
schema.persistence,
),
);
function InterveningWrite() {
useLayoutEffect(() => {
window.localStorage.setItem(storageKey, newer);
}, []);
return null;
}
const view = render(
,
);
act(() => {
vi.advanceTimersByTime(120);
});
expect(screen.getByLabelText("Persistence status").textContent).toContain("stale-snapshot");
expect(window.localStorage.getItem(storageKey)).toBe(newer);
view.unmount();
expect(window.localStorage.getItem(storageKey)).toBe(newer);
});
it("preserves successful checkpoints through StrictMode and refuses stale pagehide/unmount writes", () => {
vi.useFakeTimers();
const schema = createValuesPersistenceSchema();
let store!: ToolcraftExternalStore;
const view = render(
{
store = value;
}}
/>
,
);
act(() => {
vi.advanceTimersByTime(120);
});
expect(screen.getByLabelText("Persistence status").textContent).toContain("success");
act(() => {
store.dispatch({ type: "controls.setValue", target: "selectedLayer.opacity", value: 50 });
vi.advanceTimersByTime(120);
});
expect(
JSON.parse(window.localStorage.getItem(storageKey)!).state.values["selectedLayer.opacity"],
).toBe(50);
const newer = JSON.stringify(
createToolcraftPersistenceSnapshot(
createToolcraftState(schema, { values: { "selectedLayer.opacity": 25 } }),
schema.persistence,
),
);
window.localStorage.setItem(storageKey, newer);
act(() => {
store.dispatch({ type: "controls.setValue", target: "selectedLayer.opacity", value: 60 });
window.dispatchEvent(new Event("pagehide"));
});
expect(screen.getByLabelText("Persistence status").textContent).toContain("stale-snapshot");
expect(store.getCommittedState().values["selectedLayer.opacity"]).toBe(60);
expect(window.localStorage.getItem(storageKey)).toBe(newer);
act(() => {
vi.advanceTimersByTime(500);
});
view.unmount();
expect(window.localStorage.getItem(storageKey)).toBe(newer);
});