import { useEffect, useRef } from 'react' import { describe, it, expect, beforeEach, afterEach } from 'vitest' import { fireEvent, render, screen } from '@testing-library/react' import { Provider } from '../../provider/widget-provider' import { clearAllWidgetStores, getWidgetStore } from '../../stores' import { FullScreen } from './fullscreen' import type { FullScreenWidgetState } from './types' beforeEach(() => clearAllWidgetStores()) afterEach(() => clearAllWidgetStores()) describe(' — store toggle', () => { it('does not surface isFullScreen on the base WidgetState until the trigger fires', () => { render( , ) const state = getWidgetStore('fs1').getState() expect((state as FullScreenWidgetState).isFullScreen).toBeUndefined() }) it('toggles state on click and swaps the trigger label', () => { render( , ) fireEvent.click(screen.getByLabelText('Expand')) expect(screen.getByLabelText('Shrink')).toBeTruthy() expect( (getWidgetStore('fs2').getState() as FullScreenWidgetState).isFullScreen, ).toBe(true) fireEvent.click(screen.getByLabelText('Shrink')) expect(screen.getByLabelText('Expand')).toBeTruthy() expect( (getWidgetStore('fs2').getState() as FullScreenWidgetState).isFullScreen, ).toBe(false) }) it('keepAlive remount restores isFullScreen', () => { const { unmount } = render( , ) fireEvent.click(screen.getByLabelText('Maximise')) expect( (getWidgetStore('fs3').getState() as FullScreenWidgetState).isFullScreen, ).toBe(true) unmount() render( , ) expect( (getWidgetStore('fs3').getState() as FullScreenWidgetState).isFullScreen, ).toBe(true) }) }) describe(' — render-prop body + portal', () => { it('passes the live isFullScreen flag to the render prop', () => { let received: boolean | undefined render( {(isFullScreen) => { received = isFullScreen return body }} , ) expect(received).toBe(false) fireEvent.click(screen.getByLabelText('Open in full screen')) expect(received).toBe(true) }) it('renders the title above the body when open', async () => { render( {() =>
body
}
, ) fireEvent.click(screen.getByLabelText('Open in full screen')) expect(await screen.findByText('Sales by region')).toBeTruthy() }) it('still renders the close button when no title is given', async () => { render( {() =>
body
}
, ) fireEvent.click(screen.getByLabelText('Open in full screen')) const closes = await screen.findAllByLabelText('Exit full screen') expect(closes.length).toBeGreaterThan(0) }) it('keeps the same DOM node across the fullscreen toggle (portal reparent)', () => { render( {() => inner} , ) const before = screen.getByTestId('inner') fireEvent.click(screen.getByLabelText('Open in full screen')) const after = screen.getByTestId('inner') expect(after).toBe(before) }) it('mounts the body exactly once across multiple fullscreen toggles', () => { let mountCount = 0 function CountingChild() { const counted = useRef(false) useEffect(() => { if (counted.current) return counted.current = true mountCount += 1 }, []) return
x
} // Distinct labels for the trigger so its "close" aria-label can't collide // with the modal's own close button (also "Exit full screen" by default // when keepMounted=true keeps the modal in DOM). render( {() => } , ) expect(mountCount).toBe(1) fireEvent.click(screen.getByLabelText('OpenT')) expect(mountCount).toBe(1) fireEvent.click(screen.getByLabelText('CloseT')) expect(mountCount).toBe(1) fireEvent.click(screen.getByLabelText('OpenT')) expect(mountCount).toBe(1) }) })