javascript - Hur man korrekt testar kontrollerad inmatningskomponent som beror på useState med jest/enzyme
Jag vill testa en kontrollerad komponent med Jest/enzyme.
Jag har en <Input>-komponent som, givet max och min-props, kommer att automatiskt fylla i värdet när change-händelsen utlöses
// 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>
)
}
Jag skulle vilja testa komponenten och dess olika change-användningsfall med jest.
Eftersom det är en helt kontrollerad komponent börjar jag skriva följande kod:
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
Men jag stöter på ett problem: value-egenskapen hos <Input> uppdateras aldrig eftersom jag aldrig använder React.setState. Mitt exempel är dumt och jag kanske inte behöver det, men i ett mer komplext verkligt scenario skulle jag vilja sätta upp ett tillstånd genom att utlösa händelser och sedan antingen testa mitt state-värde eller mitt onChangeSpy
Hur skulle jag kunna uppnå detta mål? Uppdatera tillståndet och kunna testa det?
Uppdatera
Jag hittade en lösning som fungerar för mig.
Den kombinerar useState och 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