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
我怎样才能实现这个目标?更新状态并能够测试它吗?
我找到了一个适合我的解决方法。
它结合了useState和jest.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)