import { renderHook } from '@testing-library/react'; import { act } from 'react'; import usePortal from '../usePortal'; describe('usePortal', () => { afterEach(() => { document.body.innerHTML = ''; }); it('creates portal element when id and shouldCreate are provided', () => { const { result } = renderHook(() => usePortal('test-portal', true)); expect(result.current).toBeTruthy(); expect(document.querySelector('#test-portal')).toBeTruthy(); }); it('returns null when id is undefined', () => { const { result } = renderHook(() => usePortal(undefined, true)); expect(result.current).toBeNull(); expect(document.querySelector('#test-portal')).toBeNull(); }); it('returns null when shouldCreate is false', () => { const { result } = renderHook(() => usePortal('test-portal', false)); expect(result.current).toBeNull(); expect(document.querySelector('#test-portal')).toBeNull(); }); it('cleans up portal on unmount', async () => { const { result, rerender, unmount } = renderHook( ({ shouldCreate }: { shouldCreate: boolean }) => usePortal('test-portal', shouldCreate), { initialProps: { shouldCreate: true } }, ); expect(document.querySelector('#test-portal')).toBeTruthy(); // First set shouldCreate to false to trigger cleanup act(() => { rerender({ shouldCreate: false }); }); // Then unmount act(() => { unmount(); }); // Wait for cleanup to complete await act(async () => { await new Promise((resolve) => setTimeout(resolve, 100)); }); expect(document.querySelector('#test-portal')).toBeNull(); }); it('reuses existing portal if it exists', () => { const existingPortal = document.createElement('div'); existingPortal.id = 'existing-portal'; document.body.appendChild(existingPortal); const { result } = renderHook(() => usePortal('existing-portal', true)); expect(result.current).toBe(existingPortal); expect(document.querySelectorAll('#existing-portal')).toHaveLength(1); }); it('updates element reference when id changes', () => { const { result, rerender } = renderHook(({ id }) => usePortal(id, true), { initialProps: { id: 'portal-1' }, }); expect(document.querySelector('#portal-1')).toBeTruthy(); act(() => { rerender({ id: 'portal-2' }); }); expect(document.querySelector('#portal-2')).toBeTruthy(); expect(result.current?.id).toBe('portal-2'); }); });