import { act, render, screen } from '@testing-library/react'; import { WDS_LIVE_REGION_DELAY_MS } from '../constants'; import { LiveRegion, LiveRegionProps, resetLiveRegionAnnouncementQueue } from './LiveRegion'; describe('LiveRegion', () => { beforeEach(() => { jest.useFakeTimers(); resetLiveRegionAnnouncementQueue(); }); afterEach(() => { jest.clearAllTimers(); jest.useRealTimers(); }); const renderLiveRegion = (props: Partial & Pick) => render({props.children ?? 'Live content'}); const enableLiveRegion = (delay = WDS_LIVE_REGION_DELAY_MS) => { act(() => { jest.advanceTimersByTime(delay); }); }; describe('when aria-live is "polite"', () => { it('renders with role="status"', () => { renderLiveRegion({ 'aria-live': 'polite' }); enableLiveRegion(); expect(screen.getByRole('status')).toBeInTheDocument(); }); it('sets aria-live="polite"', () => { renderLiveRegion({ 'aria-live': 'polite' }); enableLiveRegion(); expect(screen.getByRole('status')).toHaveAttribute('aria-live', 'polite'); }); it('sets aria-atomic="true"', () => { renderLiveRegion({ 'aria-live': 'polite' }); enableLiveRegion(); expect(screen.getByRole('status')).toHaveAttribute('aria-atomic', 'true'); }); }); describe('when aria-live is "assertive"', () => { it('renders with role="alert"', () => { renderLiveRegion({ 'aria-live': 'assertive' }); enableLiveRegion(); expect(screen.getByRole('alert')).toBeInTheDocument(); }); it('sets aria-live="assertive"', () => { renderLiveRegion({ 'aria-live': 'assertive' }); enableLiveRegion(); expect(screen.getByRole('alert')).toHaveAttribute('aria-live', 'assertive'); }); it('sets aria-atomic="true"', () => { renderLiveRegion({ 'aria-live': 'assertive' }); enableLiveRegion(); expect(screen.getByRole('alert')).toHaveAttribute('aria-atomic', 'true'); }); }); it('delays live-region activation before the configured timeout', () => { renderLiveRegion({ 'aria-live': 'polite', children: 'Delayed content' }); const liveRegion = screen.getByRole('status'); expect(liveRegion).toBeInTheDocument(); expect(liveRegion.firstElementChild).toHaveAttribute('aria-hidden', 'true'); enableLiveRegion(WDS_LIVE_REGION_DELAY_MS - 1); expect(liveRegion.firstElementChild).toHaveAttribute('aria-hidden', 'true'); enableLiveRegion(1); expect(liveRegion.firstElementChild).not.toHaveAttribute('aria-hidden'); expect(liveRegion).toHaveTextContent('Delayed content'); }); it('queues multiple assertive regions so each one gets announced', () => { render( <> First prompt Second prompt , ); const liveRegions = screen.getAllByRole('alert'); expect(liveRegions).toHaveLength(2); expect(liveRegions[0].firstElementChild).toHaveAttribute('aria-hidden', 'true'); expect(liveRegions[1].firstElementChild).toHaveAttribute('aria-hidden', 'true'); enableLiveRegion(); const firstEnabledLiveRegions = screen.getAllByRole('alert'); expect(firstEnabledLiveRegions[0].firstElementChild).not.toHaveAttribute('aria-hidden'); expect(firstEnabledLiveRegions[1].firstElementChild).toHaveAttribute('aria-hidden', 'true'); expect(firstEnabledLiveRegions[0]).toHaveTextContent('First prompt'); enableLiveRegion(); const secondEnabledLiveRegions = screen.getAllByRole('alert'); expect(secondEnabledLiveRegions[1].firstElementChild).not.toHaveAttribute('aria-hidden'); expect(secondEnabledLiveRegions[0]).toHaveTextContent('First prompt'); expect(secondEnabledLiveRegions[1]).toHaveTextContent('Second prompt'); }); it('renders children', () => { renderLiveRegion({ 'aria-live': 'polite', children: 'Transfer sent' }); enableLiveRegion(); expect(screen.getByText('Transfer sent')).toBeInTheDocument(); }); it('passes additional HTML attributes to the wrapper div', () => { renderLiveRegion({ 'aria-live': 'polite', className: 'custom' }); enableLiveRegion(); expect(screen.getByRole('status')).toHaveClass('custom'); }); it('supports data-testid prop', () => { renderLiveRegion({ 'aria-live': 'polite', 'data-testid': 'live-region' }); enableLiveRegion(); expect(screen.getByTestId('live-region')).toBeInTheDocument(); }); });