/** * Tests for PreviewModalShell (#2976) — the backdrop, panel size and header * every file preview shares. */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { act, fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { PreviewModalShell } from '../../components/PreviewModalShell'; import { usePreviewFullscreen } from '../../hooks/usePreviewFullscreen'; const mockOnClose = vi.fn(); function Harness({ closeOnBackdropClick }: { closeOnBackdropClick?: boolean }) { const fullscreen = usePreviewFullscreen(); return ( Zoom in} >
body
); } function panelOf(): HTMLElement { return screen.getByText('drawing.pdf').closest('.flex-col') as HTMLElement; } describe('PreviewModalShell', () => { const requestFullscreen = vi.fn(); const exitFullscreen = vi.fn(); beforeEach(() => { vi.clearAllMocks(); requestFullscreen.mockResolvedValue(undefined); exitFullscreen.mockResolvedValue(undefined); Object.defineProperty(document, 'fullscreenEnabled', { configurable: true, value: true }); Object.defineProperty(document, 'fullscreenElement', { configurable: true, value: null, writable: true }); Object.defineProperty(document, 'exitFullscreen', { configurable: true, value: exitFullscreen }); Object.defineProperty(HTMLElement.prototype, 'requestFullscreen', { configurable: true, value: requestFullscreen }); }); afterEach(() => { delete (document as { fullscreenEnabled?: boolean }).fullscreenEnabled; delete (document as { fullscreenElement?: Element | null }).fullscreenElement; delete (document as { exitFullscreen?: () => Promise }).exitFullscreen; delete (HTMLElement.prototype as { requestFullscreen?: () => Promise }).requestFullscreen; }); // The browser flips fullscreenElement and fires fullscreenchange; the mocks // do neither, so the test plays the browser's part. function browserEntersFullscreen(panel: Element | null) { (document as { fullscreenElement: Element | null }).fullscreenElement = panel; act(() => { document.dispatchEvent(new Event('fullscreenchange')); }); } it('gives the panel the size every preview shares', () => { render(); const panel = panelOf(); expect(panel.className).toContain('w-[min(1800px,96vw)]'); expect(panel.className).toContain('h-[94vh]'); expect(panel.className).toContain('rounded-lg'); }); it('renders the title, the preview actions and the close button', async () => { const user = userEvent.setup(); render(); expect(screen.getByText('drawing.pdf')).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Zoom in' })).toBeInTheDocument(); await user.click(screen.getByRole('button', { name: 'Close' })); expect(mockOnClose).toHaveBeenCalledTimes(1); }); it('goes fullscreen on a double-click in the body and fills the screen', () => { render(); const panel = panelOf(); fireEvent.doubleClick(screen.getByTestId('preview-body')); expect(requestFullscreen).toHaveBeenCalledTimes(1); expect(requestFullscreen.mock.instances[0]).toBe(panel); browserEntersFullscreen(panel); expect(panel.className).toContain('max-w-none'); expect(panel.className).not.toContain('w-[min(1800px,96vw)]'); expect(screen.getByRole('button', { name: 'Exit fullscreen' })).toBeInTheDocument(); }); it('toggles fullscreen from the header button', async () => { const user = userEvent.setup(); render(); await user.click(screen.getByRole('button', { name: 'Fullscreen' })); expect(requestFullscreen).toHaveBeenCalledTimes(1); browserEntersFullscreen(panelOf()); await user.click(screen.getByRole('button', { name: 'Exit fullscreen' })); expect(exitFullscreen).toHaveBeenCalledTimes(1); }); it('closes on Escape, but leaves it to the browser while fullscreen', () => { render(); browserEntersFullscreen(panelOf()); fireEvent.keyDown(window, { key: 'Escape' }); expect(mockOnClose).not.toHaveBeenCalled(); browserEntersFullscreen(null); fireEvent.keyDown(window, { key: 'Escape' }); expect(mockOnClose).toHaveBeenCalledTimes(1); }); it('closes on a backdrop click only where the preview asks for it', async () => { const user = userEvent.setup(); const { unmount } = render(); const backdrop = panelOf().parentElement as HTMLElement; await user.click(backdrop); expect(mockOnClose).not.toHaveBeenCalled(); unmount(); render(); await user.click(panelOf().parentElement as HTMLElement); expect(mockOnClose).toHaveBeenCalledTimes(1); // A click inside the panel is not a backdrop click. await user.click(screen.getByTestId('preview-body')); expect(mockOnClose).toHaveBeenCalledTimes(1); }); });