Ant Design & React 测试库 - 使用 Select 的测试表单



我正试图在填充了initialValues的Ant设计表单中测试Select输入,但由于Select没有接收到值,因此测试失败。有没有最好的方法来测试;自定义";渲染选择?

测试输出:

Error: expect(element).toHaveValue(chocolate)
Expected the element to have value:
chocolate
Received:

示例测试:

import { render, screen } from '@testing-library/react';
import { Form, Select } from 'antd';
const customRender = (ui: React.ReactElement, options = {}) => render(ui, {
wrapper: ({ children }) => children,
...options,
});
describe('select tests', () => {
it('renders select', () => {
const options = [
{ label: 'Chocolate', value: 'chocolate' },
{ label: 'Strawberry', value: 'strawberry' },
{ label: 'Vanilla', value: 'vanilla' },
];
const { value } = options[0];
customRender(
<Form initialValues={{ formSelectItem: value }}>
<Form.Item label="Form Select Label" name="formSelectItem">
<Select options={options} />
</Form.Item>
</Form>,
);
expect(screen.getByLabelText('Form Select Label')).toHaveValue(value);
});
});

我模拟了一个正常的选择,并能够使一切正常工作。

下面的示例使用Vitest作为测试运行程序,但应用程序应与Jest类似。

antd-mock.tsx

import React from 'react';
import { vi } from 'vitest';
vi.mock('antd', async () => {
const antd = await vi.importActual('antd');
const Select = props => {
const [text, setText] = React.useState('');
const multiple = ['multiple', 'tags'].includes(props.mode);
const handleOnChange = e => props.onChange(
multiple
? Array.from(e.target.selectedOptions)
.map(option => option.value)
: e.target.value,
);
const handleKeyDown = e => {
if (e.key === 'Enter') {
props.onChange([text]);
setText('');
}
};
return (
<>
<select
// add value in custom attribute to handle async selector,
// where no option exists on load (need to type to fetch option)
className={props.className}
data-testid={props['data-testid']}
data-value={props.value || undefined}
defaultValue={props.defaultValue || undefined}
disabled={props.disabled || undefined}
id={props.id || undefined}
multiple={multiple || undefined}
onChange={handleOnChange}
value={props.value || undefined}
>
{props.children}
</select>
{props.mode === 'tags' && (
<input
data-testid={`${props['data-testid']}Input`}
onChange={e => setText(e.target.value)}
onKeyDown={handleKeyDown}
type="text"
value={text}
/>
)}
</>
);
};
Select.Option = ({ children, ...otherProps }) => (
<option {...otherProps}>{children}</option>
);
Select.OptGroup = ({ children, ...otherProps }) => (
<optgroup {...otherProps}>{children}</optgroup>
);
return { ...antd, Select };
});

utils.tsx

import { render } from '@testing-library/react';
import { ConfigProvider } from 'antd';
const customRender = (ui: React.ReactElement, options = {}) => render(ui, {
wrapper: ({ children }) => <ConfigProvider prefixCls="bingo">{children}</ConfigProvider>,
...options,
});
export * from '@testing-library/react';
export { default as userEvent } from '@testing-library/user-event';
export { customRender as render };

Select.test.tsx

import { Form } from 'antd';
import { render, screen, userEvent } from '../../../test/utils';
import Select from './Select';
const options = [
{ label: 'Chocolate', value: 'chocolate' },
{ label: 'Strawberry', value: 'strawberry' },
{ label: 'Vanilla', value: 'vanilla' },
];
const { value } = options[0];
const initialValues = { selectFormItem: value };
const renderSelect = () => render(
<Form initialValues={initialValues}>
<Form.Item label="Label" name="selectFormItem">
<Select options={options} />
</Form.Item>
</Form>,
);
describe('select tests', () => {
it('renders select', () => {
render(<Select options={options} />);
expect(screen.getByRole('combobox')).toBeInTheDocument();
});
it('renders select with initial values', () => {
renderSelect();
expect(screen.getByLabelText('Label')).toHaveValue(value);
});
it('handles select change', () => {
renderSelect();
expect(screen.getByLabelText('Label')).toHaveValue(value);
userEvent.selectOptions(screen.getByLabelText('Label'), 'vanilla');
expect(screen.getByLabelText('Label')).toHaveValue('vanilla');
});
});

测试库组件有时可能很困难,因为它隐藏了内部复杂性。对于测试antd-select,我建议模拟它,并在测试中使用正常的select,如下所示:

jest.mock('antd', () => {
const antd = jest.requireActual('antd');
const Select = ({ children, onChange, ...rest }) => {
return <select role='combobox' onChange={e => onChange(e.target.value)}>
{children}
</select>;
};
Select.Option = ({ children, ...otherProps }) => {
return <option role='option' {...otherProps}}>{children}</option>;
}
return {
...antd,
Select,
}
})

通过这种方式,您可以将select组件测试为正常的select(使用screen.debug检查antd select是否被模拟(

最新更新