import { Sentiment } from '../../common'; import { mockMatchMedia, render, screen } from '../../test-utils'; import { ActionPrompt, ActionPromptProps } from './ActionPrompt'; import { userEvent } from '@testing-library/user-event'; mockMatchMedia(); describe('ActionPrompt', () => { const defaultProps: ActionPromptProps = { title: 'Test Title', action: { label: 'Primary Action', onClick: jest.fn(), }, }; beforeEach(() => { jest.clearAllMocks(); }); describe('Basic rendering', () => { it('renders title', () => { render(); expect(screen.getByText('Test Title')).toBeInTheDocument(); }); it('renders description when provided', () => { render(); expect(screen.getByText('Test description')).toBeInTheDocument(); }); }); [ { sentiment: 'negative' as const, statusIconLabel: 'Error:' }, { sentiment: 'warning' as const, statusIconLabel: 'Warning:' }, { sentiment: 'neutral' as const, statusIconLabel: 'Information:' }, { sentiment: 'success' as const, statusIconLabel: 'Success:' }, { sentiment: 'proposition' as const, statusIconLabel: '' }, ].forEach(({ sentiment, statusIconLabel }) => { describe(sentiment, () => { if (statusIconLabel) { it('should render StatusIcon', () => { render(); expect(screen.getByLabelText(statusIconLabel)).toBeInTheDocument(); }); } }); }); describe('Actions', () => { it('renders primary action button with correct label', () => { render(); expect(screen.getByText('Primary Action')).toBeInTheDocument(); }); it('calls primary action onClick when clicked', async () => { const onClick = jest.fn(); const user = userEvent.setup(); render(); const button = screen.getByRole('button', { name: 'Primary Action' }); await user.click(button); expect(onClick).toHaveBeenCalledTimes(1); }); it('renders primary action as link when href is provided', () => { render( , ); const link = screen.getByRole('link', { name: 'Primary Action' }); expect(link).toHaveAttribute('href', '/test-url'); }); it('renders secondary action when provided', () => { render( , ); expect(screen.getByText('Secondary Action')).toBeInTheDocument(); }); it('calls secondary action onClick when clicked', async () => { const onClick = jest.fn(); const user = userEvent.setup(); render( , ); const button = screen.getByRole('button', { name: 'Secondary Action' }); await user.click(button); expect(onClick).toHaveBeenCalledTimes(1); }); it('renders secondary action as link when href is provided', () => { render( , ); const link = screen.getByRole('link', { name: 'Secondary Action' }); expect(link).toHaveAttribute('href', '/secondary-url'); }); }); describe('Media', () => { describe('Image media', () => { it('renders custom image when imgSrc is provided', () => { render( , ); const img = screen.getByRole('img', { name: 'Test image' }); expect(img).toBeInTheDocument(); expect(img).toHaveAttribute('src', '/test-image.jpg'); }); it('renders image with empty alt when aria-label is not provided', () => { const { container } = render( , ); const img = container.querySelector('img[src="/test-image.jpg"]'); expect(img).toHaveAttribute('alt', ''); }); }); describe('Avatar media', () => { it('renders avatar with image', () => { const { container } = render( , ); const img = container.querySelector('img[src="/avatar.jpg"]'); expect(img).toBeInTheDocument(); expect(img).toHaveAttribute('src', '/avatar.jpg'); }); it('renders avatar with profile name', () => { render(); expect(screen.getByText('JD')).toBeInTheDocument(); }); it('renders avatar with custom asset', () => { render( Icon } }} />, ); expect(screen.getByTestId('custom-icon')).toBeInTheDocument(); }); it('renders avatar with badge', () => { render( , ); expect(screen.getByText('Test Title')).toBeInTheDocument(); }); it('applies status badge for non-proposition sentiment when no badge is provided', () => { render( , ); expect(screen.getByText('Test Title')).toBeInTheDocument(); }); it('renders avatar for proposition sentiment when no badge is provided', () => { render( , ); expect(screen.getByText('Test Title')).toBeInTheDocument(); }); }); describe('Default media', () => { it('renders GiftBox for proposition sentiment with no media', () => { render(); expect(screen.getByTestId('gift-box-icon')).toBeInTheDocument(); }); it('renders StatusIcon for non-proposition sentiment with no media', () => { render(); expect(screen.getByText('Test Title')).toBeInTheDocument(); }); }); }); describe('Two actions styling', () => { it('applies two actions class when secondary action is provided', () => { render( , ); expect(screen.getByTestId('prompt')).toHaveClass('wds-action-prompt--with-two-actions'); }); it('does not apply two actions class when only primary action is provided', () => { render(); expect(screen.getByTestId('prompt')).not.toHaveClass('wds-action-prompt--with-two-actions'); }); }); describe('Responsive behavior', () => { it('renders buttons as block on mobile', () => { // Mock mobile viewport const mockMatchMediaFn = window.matchMedia as jest.Mock; mockMatchMediaFn.mockImplementation((query: string) => ({ matches: query === '(max-width: 768px)', media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })); render( , ); expect(screen.getByText('Primary Action')).toBeInTheDocument(); expect(screen.getByText('Secondary')).toBeInTheDocument(); }); }); });