import React from 'react'; import userEvent from '@testing-library/user-event'; import { resetWarned } from 'rc-util/lib/warning'; import Alert from '..'; import accessibilityTest from '../../../tests/shared/accessibilityTest'; import rtlTest from '../../../tests/shared/rtlTest'; import { act, render, screen, waitFakeTimer } from '../../../tests/utils'; import Button from '../../button'; import Popconfirm from '../../popconfirm'; import Tooltip from '../../tooltip'; import type { AlertRef } from '../Alert'; const { ErrorBoundary } = Alert; describe('Alert', () => { rtlTest(Alert); accessibilityTest(Alert); beforeAll(() => { jest.useFakeTimers(); }); afterAll(() => { jest.useRealTimers(); }); it('should show close button and could be closed', async () => { const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const onClose = jest.fn(); render( , ); await act(async () => { await userEvent.click(screen.getByRole('button', { name: /close/i })); jest.runAllTimers(); }); expect(onClose).toHaveBeenCalledTimes(1); expect(errSpy).not.toHaveBeenCalled(); errSpy.mockRestore(); }); it('custom action', () => { const { container } = render( UNDO } closable />, ); expect(container.firstChild).toMatchSnapshot(); }); it('should sets data attributes on alert when pass attributes to props', () => { render( , ); const alert = screen.getByRole('alert'); expect(alert).toHaveAttribute('data-test', 'test-id'); expect(alert).toHaveAttribute('data-id', '12345'); expect(alert).toHaveAttribute('aria-describedby', 'some-label'); }); it('sets role attribute on input', () => { render(); expect(screen.getByRole('status')).toBeInTheDocument(); }); it('should show error as ErrorBoundary when children have error', () => { const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); expect(warnSpy).toHaveBeenCalledTimes(0); // @ts-expect-error const ThrowError = () => ; render( , ); expect(screen.getByRole('alert')).toHaveTextContent( 'ReferenceError: NotExisted is not defined', ); warnSpy.mockRestore(); }); it('could be used with Tooltip', async () => { render( , ); await userEvent.hover(screen.getByRole('alert')); await waitFakeTimer(); expect(document.querySelector('.ant-tooltip')).toBeInTheDocument(); }); it('could be used with Popconfirm', async () => { render( , ); await userEvent.click(screen.getByRole('alert')); act(() => { jest.runAllTimers(); }); expect(screen.getByRole('tooltip')).toBeInTheDocument(); }); it('could accept none react element icon', () => { render(); expect(screen.getByRole('alert')).toHaveTextContent(/success tips/i); expect(screen.getByRole('alert')).toHaveTextContent(/icon/i); }); it('should not render message div when no message', () => { const { container } = render(); expect(!!container.querySelector('.ant-alert-message')).toBe(false); }); it('close button should be hidden when closeIcon setting to null or false', () => { const { container, rerender } = render(); expect(container.querySelector('.ant-alert-close-icon')).toBeFalsy(); rerender(); expect(container.querySelector('.ant-alert-close-icon')).toBeFalsy(); rerender(); expect(container.querySelector('.ant-alert-close-icon')).toBeTruthy(); rerender(); expect(container.querySelector('.ant-alert-close-icon')).toBeFalsy(); }); it('close button should be support aria-* by closable', () => { const { container, rerender } = render(); expect(container.querySelector('*[aria-label]')).toBeFalsy(); rerender(); expect(container.querySelector('[aria-label="Close"]')).toBeTruthy(); rerender(); expect(container.querySelector('[aria-label="Close"]')).toBeTruthy(); rerender(); expect(container.querySelector('[aria-label="Close"]')).toBeTruthy(); }); it('close button should be support custom icon by closable', () => { const { container, rerender } = render(); expect(container.querySelector('.ant-alert-close-icon')).toBeFalsy(); rerender(); expect(container.querySelector('.ant-alert-close-icon')?.textContent).toBe('CloseBtn'); rerender(); expect(container.querySelector('.ant-alert-close-icon')?.textContent).toBe('CloseBtn'); rerender(); expect(container.querySelector('.ant-alert-close-icon')?.textContent).toBe('CloseBtn'); rerender(); expect(container.querySelector('.ant-alert-close-icon')?.textContent).toBe('CloseBtn2'); rerender(); expect(container.querySelector('.ant-alert-close-icon')?.textContent).toBe('CloseBtn3'); }); it('should warning when using closeText', () => { resetWarned(); const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const { container } = render(); expect(warnSpy).toHaveBeenCalledWith( `Warning: [antd: Alert] \`closeText\` is deprecated. Please use \`closable.closeIcon\` instead.`, ); expect(container.querySelector('.ant-alert-close-icon')?.textContent).toBe('close'); warnSpy.mockRestore(); }); it('should support id and ref', () => { const alertRef = React.createRef(); const { container } = render(); const element = container.querySelector('#test-id'); expect(element).toBeTruthy(); expect(alertRef.current?.nativeElement).toBeTruthy(); expect(alertRef.current?.nativeElement).toBe(element); }); });