I'm working on a test code for my React project. What I want to check is 'if the input type is number, it disallow the text insertion'. Below is the test code I wrote.
it("disallow a text input", () => {
const input = screen.getByLabelText(label0); // it has 0 as initial value
const dummyText = "imyourfather";
// typing a text won't change the value of input
userEvent.type(input, dummyText);
screen.debug();
expect(input).toHaveValue(0); // FAILED -> return null
});
What I've expected here is to get the initial value, 0
, as a result of toHaveValue
. But it actually returns null
.
You might think 'yes, you tried to insert a text to a number-typed input, that's why it returns null', but the funny thing is that debug()
and console.log(input.value)
return 0
as I expected.
<!-- the result of debug() -->
<div
class="ui input"
>
<input
id="form-field-number01"
required=""
type="number"
value="0"
/>
</div>
And also if you manually try to insert a text value to a number-typed input on browser, it actually shows the initial value, 0. Anyone knows why toHaveValue
and debug
are showing different results?
After some digging, it appears this is indeed an expected behaviour of toHaveValue
in case of <input type="number">
.
First of all, the input value when you enter a string (in case of type="number"
) is actually an empty string:
The value sanitization algorithm is as follows: If the value of the element is not a valid floating-point number, then set it to the empty string instead.
While screen.debug()
will output the DOM tree, you can check the actual value
property by logging it after your dummy text has been typed:
userEvent.type(input, dummyText);
console.log('--> Value: ', input.value);
console.log('--> Value type: ', typeof input.value);
Now, the function used by jest-dom to get the input value looks like this:
function getInputValue(inputElement) {
switch (inputElement.type) {
case 'number':
return inputElement.value === '' ? null : Number(inputElement.value)
case 'checkbox':
return inputElement.checked
default:
return inputElement.value
}
}
As you can see, in case of type="number"
an empty string gets resolved to null
. Not sure what's the reason behind this.
As for your specific case you could test the input element to not have your dummy text as a value or to have an empty displayed value:
expect(input).not.toHaveValue(dummyText);
expect(input).toHaveDisplayValue("");