import { beforeEach, describe, expect, it, vi } from 'vitest' import { fireEvent, renderWithProviders, screen, waitFor, } from '../../../test/utils' import DownloadAction from './DownloadAction' import { triggerDownload } from './triggerDownload' import { VIEWER_ACTION_CLASS } from './viewerChromeClasses' vi.mock('./triggerDownload', () => ({ triggerDownload: vi.fn(() => Promise.resolve()), })) const mockedTriggerDownload = vi.mocked(triggerDownload) beforeEach(() => { mockedTriggerDownload.mockReset() mockedTriggerDownload.mockResolvedValue(undefined) }) describe('DownloadAction', () => { it('uses a visible label for the default pill variant', () => { renderWithProviders() const button = screen.getByRole('button', { name: 'Download' }) expect(button).toHaveTextContent('Download') expect(button).not.toHaveAttribute('aria-label') }) it.each(['inline', 'viewer'] as const)( 'uses an accessible-only label for the %s variant', (variant) => { renderWithProviders( ) const button = screen.getByRole('button', { name: 'Save file' }) expect(button).not.toHaveTextContent('Save file') } ) it('allows iconOnly to control the pill label', () => { const { rerender } = renderWithProviders( ) expect(screen.getByRole('button', { name: 'Save' })).not.toHaveTextContent( 'Save' ) rerender() expect(screen.getByRole('button', { name: 'Save' })).toHaveTextContent( 'Save' ) }) it.each(['inline', 'viewer'] as const)( 'keeps the %s label visually hidden regardless of iconOnly', (variant) => { const { rerender } = renderWithProviders( ) expect( screen.getByRole('button', { name: 'Save' }) ).not.toHaveTextContent('Save') rerender( ) expect( screen.getByRole('button', { name: 'Save' }) ).not.toHaveTextContent('Save') } ) it('stops propagation and calls the download once', async () => { const outerClick = vi.fn() renderWithProviders( // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
) fireEvent.click(screen.getByRole('button', { name: 'Download' })) await waitFor(() => expect(mockedTriggerDownload).toHaveBeenCalledWith( '/file.pdf', 'report.pdf' ) ) expect(mockedTriggerDownload).toHaveBeenCalledOnce() expect(outerClick).not.toHaveBeenCalled() }) it('disables repeated clicks while downloading and settles on success', async () => { let resolve: () => void = () => undefined mockedTriggerDownload.mockReturnValueOnce( new Promise((done) => { resolve = done }) ) const onTriggered = vi.fn() renderWithProviders( ) const button = screen.getByRole('button', { name: 'Download' }) fireEvent.click(button) fireEvent.click(button) expect(button).toBeDisabled() expect(mockedTriggerDownload).toHaveBeenCalledOnce() resolve() await waitFor(() => expect(button).toBeEnabled()) expect(onTriggered).toHaveBeenCalledOnce() }) it('settles and notifies even when downloading rejects', async () => { mockedTriggerDownload.mockRejectedValueOnce(new Error('offline')) const onTriggered = vi.fn() renderWithProviders( ) const button = screen.getByRole('button', { name: 'Download' }) fireEvent.click(button) await waitFor(() => expect(button).toBeEnabled()) expect(onTriggered).toHaveBeenCalledOnce() }) it('maps tone classes for pill and inline variants', () => { const { rerender } = renderWithProviders( ) expect(screen.getByRole('button', { name: 'Download' })).toHaveClass( 'hover:bg-[#2a2928]' ) rerender() expect(screen.getByRole('button', { name: 'Download' })).toHaveClass( 'hover:bg-white/90' ) rerender() expect(screen.getByRole('button', { name: 'Download' })).toHaveClass( 'hover:text-white' ) rerender() expect(screen.getByRole('button', { name: 'Download' })).toHaveClass( 'hover:text-black' ) }) it('uses the shared viewer action class', () => { renderWithProviders() expect(screen.getByRole('button', { name: 'Download' })).toHaveClass( VIEWER_ACTION_CLASS ) }) })