When trying to use fireEvent.change on an input The onChange event isn't triggered. I am seeing the onBlur event is triggered for fireEvent.blur
node version: v8.16.1when I use fireEvent.change(input, {target: {value: 'bob'}}
OnChange isn't triggered
When I use fireEvent.blur(input)
Blur is triggered
When I use simulate for react-dom/test-utils it works.
using "jest-environment-jsdom-fourteen": "^0.1.0",
checking to make sure input fields have type set.
it.only('should map errors', async () => {
const { container, getByLabelText, getByText } = await renderWithState();
const routingNumber = getByLabelText('Routing number') as HTMLInputElement;
const accountNumber = getByLabelText('Account number') as HTMLInputElement;
const accountConfirm = getByLabelText('Confirm account number') as HTMLInputElement;
fireEvent.change(routingNumber, { target: { value: '110000000', name: EBankingFieldNames.routingNumber } });
fireEvent.change(accountNumber, { target: { value: '000444444440', name: EBankingFieldNames.accountNumber } });
fireEvent.change(accountConfirm, {
target: { value: '000444444440', name: EBankingFieldNames.accountNumberConfirm },
});
await waitForDomChange({ container });
fireEvent.click(getByText('Save'));
await waitForDomChange({ container });
expect(getByText('Please enter a valid routing number'));
});
Hi @jamesBennett,
I'm not sure whether it will make a difference, but I noticed that you're not adding await on your waitForDomChange calls there. Those are async so you'll need to await those.
We could help a lot more if you post a codesandbox reproduction of this.
Hi @jamesBennett,
I'm not sure whether it will make a difference, but I noticed that you're not adding
awaiton yourwaitForDomChangecalls there. Those are async so you'll need toawaitthose.
Yeah doesn't change anything. Even if I had the await the onChange should be called before hitting the waitForDomChange
We could help a lot more if you post a codesandbox reproduction of this.
My app is really large. That seems like it would take a significant amount of time. Also, I have enzyme in here as well. Could that be anything?
I doubt that enzyme is causing a problem. Without a reproduction of the problem it's impossible for us to help because this works for everyone else.
@kentcdodds So the problem is that if you don't set the type or the type is invalid for an input it will not trigger an onChange.
Although this is definitely my error it seems odd that onBlur would still work. Is this a known bug? Seems like the query functions should throw an error on this.
if you don't set the type or the type is invalid for an input it will not trigger an onChange.
I think there's something else about your set up because this test passes:
import React from 'react'
import {render, fireEvent} from '@testing-library/react'
test('calls change handler for an input', () => {
const handleChange = jest.fn()
const {container} = render(<input onChange={handleChange} />)
const input = container.firstChild
fireEvent.change(input, {target: {value: 'a'}})
expect(handleChange).toHaveBeenCalledTimes(1)
})
This is why having a reproduction is a great deal of help.
I think there's something else about your set up because this test passes:
But this version fails.
import React from 'react'
import {render, fireEvent} from '@testing-library/react'
test('calls change handler for an input', () => {
const handleChange = jest.fn()
const {container} = render(
<input onChange={handleChange} type="invalidType" />,
)
const input = container.firstChild
fireEvent.change(input, {target: {value: 'a'}})
expect(handleChange).toHaveBeenCalledTimes(1)
})
notice the type
Yeah, that's a bug. I'm not sure what the problem is here and it will need some investigation. I wonder whether it's a limitation for jsdom.
Anyone's invited to do some investigation as to why an onChange handler is working when rendering it to the app, but not in the test. Here's a codesandbox example of this issue:
https://codesandbox.io/s/rtl-change-handler-with-invalid-type-yipu3
it's a limitation for jsdom.
@kentcdodds I don't think so because it works fine with reacts simulate.change
https://codesandbox.io/s/rtl-calls-change-handler-pfnks?fontsize=14&hidenavigation=1&theme=dark
Simulate doesn't fire events. Simulate is cheating, which is why we don't use it.
I did some digging into this and it looks like the root cause is JSDOM not defaulting invalid input types to "text" as per the spec:
The missing value default and the invalid value default are the Text state.
I tracked it down to React only creating change events when the input has a valid type:
https://github.com/facebook/react/blob/ab1a4f249e61045d523ddbbfb840e868afbbf785/packages/react-dom/src/events/ChangeEventPlugin.js#L275
https://github.com/facebook/react/blob/ab1a4f249e61045d523ddbbfb840e868afbbf785/packages/shared/isTextInputElement.js#L13-L29
I've opened a PR with JSDOM that should address the issue, however I think Jest is using JSDOM 14 so it might be some time for this change to filter through the right packages.
Super! Thank you for doing that! Glad to get this taken care of 馃憤
Doesn't seem to be only for invalid types. The following doesnt work:
test('calls change handler for an input', () => {
const handleChange = jest.fn()
const { container } = render(<input type="radio" onChange={handleChange} />)
const input = container.firstChild
fireEvent.change(input, { target: { value: 'a' } })
expect(handleChange).toHaveBeenCalledTimes(1)
})
@RobertSigma, you can't change the value of a radio button to "a"... that doesn't make sense. For radio and checkboxes you "click" them.
@RobertSigma, you can't change the value of a radio button to "a"... that doesn't make sense. For radio and checkboxes you "click" them.
I'm starting to think we should add some warnings to fireEvent.change in dom-testing-library. It feels like we get a lot of reports that come down to wrong usage of fireEvent.change with certain input types (e.g. type="date" and non iso values).
Most helpful comment
I did some digging into this and it looks like the root cause is JSDOM not defaulting invalid input types to
"text"as per the spec:I tracked it down to React only creating
changeevents when the input has a validtype:https://github.com/facebook/react/blob/ab1a4f249e61045d523ddbbfb840e868afbbf785/packages/react-dom/src/events/ChangeEventPlugin.js#L275
https://github.com/facebook/react/blob/ab1a4f249e61045d523ddbbfb840e868afbbf785/packages/shared/isTextInputElement.js#L13-L29
I've opened a PR with JSDOM that should address the issue, however I think Jest is using JSDOM 14 so it might be some time for this change to filter through the right packages.