Closed edickins closed 3 weeks ago
It might be interesting to add that I got the test working using fireEvent instead.
so instead of:
await user.clear(chocolateInput);
await user.type(chocolateInput, '1');
I used:
fireEvent.change(chocolateInput, {target:{value:1}})
the difference being that fireEvent fires a single event whereas the purpose of UserEvent as I understand it is that it fires all of the events on the component that would be triggered if the element was in a webpage and a user clicked on it to enter text (onFocus, onChange, onBlue etc)
I also didn't make it clear that this example I have provided (which is from a course on using testing-library for TDD) was originally in JavaScript where UserEvent worked fine. I decided to re-do the course using TypeScript so I could get TDD experience for TypeScript and for whatever reason TypeScript is the main thing that has changed here. Everything else, the ContextProvider, the page and the test are all doing the same thing in the same way.
Reproduction example
https://codesandbox.io/p/devbox/2x7q82?file=%2Fsrc%2Fpages%2Fentry%2FScoopOption.tsx%3A25%2C25
Prerequisites
you can run all tests using 'npm test' in the console and you will see an error from the totalUpdate.test.tsx test file where the subTotal value does not match what is expected.
Expected behavior
when you run the tests you will see that it fails in totalsTest.test.tsx where the subTotal text content should be $2.00 after the userEvent.clear() and userEvent.type() functions have run.
The subtotal should include the text "$2.00" because the chocolate HTMLInput has had the text value updated by userEvent.type() and this change is handled, the value is read and passed to a Context, and the subtotal which is updated is tested.
Actual behavior
When the
ScoopOption.tsx
component (the one that the test is setting values in) has adefaultValue={0}
attribute on the HTMLInput, the subTotal text content is"$NaN"
because when theScoopOption.tsx
reads thee.target.value
in theonChange
handler for the input afteruserEvent.type()
has changed the value to "1".The HTMLInput has an empty string as a value when it should have a value of "1".
This value from the input is read in an
onChange
handler and is sent to the ContextProvider, which updates the state in the Context, and so in the test when the subtotal is asserted to be"$2,00"
it is in fact"$NaN"
.in other words,
userEvent.type()
is not putting a value of "1" into the HTMLInput it is leaving it as an empty string, and that value is sent to the Context and displayed as$NaN
. This only happens when the HTMLInput has adefaultValue={0}
attribute.You can make the test pass by commenting this line out in
ScoopTopping.tsx
User-event version
14.5.1
Environment
Testing Library framework:
JS framework:
I have provided a link to a codesandbox replication of this code including the tests
Test environment:
DOM implementation:
Additional context
I tried a number of things to change the code so that for example the ScoopOption input was a controlled component and instead of having a defaultValue attribute it had a value attribute that was held in state and set that way, it did not fix it.
All I can say is that it looks like it is something to do with what does/doesn't trigger a re-render in the ScoopOption component - the userEvent.clear() is definitely working - the input changes from a defaultValue of 0 to an empty string value. The userEvent.type() method seems not to enter the text and get the component re-rendering to accept that text change if the input has a defaultValue attribute.