开发者问题收集

jest 和 testing-library 控制输入

2022-09-12
1497

我正尝试在自定义输入组件中应用单元测试
如果我在 render 函数中的 <Input /> 中传递 value 属性,则测试失败。
有人知道原因吗?
在类似此输入的受控组件中,我们可以测试什么才能进行有效的单元测试?
谢谢

Input.tsx

import React, {ChangeEvent, FunctionComponent} from 'react';
import styles from './Input.module.css'

export interface InputProps {
    type?: string
    disabled?: boolean
    value?: string
    onChange?: (value: string) => void
}

const Input: FunctionComponent<InputProps> = ({
    type= 'text',
    disabled = false,
    value,
    onChange,
}) => {
    
    const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
        const value = e.currentTarget.value
        if (onChange) {
            onChange(value)
        }
    }
    
    return (
        <div className={styles.inputWrapper}>
            <input
                className={styles.input}
                type={type}
                disabled={disabled}
                value={value}
                onChange={handleOnChange}
            />
        </div>
    );
}

export default Input;

Input.test.tsx

// PASS WITHOUT ANY ERRORS
it('should has the new value', async () => {
    const user = userEvent.setup()
    const onChangeMock = jest.fn();
    const { getByRole } = render(<Input onChange={onChangeMock} />)
    const input = getByRole('textbox')
    expect(input).toHaveValue('')
    await user.type(input, 'new input value')
    expect(input).toHaveValue('new input value')
})
 
// FAILS
it('should has the new value', async () => {
    const user = userEvent.setup()
    const onChangeMock = jest.fn();
    const { getByRole } = render(<Input value="" onChange={onChangeMock} />)
    const input = getByRole('textbox')
    expect(input).toHaveValue('')
    await user.type(input, 'new input value')
    expect(input).toHaveValue('new input value')
})
1个回答

您可以使用从 render 返回的 rerender 函数。

通过此函数,您可以将新值发送到您的组件,输入具有新值,然后您可以在输入中对该值进行断言。

在您的情况下,您的测试还需要检查在执行 userEvent.type() 时是否调用了 onChange 方法,如果该方法不起作用,您可以使用 fireEvent.change(input...)

it('should has the new value', async () => {
  const user = userEvent.setup();
  const onChangeMock = jest.fn();
  const { getByRole, rerender } = render(<Input value="" onChange={onChangeMock} />);

  const input = getByRole('textbox');
  expect(input).toHaveValue('');

  rerender(<Input value="new input value" onChange={onChangeMock} />);

  expect(input).toHaveValue('new input value');
});
Mario Petrovic
2022-09-12