test: replace layout test case with test lib (#36323)

* test: replace layout test case with test lib

* test: fix react 18

* test: clean up

Co-authored-by: zombiej <smith3816@gmail.com>
This commit is contained in:
dingkang 2022-07-02 16:31:38 +08:00 committed by GitHub
parent 1d82f221b6
commit 40728fb4dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 109 additions and 75 deletions

View File

@ -3,7 +3,7 @@
exports[`Layout renders string width correctly 1`] = ` exports[`Layout renders string width correctly 1`] = `
<aside <aside
class="ant-layout-sider ant-layout-sider-dark" class="ant-layout-sider ant-layout-sider-dark"
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px" style="flex: 0 0 200px; max-width: 200px; min-width: 200px; width: 200px;"
> >
<div <div
class="ant-layout-sider-children" class="ant-layout-sider-children"

View File

@ -1,6 +1,6 @@
import { mount } from 'enzyme';
import React, { useState } from 'react'; import React, { useState } from 'react';
import Sider from '../Sider'; import Sider from '../Sider';
import { render, fireEvent } from '../../../tests/utils';
const Content = () => { const Content = () => {
const [breakpoint, setBreakpoint] = useState('sm'); const [breakpoint, setBreakpoint] = useState('sm');
@ -23,25 +23,27 @@ const Content = () => {
it('Dynamic breakpoint in Sider component', () => { it('Dynamic breakpoint in Sider component', () => {
const add = jest.fn(); const add = jest.fn();
const remove = jest.fn(); const remove = jest.fn();
jest.spyOn(window, 'matchMedia').mockReturnValue({ const newMatch = jest.spyOn(window, 'matchMedia').mockReturnValue({
matches: true, matches: true,
addEventListener: add, addEventListener: add,
removeEventListener: remove, removeEventListener: remove,
} as any); } as any);
const wrapper = mount(<Content />); const { container } = render(<Content />);
const newMatch = window.matchMedia as jest.Mock;
// Record here since React 18 strict mode will render twice at first mount
const originCallTimes = newMatch.mock.calls.length;
expect(originCallTimes <= 2).toBeTruthy();
// subscribe at first // subscribe at first
expect(newMatch.mock.calls.length).toBe(1); expect(add.mock.calls).toHaveLength(originCallTimes);
expect(add.mock.calls.length).toBe(1); expect(remove.mock.calls).toHaveLength(originCallTimes - 1);
expect(remove.mock.calls.length).toBe(0);
wrapper.find('#toggle').at(0).simulate('click'); fireEvent.click(container.querySelector('#toggle') as Element);
// unsubscribe then subscribe again
expect(newMatch.mock.calls.length).toBe(2); expect(newMatch.mock.calls).toHaveLength(originCallTimes + 1);
expect(add.mock.calls.length).toBe(2); expect(add.mock.calls).toHaveLength(originCallTimes + 1);
expect(remove.mock.calls.length).toBe(1); expect(remove.mock.calls).toHaveLength(originCallTimes);
jest.restoreAllMocks(); jest.restoreAllMocks();
}); });

View File

@ -1,10 +1,11 @@
import { mount, render } from 'enzyme';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { act } from 'react-dom/test-utils';
import Layout from '..'; import Layout from '..';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
import Icon from '../../icon'; import Icon from '../../icon';
import Menu from '../../menu'; import Menu from '../../menu';
import { fireEvent, render } from '../../../tests/utils';
const { Sider, Content, Footer, Header } = Layout; const { Sider, Content, Footer, Header } = Layout;
@ -24,14 +25,16 @@ describe('Layout', () => {
rtlTest(Sider); rtlTest(Sider);
it('detect the sider as children', () => { it('detect the sider as children', () => {
const wrapper = mount( const { container, unmount } = render(
<Layout> <Layout>
<Sider>Sider</Sider> <Sider>Sider</Sider>
<Content>Content</Content> <Content>Content</Content>
</Layout>, </Layout>,
); );
expect(wrapper.find('.ant-layout').hasClass('ant-layout-has-sider')).toBe(true); expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
wrapper.unmount(); true,
);
unmount();
}); });
it('umount from multiple siders', async () => { it('umount from multiple siders', async () => {
@ -53,16 +56,22 @@ describe('Layout', () => {
</Layout> </Layout>
); );
}; };
const wrapper = mount(<App />); const { container } = render(<App />);
expect(wrapper.find('.ant-layout').hasClass('ant-layout-has-sider')).toBe(true); expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
wrapper.find('button').at(0).simulate('click'); true,
expect(wrapper.find('.ant-layout').hasClass('ant-layout-has-sider')).toBe(true); );
wrapper.find('button').at(1).simulate('click'); fireEvent.click(container.querySelectorAll('button')[0]);
expect(wrapper.find('.ant-layout').hasClass('ant-layout-has-sider')).toBe(false); expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
true,
);
fireEvent.click(container.querySelectorAll('button')[1]);
expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
false,
);
}); });
it('detect the sider inside the children', async () => { it('detect the sider inside the children', async () => {
const wrapper = mount( const { container } = render(
<Layout> <Layout>
<div> <div>
<Sider>Sider</Sider> <Sider>Sider</Sider>
@ -70,11 +79,13 @@ describe('Layout', () => {
<Content>Content</Content> <Content>Content</Content>
</Layout>, </Layout>,
); );
expect(wrapper.find('.ant-layout').hasClass('ant-layout-has-sider')).toBe(true); expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
true,
);
}); });
it('detect ant-layout-sider-has-trigger class in sider when ant-layout-sider-trigger div tag exists', async () => { it('detect ant-layout-sider-has-trigger class in sider when ant-layout-sider-trigger div tag exists', async () => {
const wrapper = mount( const { container } = render(
<Layout> <Layout>
<div> <div>
<Sider collapsible>Sider</Sider> <Sider collapsible>Sider</Sider>
@ -82,11 +93,15 @@ describe('Layout', () => {
<Content>Content</Content> <Content>Content</Content>
</Layout>, </Layout>,
); );
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-has-trigger')).toBe(true); expect(
container
.querySelector('.ant-layout-sider')
.className.includes('ant-layout-sider-has-trigger'),
).toBe(true);
}); });
it('should have 50% width of sidebar', async () => { it('should have 50% width of sidebar', async () => {
const wrapper = mount( const { container } = render(
<Layout> <Layout>
<div> <div>
<Sider width="50%">Sider</Sider> <Sider width="50%">Sider</Sider>
@ -94,13 +109,13 @@ describe('Layout', () => {
<Content>Content</Content> <Content>Content</Content>
</Layout>, </Layout>,
); );
expect(wrapper.find('.ant-layout-sider').at(0).prop('style').width).toBe('50%'); expect(container.querySelector('.ant-layout-sider').style.width).toBe('50%');
expect(wrapper.find('.ant-layout-sider').at(0).prop('style').flex).toBe('0 0 50%'); expect(container.querySelector('.ant-layout-sider').style.flex).toBe('0 0 50%');
}); });
describe('zeroWidth', () => { describe('zeroWidth', () => {
it('detect ant-layout-sider-zero-width class in sider when its width is 0%', async () => { it('detect ant-layout-sider-zero-width class in sider when its width is 0%', async () => {
const wrapper = mount( const { container } = render(
<Layout> <Layout>
<div> <div>
<Sider width="0%">Sider</Sider> <Sider width="0%">Sider</Sider>
@ -108,14 +123,18 @@ describe('Layout', () => {
<Content>Content</Content> <Content>Content</Content>
</Layout>, </Layout>,
); );
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-zero-width')).toBe(true); expect(
container
.querySelector('.ant-layout-sider')
.className.includes('ant-layout-sider-zero-width'),
).toBe(true);
}); });
describe('should collapsible', () => { describe('should collapsible', () => {
it('uncontrolled', () => { it('uncontrolled', () => {
const onCollapse = jest.fn(); const onCollapse = jest.fn();
const wrapper = mount( const { container } = render(
<Layout> <Layout>
<Sider collapsible breakpoint="lg" collapsedWidth="0" onCollapse={onCollapse}> <Sider collapsible breakpoint="lg" collapsedWidth="0" onCollapse={onCollapse}>
Sider Sider
@ -125,8 +144,7 @@ describe('Layout', () => {
); );
onCollapse.mockReset(); onCollapse.mockReset();
fireEvent.click(container.querySelector('.ant-layout-sider-zero-width-trigger'));
wrapper.find('.ant-layout-sider-zero-width-trigger').simulate('click');
expect(onCollapse).toHaveBeenCalledTimes(1); expect(onCollapse).toHaveBeenCalledTimes(1);
}); });
@ -150,50 +168,54 @@ describe('Layout', () => {
); );
}; };
const wrapper = mount(<Demo />); const { container } = render(<Demo />);
expect(wrapper.find(Sider).prop('collapsed')).toBeTruthy(); expect(container.querySelector('.ant-layout-sider-collapsed')).toBeTruthy();
fireEvent.click(container.querySelector('.ant-layout-sider-zero-width-trigger'));
wrapper.find('.ant-layout-sider-zero-width-trigger').simulate('click'); expect(container.querySelector('.ant-layout-sider-collapsed')).toBeFalsy();
expect(wrapper.find(Sider).prop('collapsed')).toBeFalsy();
}); });
}); });
}); });
it('detect ant-layout-sider-dark as default theme', async () => { it('detect ant-layout-sider-dark as default theme', async () => {
const wrapper = mount(<Sider>Sider</Sider>); const { container } = render(<Sider>Sider</Sider>);
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-dark')).toBe(true); expect(
container.querySelector('.ant-layout-sider').className.includes('ant-layout-sider-dark'),
).toBe(true);
}); });
it('detect ant-layout-sider-light when set light theme', async () => { it('detect ant-layout-sider-light when set light theme', async () => {
const wrapper = mount(<Sider theme="light">Sider</Sider>); const { container } = render(<Sider theme="light">Sider</Sider>);
expect(wrapper.find('.ant-layout-sider').hasClass('ant-layout-sider-light')).toBe(true); expect(
container.querySelector('.ant-layout-sider').className.includes('ant-layout-sider-light'),
).toBe(true);
}); });
it('renders string width correctly', () => { it('renders string width correctly', () => {
const wrapper = render(<Sider width="200">Sider</Sider>); const { asFragment } = render(<Sider width="200">Sider</Sider>);
expect(wrapper).toMatchSnapshot(); expect(asFragment().firstChild).toMatchSnapshot();
}); });
it('should be controlled by collapsed', () => { it('should be controlled by collapsed', () => {
const wrapper = mount(<Sider>Sider</Sider>); const { asFragment, rerender } = render(<Sider>Sider</Sider>);
expect(wrapper.render()).toMatchSnapshot(); expect(asFragment().firstChild).toMatchSnapshot();
wrapper.setProps({ collapsed: true }); rerender(<Sider collapsed>Sider</Sider>);
wrapper.update(); expect(asFragment().firstChild).toMatchSnapshot();
expect(wrapper.render()).toMatchSnapshot();
}); });
it('should not add ant-layout-has-sider when `hasSider` is `false`', () => { it('should not add ant-layout-has-sider when `hasSider` is `false`', () => {
const wrapper = mount( const { container } = render(
<Layout hasSider={false}> <Layout hasSider={false}>
<Sider>Sider</Sider> <Sider>Sider</Sider>
</Layout>, </Layout>,
); );
expect(wrapper.find('.ant-layout').hasClass('ant-layout-has-sider')).toBe(false); expect(container.querySelector('.ant-layout').className.includes('ant-layout-has-sider')).toBe(
false,
);
}); });
it('render correct with Tooltip', () => { it('render correct with Tooltip', () => {
jest.useFakeTimers(); jest.useFakeTimers();
const wrapper = mount( const { container, rerender } = render(
<Sider collapsible collapsed={false}> <Sider collapsible collapsed={false}>
<Menu mode="inline"> <Menu mode="inline">
<Menu.Item key="1"> <Menu.Item key="1">
@ -204,19 +226,27 @@ describe('Layout', () => {
</Sider>, </Sider>,
); );
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter'); fireEvent.mouseEnter(container.querySelector('.ant-menu-item'));
jest.runAllTimers(); act(() => {
wrapper.update(); jest.runAllTimers();
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy(); });
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseout'); expect(container.querySelectorAll('.ant-tooltip-inner').length).toBeFalsy();
jest.runAllTimers();
wrapper.update();
wrapper.setProps({ collapsed: true }); rerender(
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter'); <Sider collapsible collapsed>
jest.runAllTimers(); <Menu mode="inline">
wrapper.update(); <Menu.Item key="1">
expect(wrapper.find('.ant-tooltip-inner').length).toBeTruthy(); <Icon type="user" />
<span>Light</span>
</Menu.Item>
</Menu>
</Sider>,
);
fireEvent.mouseEnter(container.querySelector('.ant-menu-item'));
act(() => {
jest.runAllTimers();
});
expect(container.querySelectorAll('.ant-tooltip-inner').length).toBeTruthy();
jest.useRealTimers(); jest.useRealTimers();
}); });
@ -236,7 +266,7 @@ describe('Sider', () => {
it('should trigger onBreakpoint', async () => { it('should trigger onBreakpoint', async () => {
const onBreakpoint = jest.fn(); const onBreakpoint = jest.fn();
mount( render(
<Sider breakpoint="md" onBreakpoint={onBreakpoint}> <Sider breakpoint="md" onBreakpoint={onBreakpoint}>
Sider Sider
</Sider>, </Sider>,
@ -245,7 +275,7 @@ describe('Sider', () => {
}); });
it('should warning if use `inlineCollapsed` with menu', () => { it('should warning if use `inlineCollapsed` with menu', () => {
mount( render(
<Sider collapsible> <Sider collapsible>
<Menu mode="inline" inlineCollapsed /> <Menu mode="inline" inlineCollapsed />
</Sider>, </Sider>,
@ -256,7 +286,7 @@ describe('Sider', () => {
}); });
it('zeroWidthTriggerStyle should work', () => { it('zeroWidthTriggerStyle should work', () => {
const wrapper = mount( const { container } = render(
<Sider collapsedWidth={0} collapsible zeroWidthTriggerStyle={{ background: '#F96' }}> <Sider collapsedWidth={0} collapsible zeroWidthTriggerStyle={{ background: '#F96' }}>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}> <Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1"> <Menu.Item key="1">
@ -266,13 +296,13 @@ describe('Sider', () => {
</Menu> </Menu>
</Sider>, </Sider>,
); );
expect(wrapper.find('.ant-layout-sider-zero-width-trigger').props().style).toEqual({ expect(
background: '#F96', container.querySelector('.ant-layout-sider-zero-width-trigger').style.background,
}); ).toEqual('rgb(255, 153, 102)');
}); });
it('should be able to customize zero width trigger by trigger prop', () => { it('should be able to customize zero width trigger by trigger prop', () => {
const wrapper = mount( const { container } = render(
<Sider collapsedWidth={0} collapsible trigger={<span className="my-trigger" />}> <Sider collapsedWidth={0} collapsible trigger={<span className="my-trigger" />}>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}> <Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1"> <Menu.Item key="1">
@ -282,7 +312,9 @@ describe('Sider', () => {
</Menu> </Menu>
</Sider>, </Sider>,
); );
expect(wrapper.find('.ant-layout-sider-zero-width-trigger').find('.my-trigger').length).toBe(1); expect(
container.querySelector('.ant-layout-sider-zero-width-trigger').querySelector('.my-trigger'),
).toBeTruthy();
}); });
['Layout', 'Header', 'Footer', 'Sider'].forEach(tag => { ['Layout', 'Header', 'Footer', 'Sider'].forEach(tag => {
@ -292,7 +324,7 @@ describe('Sider', () => {
const onSelect = jest.fn(); const onSelect = jest.fn();
const Component = ComponentMap[tag]; const Component = ComponentMap[tag];
mount( render(
<Component onSelect={onSelect} ref={ref}> <Component onSelect={onSelect} ref={ref}>
{tag} {tag}
</Component>, </Component>,