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(); } }, ); });