🙂 I'm learning testing in React, but fireEvent doesn't change value on my input. Unfotunanently, I don't know why?
I'm rendering BuyPlace component. In this component I have form which has Input components (these components are simply label with input and I'm passing props to this compoments on form).
On screen.debug() I can see that my components is rendered corretly with this form and all of these inputs.
Also, my input is catched corretly in my test, I checked this.
This is my test:
test("should change input value", async () => {
render(
<HashRouter>
<UserContext.Provider value={{ user: true }}>
<BuyPlace />
</UserContext.Provider>
</HashRouter>
);
const nameInputEl = screen.getByPlaceholderText("Podaj własną nazwę");
fireEvent.change(nameInputEl, {
target: { value: "Michał" },
});
await waitFor(() => {
expect(nameInputEl.value).toBe("Michał");
});
});
Test is not passing. Ofcourse my app is working corretly, but on test it doesn't work.
This is handleInputChange on my component:
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => {
setInputValues((prevValues) => {
return {
...prevValues,
[e.target.name]: e.target.value,
}
});
};
Every solution which I found is not working... My value on input is always empty string. Can someone help me with this? I want to learn to write good tests, but I don't know where is the problem.
EDIT I saw something interesting on screen.debug().
My input on test is rendered without onchange attribute, this is normal on tests? Check this out:
<input
id="name"
name="name"
placeholder="Podaj własną nazwę"
type="text"
value=""
/>
On my rendered parent component I have handleInputChange and this function is passing to the Input components. On live everything is working but on test is not... Maybe this is why fireEvent is not working?
But why on test my input doesn't have onchange attribute?
EDIT 2 SOLUTION
Wow, after 3 days I found where the problem was!
The problem was in setState function which changes values. I had:
const myValues = (object with values);
setState((previousValues) => {
...previousValues,
[e.target.name]: e.target.value
})
But after changing on this:
setState({
...myValues,
[e.target.name]: e.target.value
})
My test is passing. So I can't use previousState callback on setState - this is why my test was incorrect. But... why? This is a question for me!
fireEvent.change
, doesfireEvent.input
work? – Conjunction