// @vitest-environment jsdom import { act } from 'react'; import { createElement } from 'react'; import { createRoot, type Root } from 'react-dom/client'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { PageSnapshotProvider } from '../provider'; import { usePageSnapshot, type PageSnapshotContextValue, } from '../use-page-snapshot'; // React 19 act() environment flag. (globalThis as Record).IS_REACT_ACT_ENVIRONMENT = true; let container: HTMLDivElement; let root: Root; /** Latest context value, captured by the probe component each render. */ let ctx: PageSnapshotContextValue | null = null; /** Probe component — publishes the context value to the test. */ function Probe() { ctx = usePageSnapshot(); return null; } beforeEach(() => { container = document.createElement('div'); document.body.appendChild(container); root = createRoot(container); }); afterEach(() => { act(() => root.unmount()); container.remove(); ctx = null; }); /** Render the provider with the probe inside; flushes effects. */ async function render(defaultLinked = false) { await act(async () => { root.render( createElement(PageSnapshotProvider, { defaultLinked, children: createElement(Probe), }), ); }); } describe('PageSnapshotProvider / usePageSnapshot', () => { it('defaults to not linked', async () => { await render(); expect(ctx!.isLinked).toBe(false); expect(ctx!.lastSnapshot).toBeNull(); }); it('capture() returns null while not linked', async () => { await render(); let result: unknown; act(() => { result = ctx!.capture(); }); expect(result).toBeNull(); }); it('getChatMetadata() returns undefined while not linked', async () => { await render(); expect(ctx!.getChatMetadata()).toBeUndefined(); }); it('generatePreview() works even when not linked (preview gate)', async () => { document.body.innerHTML += '

Preview Page

'; await render(); let preview: ReturnType; act(() => { preview = ctx!.generatePreview(); }); expect(preview!).not.toBeNull(); expect(preview!.payload.snapshot.type).toBe('root'); }); it('opting in captures an initial snapshot', async () => { document.body.innerHTML += '

Linked Page

'; await render(); await act(async () => { ctx!.setIsLinked(true); }); expect(ctx!.isLinked).toBe(true); expect(ctx!.lastSnapshot).not.toBeNull(); }); it('getChatMetadata() returns { pageContext } when linked', async () => { document.body.innerHTML += '

Meta Page

'; await render(true); let meta: Record | undefined; await act(async () => { meta = ctx!.getChatMetadata(); }); expect(meta).toBeDefined(); expect(meta).toHaveProperty('pageContext'); }); });