import { act, cleanup, fireEvent, render, screen, } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; import { timelineModule } from "../../modules/built-ins/timeline/timeline-module"; import { defineToolcraft } from "../../schema/define-toolcraft"; import type { ToolcraftExternalStore } from "../../state/toolcraft-external-store"; import { ToolcraftRoot } from "./toolcraft-root"; import { useToolcraftStore } from "./toolcraft-store-context"; import { useToolcraftDispatch } from "./use-toolcraft"; const playbackPersistenceSchema = defineToolcraft({ base: { identity: { id: "runtime-test", title: "Toolcraft App" }, canvas: { enabled: true }, panels: {}, persistence: { storage: "localStorage", }, }, modules: [ timelineModule({ mode: "playback", }), ], }); function CaptureStore({ capture, }: { capture: (store: ToolcraftExternalStore) => void; }): null { capture(useToolcraftStore()); return null; } function PublicPlaybackControls(): React.JSX.Element { const dispatch = useToolcraftDispatch(); return ( <> ); } afterEach(() => { vi.useRealTimers(); cleanup(); window.localStorage.clear(); }); describe("public playback persistence boundary", () => { it.each([ { buttonName: "Pause through public dispatch", label: "setPlaying(false)" }, { buttonName: "Toggle through public dispatch", label: "togglePlayback" }, ])( "persists and reloads transient time when public $label stops playback", ({ buttonName }) => { vi.useFakeTimers(); let store: ToolcraftExternalStore | undefined; const view = render( { store = value; }} /> , ); act(() => { vi.advanceTimersByTime(120); store?.dispatchTransient({ currentTimeSeconds: 2, type: "timeline.setCurrentTime", }); }); fireEvent.click(screen.getByRole("button", { name: buttonName })); expect(store?.getCommittedState().timeline).toMatchObject({ currentTimeSeconds: 2, isPlaying: false, }); act(() => { vi.advanceTimersByTime(120); }); view.unmount(); let reloadedStore: ToolcraftExternalStore | undefined; render( { reloadedStore = value; }} /> , ); expect(reloadedStore?.getState().timeline).toMatchObject({ currentTimeSeconds: 2, isPlaying: false, }); }, ); });