import React, { act, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { Presence } from '@radix-ui/react-presence'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; const flushMicrotasks = async (): Promise => { await Promise.resolve(); await Promise.resolve(); }; describe('Radix Presence React 19 compatibility', () => { beforeEach(() => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); }); afterEach(() => { document.body.innerHTML = ''; vi.unstubAllGlobals(); }); it('does not recurse when a composed child ref changes identity and returns cleanup', async () => { const refEvents: string[] = []; const Harness = (): React.JSX.Element => { const [tick, setTick] = useState(0); return (
{ refEvents.push(node ? 'node' : 'null'); return () => { refEvents.push('cleanup'); }; }} > tick {tick}
); }; const host = document.createElement('div'); document.body.appendChild(host); const root = createRoot(host); await act(async () => { root.render(); await flushMicrotasks(); }); await act(async () => { host.querySelector('button')?.click(); await flushMicrotasks(); }); expect(host.textContent).toContain('tick 1'); expect(refEvents.length).toBeLessThan(10); expect(refEvents).toContain('cleanup'); await act(async () => { root.unmount(); await flushMicrotasks(); }); }); });