自动完成的单元测试 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[]。然后你不带参数调用renderTagsvalue就是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'],{})