如何测试使用 React 测试库选中的复选框?

ken*_*z90 5 unit-testing typescript reactjs react-testing-library

有人看到这里的问题吗?如果我在更改时将检查状态设置为有效。但我不想复制检查的状态数据并观察它的每一个道具的变化。

父组件获取最新的检查信息并将其置于自己的状态中,如果父组件 isChecked 更改,则 FormCheckBox isChecked 更改。我认为,它是异步工​​作的,当我到达测试代码的最新行时,父更新没有完成,所以我看到过时的 isChecked。

    export default function FormCheckBox(props: IFormCheckBoxProps) {
      const { onChange, label, isChecked, error, errorModelLabel = '' } = props
    
      const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        onChange(event.currentTarget.checked)
      }
    
      const errorMsg = getFormErrorMsg(error, errorModelLabel)
    
      return (
        <FormGroup
          as={Row}
          className={cx('mb-3', { 'is-invalid': errorMsg })}
          controlId="catalogDescription"
          data-testid="slvy-formcheckbox"
        >
          <FormLabel column className="d-flex align-items-center justify-content-end fw-bold" sm={2}>
            {label}
          </FormLabel>
          <Col className="d-flex align-items-center" sm={10}>
            <input
              checked={isChecked}
              className={cx('checkbox', { 'is-invalid': errorMsg })}
              type="checkbox"
              onChange={handleChange}
            />
            <Form.Control.Feedback type="invalid">{errorMsg}</Form.Control.Feedback>
          </Col>
        </FormGroup>
      )
    }


 it('checkbox must use fireEvent.click', async () => {
    const handleChange = jest.fn()
    props.isChecked = false
    props.onChange = handleChange

    const { container } = render(<FormCheckBox {...props} />)
    const checkbox = container.querySelectorAll("input[type='checkbox']")[0] as HTMLInputElement

    fireEvent.click(checkbox)
    expect(handleChange).toHaveBeenCalledTimes(1)
    
    expect(checkbox.checked).toBe(true)
  })
Run Code Online (Sandbox Code Playgroud)

sli*_*wp2 4

由于FormCheckBox是受控组件,因此 input\xe2\x80\x99s 值始终由 React 状态驱动。所以你需要一个包装组件来提供这种状态。在您的测试用例中,即使handleChange调用了模拟函数,我们也需要更新isChecked状态,以便FormCheckBox组件将以新状态重新渲染。

\n

例如

\n

index.tsx

\n
import React from \'react\';\n\nexport default function FormCheckBox({ onChange, isChecked }) {\n\n  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    onChange(event.currentTarget.checked);\n  };\n\n  return <input checked={isChecked} type="checkbox" onChange={handleChange} />;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

为了让事情变得简单。我删除了不相关的代码。

\n

index.test.tsx

\n
import { fireEvent, render } from \'@testing-library/react\';\nimport React, { useState } from \'react\';\nimport FormCheckBox from \'./\';\n\ndescribe(\'73184212\', () => {\n  test(\'should pass\', () => {\n    const Wrap = () => {\n      const [isChecked, setIsChecked] = useState(false);\n      return <FormCheckBox isChecked={isChecked} onChange={() => setIsChecked(!isChecked)} />;\n    };\n    const { container } = render(<Wrap />);\n    const checkbox = container.querySelectorAll("input[type=\'checkbox\']")[0] as HTMLInputElement;\n    fireEvent.click(checkbox);\n    expect(checkbox.checked).toBe(true);\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

测试结果:

\n
import React from \'react\';\n\nexport default function FormCheckBox({ onChange, isChecked }) {\n\n  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    onChange(event.currentTarget.checked);\n  };\n\n  return <input checked={isChecked} type="checkbox" onChange={handleChange} />;\n}\n
Run Code Online (Sandbox Code Playgroud)\n