自动完成的单元测试 renderTags 道具
Unit test renderTags prop of Autocomplete
我一直在尝试对 mui Autocomplete
组件的 renderTags
属性 进行单元测试。我创建了一个使用它的自定义组件。但我不知道如何对其进行单元测试。下面我将向您展示我到目前为止所做的尝试。
组件如下所示:
function ChipInput(props: Props): ReactElement {
const [field, meta, { setValue }] = useField<string[]>(props.name);
const errorText = (meta.touched && meta.error) || undefined;
const handleChange = useCallback((_, value) => setValue(value), [setValue]);
const renderTags = (value: string[], getTagProps) =>
value.map((option: string, index: number) => (
<Chip variant="outlined" label={option} {...getTagProps({ index })} />
));
const renderInput = params => (
<TextField
{...params}
variant="filled"
label={props.label}
error={errorText !== undefined}
helperText={errorText || props.helperText}
/>
);
return (
<Column column={props.column}>
<Autocomplete
id={`chipInput-${props.name}`}
multiple
options={[]}
value={field.value || []}
onChange={handleChange}
freeSolo
renderTags={renderTags}
renderInput={renderInput}
/>
</Column>
);
}
这就是我目前尝试对其进行单元测试的方式。它适用于 renderInput
但不适用于 renderTags
:
describe('ChipInput', () => {
const useFieldMock = jest.spyOn(Formik, 'useField');
const flavours = mockUseField<unknown>(['salt', 'paprika']);
const props: ComponentProps<typeof ChipInput> = {
name: 'chipInput',
label: 'Chip input',
column: 1,
};
it('should render chips', () => {
jest.clearAllMocks();
useFieldMock.mockReturnValue(flavours);
const component = shallow(<ChipInput {...props} />);
const autocomplete = component.find(Autocomplete);
console.log(autocomplete.prop('value'));
const renderTags = autocomplete.prop('renderTags') as () => ReactElement;
const input = shallow(renderTags());
expect(input).toExist();
});
});
在控制台日志中,我可以看到打印了 [ 'salt', 'paprika' ]
,所以我知道该值已正确设置。但不知何故,在 shallow(renderTags())
它会抛出错误
TypeError: Cannot read property 'map' of undefined
,因为显然在 renderTags
中,value 参数仍然是空的。即使在控制台日志中看到,它已被设置。
任何人都可以指出我正确的方向吗?我觉得我一定是误会了什么。提前致谢!
问题是,当您使用 autocomplete.prop('renderTags')
时,它 returns 您在组件中定义的 renderTags
函数原样。而且它的类型不是() => ReactElement
而是(value: string[], getTagProps: Function) => ReactElement[]
。然后你不带参数调用renderTags
,value
就是undefined
,执行value.map(...)
的时候报错。要解决此问题,您需要传递一组正确的参数:
// I've made the second argument(getTagProps) return an empty object
// update with what you expect
const input = shallow(renderTags(['salt', 'paprika'], () => ({})));
一般来说,我建议将 renderTags
移出组件并使其可导出,这样就可以单独进行测试。这将使测试方式更容易(无需渲染整个组件)。
尝试通过像这样传递参数来调用它..
const component = shallow(<ChipInput {...props} />);
const autocomplete = component.find(Autocomplete);
autocomplete.at(0).prop('renderTags')(['salt', 'paprika'],{})
我一直在尝试对 mui Autocomplete
组件的 renderTags
属性 进行单元测试。我创建了一个使用它的自定义组件。但我不知道如何对其进行单元测试。下面我将向您展示我到目前为止所做的尝试。
组件如下所示:
function ChipInput(props: Props): ReactElement {
const [field, meta, { setValue }] = useField<string[]>(props.name);
const errorText = (meta.touched && meta.error) || undefined;
const handleChange = useCallback((_, value) => setValue(value), [setValue]);
const renderTags = (value: string[], getTagProps) =>
value.map((option: string, index: number) => (
<Chip variant="outlined" label={option} {...getTagProps({ index })} />
));
const renderInput = params => (
<TextField
{...params}
variant="filled"
label={props.label}
error={errorText !== undefined}
helperText={errorText || props.helperText}
/>
);
return (
<Column column={props.column}>
<Autocomplete
id={`chipInput-${props.name}`}
multiple
options={[]}
value={field.value || []}
onChange={handleChange}
freeSolo
renderTags={renderTags}
renderInput={renderInput}
/>
</Column>
);
}
这就是我目前尝试对其进行单元测试的方式。它适用于 renderInput
但不适用于 renderTags
:
describe('ChipInput', () => {
const useFieldMock = jest.spyOn(Formik, 'useField');
const flavours = mockUseField<unknown>(['salt', 'paprika']);
const props: ComponentProps<typeof ChipInput> = {
name: 'chipInput',
label: 'Chip input',
column: 1,
};
it('should render chips', () => {
jest.clearAllMocks();
useFieldMock.mockReturnValue(flavours);
const component = shallow(<ChipInput {...props} />);
const autocomplete = component.find(Autocomplete);
console.log(autocomplete.prop('value'));
const renderTags = autocomplete.prop('renderTags') as () => ReactElement;
const input = shallow(renderTags());
expect(input).toExist();
});
});
在控制台日志中,我可以看到打印了 [ 'salt', 'paprika' ]
,所以我知道该值已正确设置。但不知何故,在 shallow(renderTags())
它会抛出错误
TypeError: Cannot read property 'map' of undefined
,因为显然在 renderTags
中,value 参数仍然是空的。即使在控制台日志中看到,它已被设置。
任何人都可以指出我正确的方向吗?我觉得我一定是误会了什么。提前致谢!
问题是,当您使用 autocomplete.prop('renderTags')
时,它 returns 您在组件中定义的 renderTags
函数原样。而且它的类型不是() => ReactElement
而是(value: string[], getTagProps: Function) => ReactElement[]
。然后你不带参数调用renderTags
,value
就是undefined
,执行value.map(...)
的时候报错。要解决此问题,您需要传递一组正确的参数:
// I've made the second argument(getTagProps) return an empty object
// update with what you expect
const input = shallow(renderTags(['salt', 'paprika'], () => ({})));
一般来说,我建议将 renderTags
移出组件并使其可导出,这样就可以单独进行测试。这将使测试方式更容易(无需渲染整个组件)。
尝试通过像这样传递参数来调用它..
const component = shallow(<ChipInput {...props} />);
const autocomplete = component.find(Autocomplete);
autocomplete.at(0).prop('renderTags')(['salt', 'paprika'],{})