Skip to content

Commit

Permalink
fix: react 18 test fixing (ant-design#34787)
Browse files Browse the repository at this point in the history
* fix: try fix

* chore: ci

* test: recover

* test: more test case

* test: more and mote

* test: btn test

* fix: react 18 compitable

* chore: more test

* test: all confirm test

* chore: tmp

* chore: test lib

* chore: tmp

* chore: tmp

* test: back of part

* test: back of menu index test

* test: more test

* test: form test

* test: rm IE11 test case

* chore: fix compatible

* chore: clean up

* chore: back of all test case

* test: ignore 18 lines

* chore: remove render test of enzyme in upload

* test: back of IE11 test case to fit 100% coverage

* chore: fix pkg deps
  • Loading branch information
zombieJ authored Apr 6, 2022
1 parent 08e962d commit a67c0d2
Show file tree
Hide file tree
Showing 28 changed files with 825 additions and 496 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,7 @@ jobs:
name: test
strategy:
matrix:
react: ['16', '17']
# react: ['17', '18']
react: ['16', '17', '18']
module: ['dom', 'node', 'dist']
env:
REACT: ${{ matrix.react }}
Expand Down Expand Up @@ -349,8 +348,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
react: ['16', '17']
# react: ['17', '18']
react: ['16', '17', '18']
module: [lib, es]
env:
REACT: ${{ matrix.react }}
Expand Down
50 changes: 50 additions & 0 deletions components/_util/compatible.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable import/prefer-default-export */
import * as React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import type { Root } from 'react-dom/client';
// import * as reactDomClient from 'react-dom/client';

let createRoot: (container: ContainerType) => Root;
try {
// eslint-disable-next-line global-require, import/no-unresolved
createRoot = require('react-dom/client').createRoot;
} catch (e) {
// Do nothing;
}

const MARK = '__antd_react_root__';

type ContainerType = (Element | DocumentFragment) & {
[MARK]?: Root;
};

export function reactRender(node: React.ReactElement, container: ContainerType) {
// React 17 test will not reach here
/* istanbul ignore next */
if (createRoot !== undefined) {
const root = container[MARK] || createRoot(container);
root.render(node);

container[MARK] = root;
return;
}

render(node, container);
}

export function reactUnmount(container: ContainerType) {
// React 17 test will not reach here
/* istanbul ignore next */
if (createRoot !== undefined) {
// Delay to unmount to avoid React 18 sync warning
Promise.resolve().then(() => {
container[MARK]?.unmount();

delete container[MARK];
});

return;
}

unmountComponentAtNode(container);
}
7 changes: 5 additions & 2 deletions components/avatar/__tests__/Avatar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import Avatar from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
Expand Down Expand Up @@ -144,9 +146,10 @@ describe('Avatar Render', () => {

it('should warning when pass a string as icon props', () => {
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(<Avatar size={64} icon="aa" />);
render(<Avatar size={64} icon="aa" />);
expect(warnSpy).not.toHaveBeenCalled();
mount(<Avatar size={64} icon="user" />);

render(<Avatar size={64} icon="user" />);
expect(warnSpy).toHaveBeenCalledWith(
`Warning: [antd: Avatar] \`icon\` is using ReactNode instead of string naming in v4. Please check \`user\` at https://ant.design/components/icon`,
);
Expand Down
38 changes: 20 additions & 18 deletions components/breadcrumb/__tests__/Breadcrumb.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import { mount, render } from 'enzyme';
import { mount } from 'enzyme';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import Breadcrumb from '../index';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
Expand All @@ -21,7 +23,7 @@ describe('Breadcrumb', () => {
// https://github.com/airbnb/enzyme/issues/875
it('warns on non-Breadcrumb.Item and non-Breadcrumb.Separator children', () => {
const MyCom = () => <div>foo</div>;
mount(
render(
<Breadcrumb>
<MyCom />
</Breadcrumb>,
Expand All @@ -34,32 +36,32 @@ describe('Breadcrumb', () => {

// https://github.com/ant-design/ant-design/issues/5015
it('should allow Breadcrumb.Item is null or undefined', () => {
const wrapper = render(
const { asFragment } = render(
<Breadcrumb>
{null}
<Breadcrumb.Item>Home</Breadcrumb.Item>
{undefined}
</Breadcrumb>,
);
expect(errorSpy).not.toHaveBeenCalled();
expect(wrapper).toMatchSnapshot();
expect(asFragment().firstChild).toMatchSnapshot();
});

// https://github.com/ant-design/ant-design/issues/5542
it('should not display Breadcrumb Item when its children is falsy', () => {
const wrapper = render(
const wrapper = mount(
<Breadcrumb>
<Breadcrumb.Item />
<Breadcrumb.Item>xxx</Breadcrumb.Item>
<Breadcrumb.Item>yyy</Breadcrumb.Item>
</Breadcrumb>,
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});

// https://github.com/ant-design/ant-design/issues/18260
it('filter React.Fragment', () => {
const wrapper = render(
const wrapper = mount(
<Breadcrumb separator="">
<Breadcrumb.Item>Location</Breadcrumb.Item>
<Breadcrumb.Separator>:</Breadcrumb.Separator>
Expand All @@ -69,7 +71,7 @@ describe('Breadcrumb', () => {
</>
</Breadcrumb>,
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});

it('should render a menu', () => {
Expand Down Expand Up @@ -104,27 +106,27 @@ describe('Breadcrumb', () => {
path: 'third',
},
];
const wrapper = render(<Breadcrumb routes={routes} />);
expect(wrapper).toMatchSnapshot();
const wrapper = mount(<Breadcrumb routes={routes} />);
expect(wrapper.render()).toMatchSnapshot();
});

it('should accept undefined routes', () => {
const wrapper = render(<Breadcrumb routes={undefined} />);
expect(wrapper).toMatchSnapshot();
const wrapper = mount(<Breadcrumb routes={undefined} />);
expect(wrapper.render()).toMatchSnapshot();
});

it('should support custom attribute', () => {
const wrapper = render(
const wrapper = mount(
<Breadcrumb data-custom="custom">
<Breadcrumb.Item data-custom="custom-item">xxx</Breadcrumb.Item>
<Breadcrumb.Item>yyy</Breadcrumb.Item>
</Breadcrumb>,
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});

it('should support React.Fragment and falsy children', () => {
const wrapper = render(
const wrapper = mount(
<Breadcrumb>
<>
<Breadcrumb.Item>yyy</Breadcrumb.Item>
Expand All @@ -136,7 +138,7 @@ describe('Breadcrumb', () => {
{undefined}
</Breadcrumb>,
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});

// https://github.com/ant-design/ant-design/issues/25975
Expand All @@ -146,13 +148,13 @@ describe('Breadcrumb', () => {
<Breadcrumb.Item>Mock Node</Breadcrumb.Item>
</span>
);
const wrapper = render(
const wrapper = mount(
<Breadcrumb>
<Breadcrumb.Item>Location</Breadcrumb.Item>
<MockComponent />
<Breadcrumb.Item>Application Center</Breadcrumb.Item>
</Breadcrumb>,
);
expect(wrapper).toMatchSnapshot();
expect(wrapper.render()).toMatchSnapshot();
});
});
27 changes: 17 additions & 10 deletions components/button/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { Component } from 'react';
import { mount, render } from 'enzyme';
import { mount } from 'enzyme';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import { act } from 'react-dom/test-utils';
import { SearchOutlined } from '@ant-design/icons';
import { resetWarned } from 'rc-util/lib/warning';
Expand Down Expand Up @@ -39,7 +41,7 @@ describe('Button', () => {
const mockWarn = jest.fn();
jest.spyOn(console, 'warn').mockImplementation(mockWarn);
const size = 'who am I' as any as SizeType;
render(<Button.Group size={size} />);
mount(<Button.Group size={size} />);
expect(mockWarn).toHaveBeenCalledTimes(1);
expect(mockWarn.mock.calls[0][0]).toMatchObject({
message: 'unreachable case: "who am I"',
Expand All @@ -51,12 +53,14 @@ describe('Button', () => {
// should not insert space when there is icon
expect(mount(<Button icon={<SearchOutlined />}>按钮</Button>).render()).toMatchSnapshot();
// should not insert space when there is icon
expect(mount(
<Button>
<SearchOutlined />
按钮
</Button>,
).render()).toMatchSnapshot();
expect(
mount(
<Button>
<SearchOutlined />
按钮
</Button>,
).render(),
).toMatchSnapshot();
// should not insert space when there is icon
expect(mount(<Button icon={<SearchOutlined />}>按钮</Button>).render()).toMatchSnapshot();
// should not insert space when there is icon while loading
Expand Down Expand Up @@ -261,12 +265,15 @@ describe('Button', () => {
it('should warning when pass a string as icon props', () => {
resetWarned();
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(<Button type="primary" icon="ab" />);

render(<Button type="primary" icon="ab" />);
expect(warnSpy).not.toHaveBeenCalled();
mount(<Button type="primary" icon="search" />);

render(<Button type="primary" icon="search" />);
expect(warnSpy).toHaveBeenCalledWith(
`Warning: [antd: Button] \`icon\` is using ReactNode instead of string naming in v4. Please check \`search\` at https://ant.design/components/icon`,
);

warnSpy.mockRestore();
});

Expand Down
22 changes: 12 additions & 10 deletions components/config-provider/__tests__/form.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import { act } from 'react-dom/test-utils';
import ConfigProvider from '..';
import zhCN from '../../locale/zh_CN';
Expand All @@ -15,10 +17,10 @@ describe('ConfigProvider.Form', () => {
});

describe('form validateMessages', () => {
const wrapperComponent = ({ validateMessages }) => {
const renderComponent = ({ validateMessages }) => {
const formRef = React.createRef();

const wrapper = mount(
const { container } = render(
<ConfigProvider locale={zhCN} form={{ validateMessages }}>
<Form ref={formRef} initialValues={{ age: 18 }}>
<Form.Item name="test" label="姓名" rules={[{ required: true }]}>
Expand All @@ -31,11 +33,11 @@ describe('ConfigProvider.Form', () => {
</ConfigProvider>,
);

return [wrapper, formRef];
return [container, formRef];
};

it('set locale zhCN', async () => {
const [wrapper, formRef] = wrapperComponent({});
const [container, formRef] = renderComponent({});

await act(async () => {
try {
Expand All @@ -47,15 +49,14 @@ describe('ConfigProvider.Form', () => {

await act(async () => {
jest.runAllTimers();
wrapper.update();
await Promise.resolve();
});

expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual('请输入姓名');
expect(container.querySelector('.ant-form-item-explain')).toHaveTextContent('请输入姓名');
});

it('set locale zhCN and set form validateMessages one item, other use default message', async () => {
const [wrapper, formRef] = wrapperComponent({ validateMessages: { required: '必须' } });
const [container, formRef] = renderComponent({ validateMessages: { required: '必须' } });

await act(async () => {
try {
Expand All @@ -67,12 +68,13 @@ describe('ConfigProvider.Form', () => {

await act(async () => {
jest.runAllTimers();
wrapper.update();
await Promise.resolve();
});

expect(wrapper.find('.ant-form-item-explain').first().text()).toEqual('必须');
expect(wrapper.find('.ant-form-item-explain').last().text()).toEqual('年龄必须等于17');
const explains = Array.from(container.querySelectorAll('.ant-form-item-explain'));

expect(explains[0]).toHaveTextContent('必须');
expect(explains[explains.length - 1]).toHaveTextContent('年龄必须等于17');
});
});

Expand Down
Loading

0 comments on commit a67c0d2

Please sign in to comment.