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 ( {JSON.stringify(useToolcraftPersistenceStatus())} ); } 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); });