You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
6.4 KiB
244 lines
6.4 KiB
import React from 'react';
|
|
import { mount } from 'enzyme';
|
|
import raf from 'raf';
|
|
import { act } from 'react-dom/test-utils';
|
|
import Form from '..';
|
|
import Input from '../../input';
|
|
import Button from '../../button';
|
|
import { sleep } from '../../../tests/utils';
|
|
|
|
jest.mock('raf');
|
|
|
|
describe('Form.List', () => {
|
|
raf.mockImplementation(callback => window.setTimeout(callback));
|
|
|
|
afterAll(() => {
|
|
raf.mockRestore();
|
|
});
|
|
|
|
async function change(wrapper, index, value) {
|
|
wrapper.find(Input).at(index).simulate('change', { target: { value } });
|
|
await sleep();
|
|
wrapper.update();
|
|
}
|
|
|
|
function testList(name, renderField) {
|
|
it(name, async () => {
|
|
jest.useFakeTimers();
|
|
|
|
const wrapper = mount(
|
|
<Form>
|
|
<Form.List name="list">
|
|
{(fields, { add, remove }) => (
|
|
<>
|
|
{fields.map(field => renderField(field))}
|
|
<Button className="add" onClick={add}>
|
|
Add
|
|
</Button>
|
|
<Button
|
|
className="remove-0"
|
|
onClick={() => {
|
|
remove(0);
|
|
}}
|
|
/>
|
|
<Button
|
|
className="remove-1"
|
|
onClick={() => {
|
|
remove(1);
|
|
}}
|
|
/>
|
|
</>
|
|
)}
|
|
</Form.List>
|
|
</Form>,
|
|
);
|
|
|
|
function operate(className) {
|
|
act(() => {
|
|
wrapper.find(className).last().simulate('click');
|
|
jest.runAllTimers();
|
|
});
|
|
wrapper.update();
|
|
}
|
|
|
|
operate('.add');
|
|
expect(wrapper.find(Input).length).toBe(1);
|
|
|
|
operate('.add');
|
|
expect(wrapper.find(Input).length).toBe(2);
|
|
|
|
operate('.add');
|
|
expect(wrapper.find(Input).length).toBe(3);
|
|
|
|
await change(wrapper, 2, '');
|
|
act(() => {
|
|
jest.runAllTimers();
|
|
});
|
|
wrapper.update();
|
|
expect(wrapper.find('.ant-form-item-explain div').length).toBe(1);
|
|
|
|
operate('.remove-0');
|
|
expect(wrapper.find(Input).length).toBe(2);
|
|
expect(wrapper.find('.ant-form-item-explain div').length).toBe(1);
|
|
|
|
operate('.remove-1');
|
|
expect(wrapper.find(Input).length).toBe(1);
|
|
expect(wrapper.find('.ant-form-item-explain div').length).toBe(0);
|
|
|
|
jest.useRealTimers();
|
|
});
|
|
}
|
|
|
|
testList('operation correctly', field => (
|
|
<Form.Item {...field} rules={[{ required: true }]}>
|
|
<Input />
|
|
</Form.Item>
|
|
));
|
|
|
|
testList('nest noStyle', field => (
|
|
<Form.Item key={field.key}>
|
|
<Form.Item noStyle {...field} rules={[{ required: true }]}>
|
|
<Input />
|
|
</Form.Item>
|
|
</Form.Item>
|
|
));
|
|
|
|
it('correct onFinish values', async () => {
|
|
async function click(wrapper, className) {
|
|
wrapper.find(className).last().simulate('click');
|
|
await sleep();
|
|
wrapper.update();
|
|
}
|
|
|
|
const onFinish = jest.fn().mockImplementation(() => {});
|
|
|
|
const wrapper = mount(
|
|
<Form
|
|
onFinish={v => {
|
|
if (typeof v.list[0] === 'object') {
|
|
/* old version led to SyntheticEvent be passed as an value here
|
|
that led to weird infinite loop somewhere and OutOfMemory crash */
|
|
v = new Error('We expect value to be a primitive here');
|
|
}
|
|
onFinish(v);
|
|
}}
|
|
>
|
|
<Form.List name="list">
|
|
{(fields, { add, remove }) => (
|
|
<>
|
|
{fields.map(field => (
|
|
// key is in a field
|
|
// eslint-disable-next-line react/jsx-key
|
|
<Form.Item {...field}>
|
|
<Input />
|
|
</Form.Item>
|
|
))}
|
|
<Button className="add" onClick={add}>
|
|
Add
|
|
</Button>
|
|
<Button className="remove" onClick={() => remove(0)}>
|
|
Remove
|
|
</Button>
|
|
</>
|
|
)}
|
|
</Form.List>
|
|
</Form>,
|
|
);
|
|
|
|
await click(wrapper, '.add');
|
|
await change(wrapper, 0, 'input1');
|
|
wrapper.find('form').simulate('submit');
|
|
await sleep();
|
|
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input1'] });
|
|
|
|
await click(wrapper, '.add');
|
|
await change(wrapper, 1, 'input2');
|
|
await click(wrapper, '.add');
|
|
await change(wrapper, 2, 'input3');
|
|
wrapper.find('form').simulate('submit');
|
|
await sleep();
|
|
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input1', 'input2', 'input3'] });
|
|
|
|
await click(wrapper, '.remove'); // will remove first input
|
|
wrapper.find('form').simulate('submit');
|
|
await sleep();
|
|
expect(onFinish).toHaveBeenLastCalledWith({ list: ['input2', 'input3'] });
|
|
});
|
|
|
|
it('list errors', async () => {
|
|
jest.useFakeTimers();
|
|
|
|
let operation;
|
|
const wrapper = mount(
|
|
<Form>
|
|
<Form.List
|
|
name="list"
|
|
rules={[
|
|
{
|
|
validator: async (_, value) => {
|
|
if (value.length < 2) {
|
|
return Promise.reject(new Error('At least 2'));
|
|
}
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
{(_, opt, { errors }) => {
|
|
operation = opt;
|
|
return <Form.ErrorList errors={errors} />;
|
|
}}
|
|
</Form.List>
|
|
</Form>,
|
|
);
|
|
|
|
async function addItem() {
|
|
await act(async () => {
|
|
operation.add();
|
|
await sleep(100);
|
|
jest.runAllTimers();
|
|
wrapper.update();
|
|
});
|
|
}
|
|
|
|
await addItem();
|
|
expect(wrapper.find('.ant-form-item-explain div').text()).toEqual('At least 2');
|
|
|
|
await addItem();
|
|
expect(wrapper.find('.ant-form-item-explain div')).toHaveLength(0);
|
|
|
|
jest.useRealTimers();
|
|
});
|
|
|
|
describe('ErrorList component', () => {
|
|
it('should trigger onDomErrorVisibleChange by motion end', async () => {
|
|
jest.useFakeTimers();
|
|
|
|
const onDomErrorVisibleChange = jest.fn();
|
|
const wrapper = mount(
|
|
<Form.ErrorList
|
|
errors={['bamboo is light']}
|
|
onDomErrorVisibleChange={onDomErrorVisibleChange}
|
|
/>,
|
|
);
|
|
|
|
await act(async () => {
|
|
await sleep();
|
|
jest.runAllTimers();
|
|
wrapper.update();
|
|
});
|
|
|
|
act(() => {
|
|
wrapper.find('CSSMotion').props().onLeaveEnd();
|
|
});
|
|
|
|
expect(onDomErrorVisibleChange).toHaveBeenCalledWith(false);
|
|
|
|
jest.useRealTimers();
|
|
});
|
|
});
|
|
|
|
it('should render empty without errors', () => {
|
|
const wrapper = mount(<Form.ErrorList />);
|
|
expect(wrapper.render()).toMatchSnapshot();
|
|
});
|
|
});
|
|
|