import React, { Component } from 'react'; import { mount } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { SearchOutlined } from '@ant-design/icons'; import { resetWarned } from 'rc-util/lib/warning'; import Button from '..'; import ConfigProvider from '../../config-provider'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; import { sleep, render, fireEvent } from '../../../tests/utils'; import type { SizeType } from '../../config-provider/SizeContext'; describe('Button', () => { mountTest(Button); mountTest(() => ).render()).toMatchSnapshot(); }); it('mount correctly', () => { expect(() => mount()).not.toThrow(); }); it('warns if size is wrong', () => { resetWarned(); const mockWarn = jest.spyOn(console, 'error').mockImplementation(() => {}); const size = 'who am I' as any as SizeType; render(); expect(mockWarn).toHaveBeenCalledWith('Warning: [antd: Button.Group] Invalid prop `size`.'); mockWarn.mockRestore(); }); it('renders Chinese characters correctly', () => { expect(mount().render()).toMatchSnapshot(); // should not insert space when there is icon expect(mount().render()).toMatchSnapshot(); // should not insert space when there is icon expect( mount( , ).render(), ).toMatchSnapshot(); // should not insert space when there is icon expect(mount().render()).toMatchSnapshot(); // should not insert space when there is icon while loading expect( mount( , ).render(), ).toMatchSnapshot(); // should insert space while loading expect(mount().render()).toMatchSnapshot(); // should insert space while only one nested element expect( mount( , ).render(), ).toMatchSnapshot(); }); it('renders Chinese characters correctly in HOC', () => { const Text = ({ children }: { children: React.ReactNode }) => {children}; const { container, rerender } = render( , ); expect(container.querySelector('.ant-btn')).toHaveClass('ant-btn-two-chinese-chars'); rerender( , ); expect(container.querySelector('.ant-btn')).not.toHaveClass('ant-btn-two-chinese-chars'); rerender( , ); expect(container.querySelector('.ant-btn')).toHaveClass('ant-btn-two-chinese-chars'); }); // https://github.com/ant-design/ant-design/issues/18118 it('should not insert space to link or text button', () => { const wrapper1 = mount(); expect(wrapper1.text()).toBe('按钮'); const wrapper2 = mount(); expect(wrapper2.text()).toBe('按钮'); }); it('should render empty button without errors', () => { const wrapper = mount( , ); expect(wrapper.render()).toMatchSnapshot(); }); it('have static property for type detecting', () => { const wrapper = mount(); expect((wrapper.find(Button).type() as any).__ANT_BUTTON).toBe(true); }); it('should change loading state instantly by default', () => { class DefaultButton extends Component { state = { loading: false, }; enterLoading = () => { this.setState({ loading: true }); }; render() { const { loading } = this.state; return ( ); } } const wrapper = mount(); wrapper.simulate('click'); expect(wrapper.find('.ant-btn-loading').length).toBe(1); }); it('should change loading state with delay', () => { class DefaultButton extends Component { state = { loading: false, }; enterLoading = () => { this.setState({ loading: { delay: 1000 } }); }; render() { const { loading } = this.state; return ( ); } } const wrapper = mount(); wrapper.simulate('click'); expect(wrapper.hasClass('ant-btn-loading')).toBe(false); }); it('reset when loading back of delay', () => { jest.useFakeTimers(); const wrapper = mount(, ); fireEvent.click(container.firstChild!); expect(onClick).not.toHaveBeenCalledWith(); }); it('should support link button', () => { const wrapper = mount( , ); expect(wrapper.render()).toMatchSnapshot(); }); it('fixbug renders {0} , 0 and {false}', () => { expect(mount().render()).toMatchSnapshot(); expect(mount().render()).toMatchSnapshot(); expect(mount().render()).toMatchSnapshot(); }); it('should not render as link button when href is undefined', async () => { const wrapper = mount( , ); expect(wrapper.render()).toMatchSnapshot(); }); // https://github.com/ant-design/ant-design/issues/15342 it('should merge text if children using variable', () => { const wrapper = mount( , ); expect(wrapper.render()).toMatchSnapshot(); }); it('should support to change loading', async () => { const wrapper = mount(); wrapper.setProps({ loading: true }); wrapper.update(); expect(wrapper.find('.ant-btn-loading').length).toBe(1); wrapper.setProps({ loading: false }); wrapper.update(); expect(wrapper.find('.ant-btn-loading').length).toBe(0); wrapper.setProps({ loading: { delay: 50 } }); wrapper.update(); expect(wrapper.find('.ant-btn-loading').length).toBe(0); await sleep(50); wrapper.update(); expect(wrapper.find('.ant-btn-loading').length).toBe(1); wrapper.setProps({ loading: false }); await sleep(50); wrapper.update(); expect(wrapper.find('.ant-btn-loading').length).toBe(0); expect(() => { wrapper.unmount(); }).not.toThrow(); }); it('should warning when pass a string as icon props', () => { resetWarned(); const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); render( , ); const btn = wrapper.find('button').instance(); Object.defineProperty(btn, 'textContent', { get() { throw new Error('Should not called!!!'); }, }); }); it('should not redirect when button is disabled', () => { const onClick = jest.fn(); const { container } = render( , ); fireEvent.click(container.firstChild!); expect(onClick).not.toHaveBeenCalled(); }); // https://github.com/ant-design/ant-design/issues/30953 it('should handle fragment as children', () => { const wrapper = mount( , ); expect(wrapper.render()).toMatchSnapshot(); }); });