import { describe, expect, it, vi } from 'vitest' import { fireEvent, renderWithProviders, screen } from '../../../test/utils' import MediaStackGrid from './MediaStackGrid' const tiles = (count: number) => Array.from({ length: count }, (_, index) => ({ content: tile {index + 1}, ariaLabel: index === 1 ? 'Second tile' : undefined, })) describe('MediaStackGrid', () => { it('renders nothing for empty tiles', () => { const { container } = renderWithProviders() expect(container.firstChild).toBeNull() }) it.each([ [1, 'aspect-square'], [2, 'aspect-[16/9]'], [3, 'aspect-[4/3]'], [4, 'aspect-[379/286]'], ])('renders the %s-tile layout', (count, layoutClass) => { const { container } = renderWithProviders( ) expect(container.firstElementChild).toHaveClass(layoutClass, 'custom-grid') expect(screen.getAllByText(/tile/)).toHaveLength(count) }) it('clamps visible tiles and places overflow on the last tile', () => { const { container, rerender } = renderWithProviders( ) expect(container.querySelectorAll('span')).toHaveLength(4) expect(screen.getByText('+2')).toBeInTheDocument() expect(screen.getByText('+2').parentElement).toHaveTextContent('tile 4') rerender() expect(container.querySelectorAll('span')).toHaveLength(2) expect(screen.queryByText(/^\+/)).toBeNull() rerender() expect( screen.getByText('tile 1').closest('div')?.parentElement ).toHaveStyle({ aspectRatio: '0.5', }) }) it.each([ [2, '+3', 'tile 2'], [3, '+2', 'tile 3'], ])( 'shows overflow on the last visible tile when maxVisible is %s', (maxVisible, badge, lastTile) => { const { container } = renderWithProviders( ) expect(container.querySelectorAll('span')).toHaveLength(maxVisible) expect(screen.getByText(badge)).toBeInTheDocument() expect(screen.getByText(badge).parentElement).toHaveTextContent(lastTile) } ) it('shows overflow on the single visible tile', () => { const { container } = renderWithProviders( ) expect(container.querySelectorAll('span')).toHaveLength(1) expect(screen.getByText('+2').parentElement).toHaveTextContent('tile 1') }) it('does not show overflow when all tiles are visible', () => { renderWithProviders() expect(screen.queryByText(/^\+/)).toBeNull() }) it('renders activatable buttons with labels and indexes', () => { const onActivate = vi.fn() renderWithProviders( ) const buttons = screen.getAllByRole('button') expect(buttons).toHaveLength(3) expect(buttons[0]).toHaveAttribute('aria-label', 'Open media 1') expect(buttons[1]).toHaveAttribute('aria-label', 'Second tile') fireEvent.click(buttons[0]) fireEvent.click(buttons[2]) expect(onActivate).toHaveBeenNthCalledWith(1, 0) expect(onActivate).toHaveBeenNthCalledWith(2, 2) }) it('uses non-interactive shells when no activation handler is supplied', () => { renderWithProviders() expect(screen.queryAllByRole('button')).toHaveLength(0) }) })