import React, { useEffect } from 'react'; import { SmileOutlined } from '@ant-design/icons'; import type { NotificationConfig } from 'antd/es/notification/interface'; import App from '..'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; import { render, waitFakeTimer } from '../../../tests/utils'; import type { AppConfig } from '../context'; import { AppConfigContext } from '../context'; describe('App', () => { mountTest(App); rtlTest(App); beforeEach(() => { jest.useFakeTimers(); }); afterEach(() => { jest.clearAllTimers(); jest.useRealTimers(); }); it('single', () => { // Sub page const MyPage: React.FC = () => { const { message } = App.useApp(); React.useEffect(() => { message.success('Good!'); }, [message]); return
Hello World
; }; // Entry component const MyApp: React.FC = () => ( ); const { getByText, container } = render(); expect(getByText('Hello World')).toBeTruthy(); expect(container.firstChild).toMatchSnapshot(); }); it('should work as message and notification config configured in app', async () => { let consumedConfig: AppConfig | undefined; const Consumer = () => { const { message, notification } = App.useApp(); consumedConfig = React.useContext(AppConfigContext); useEffect(() => { message.success('Message 1'); message.success('Message 2'); notification.success({ message: 'Notification 1' }); notification.success({ message: 'Notification 2' }); notification.success({ message: 'Notification 3' }); }, [message, notification]); return
; }; const Wrapper = () => ( ); render(); await waitFakeTimer(); expect(consumedConfig?.message).toStrictEqual({ maxCount: 1 }); expect(consumedConfig?.notification).toStrictEqual({ maxCount: 2 }); expect(document.querySelectorAll('.ant-message-notice')).toHaveLength(1); expect(document.querySelectorAll('.ant-notification-notice')).toHaveLength(2); }); it('should be a merged config configured in nested app', async () => { let offsetConsumedConfig: AppConfig | undefined; let maxCountConsumedConfig: AppConfig | undefined; const OffsetConsumer = () => { offsetConsumedConfig = React.useContext(AppConfigContext); return
; }; const MaxCountConsumer = () => { maxCountConsumedConfig = React.useContext(AppConfigContext); return
; }; const Wrapper = () => ( ); render(); expect(offsetConsumedConfig?.message).toStrictEqual({ maxCount: 1, top: 32 }); expect(offsetConsumedConfig?.notification).toStrictEqual({ maxCount: 2, top: 96 }); expect(maxCountConsumedConfig?.message).toStrictEqual({ maxCount: 1 }); expect(maxCountConsumedConfig?.notification).toStrictEqual({ maxCount: 2 }); }); it('should respect config from props in priority', async () => { let config: AppConfig | undefined; const Consumer = () => { config = React.useContext(AppConfigContext); return
; }; const Wrapper = () => ( ); render(); expect(config?.message).toStrictEqual({ maxCount: 11, top: 20 }); expect(config?.notification).toStrictEqual({ maxCount: 30, bottom: 41 }); }); it('should respect notification placement config from props in priority', async () => { let consumedConfig: AppConfig | undefined; const Consumer = () => { const { notification } = App.useApp(); consumedConfig = React.useContext(AppConfigContext); useEffect(() => { notification.success({ message: 'Notification 1' }); notification.success({ message: 'Notification 2' }); notification.success({ message: 'Notification 3' }); }, [notification]); return
; }; const config: NotificationConfig = { placement: 'bottomLeft', top: 100, bottom: 50, }; const Wrapper = () => ( ); render(); await waitFakeTimer(); expect(consumedConfig?.notification).toStrictEqual(config); expect(document.querySelector('.ant-notification-topRight')).not.toBeInTheDocument(); expect(document.querySelector('.ant-notification-bottomLeft')).toHaveStyle({ top: '', left: '0px', bottom: '50px', }); }); it('support className', () => { const { container } = render(
test
, ); expect(container.querySelector('.ant-app')).toHaveClass('test-class'); }); it('support style', () => { const { container } = render(
test
, ); expect(container.querySelector('.ant-app')).toHaveStyle('color: blue;'); }); // https://github.com/ant-design/ant-design/issues/41197#issuecomment-1465803061 describe('restIcon style', () => { beforeEach(() => { Array.from(document.querySelectorAll('style')).forEach((style) => { style.parentNode?.removeChild(style); }); }); it('should work by default', () => { const { container } = render( , ); expect(container.querySelector('.anticon')).toBeTruthy(); const dynamicStyles = Array.from(document.querySelectorAll('style[data-css-hash]')); expect( dynamicStyles.some((style) => { const { innerHTML } = style; return innerHTML.startsWith('.anticon'); }), ).toBeTruthy(); }); }); describe('component', () => { it('replace', () => { const { container } = render(

, ); expect(container.querySelector('section.ant-app')).toBeTruthy(); }); it('to false', () => { const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const { container } = render(

, ); expect(warnSpy).not.toHaveBeenCalled(); expect(container.querySelector('.ant-app')).toBeFalsy(); warnSpy.mockRestore(); }); }); });