如何使用 jest/enzyme 正确测试依赖于 useState 的受控输入组件

Sim*_*aud 7 javascript typescript reactjs jestjs enzyme

我想使用 Jest/enzyme 测试受控组件。

我有一个<Input>给定的组件max,并且props 会在触发事件min时自动完成该值change

// Input.tsx
const Input = ({value, onChange, max, min}) => {

  const handleChange = (evt) => {
    const newValue = Number(evt.target.value)

    if(min !== undefined && newValue < min) {
      onChange(min)
      return 
    }

    if(max !== undefined && newValue > max) {
      onChange(max)
      return
    }

    onChange(newValue)
  }

  return (
    <div>
      <label>My input</label>
      <input type="number" value={value} onChange={handleChange} />
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

我想用玩笑来测试该组件及其不同的change用例。
因为它是一个完全受控的组件,所以我开始编写以下代码:

    const onChangeSpy = jest.fn()
    const Wrapper = () => {
      const [state] = React.useState(0)
      return (
        <Input
          value={state}
          onChange={onChangeSpy}
          min={0}
          max={50}
        />
      )
    }

    const wrapper = mount(<Wrapper />)
    wrapper
      .find('input')
      .simulate('change', { target: { value: 25 } })
      .simulate('change', { target: { value: 115 } })
    expect(onChangeSpy.mock.calls).toHaveLength(2) // pass
Run Code Online (Sandbox Code Playgroud)

但我遇到了一个问题: 的valueprop<Input>永远不会更新,因为我从不使用 React.setState。我的例子很愚蠢,我可能不需要它,但在更复杂的现实世界场景中,我想通过触发事件来设置一些状态,然后测试我的state值或我的值onChangeSpy

我怎样才能实现这个目标?更新状态并能够测试它吗?

更新

我找到了一个适合我的解决方法。
它结合了useStatejest.fn()

    const onChangeSpy = jest.fn()
    const Wrapper = () => {
      const [state, setState] = React.useState(0)
      return (
        <Input
          value={state}
          // Call both spy and setState (not clean but working)
          onChange={(val) => {
            onChangeSpy(val)
            setState(val)
          }}
          min={0}
          max={50}
        />
      )
    }

    const wrapper = mount(<Wrapper />)
    wrapper
      .find('input')
      .simulate('change', { target: { value: 25 } })
      .simulate('change', { target: { value: 115 } })
    expect(onChangeSpy.mock.calls).toHaveLength(2) // pass
    expect(wrapper.find('input').props().value).toEqual('115') // pass

Run Code Online (Sandbox Code Playgroud)