react-testing-library: Onchange event not being fired when using fireEvent.change

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

  • “jest”: “24.9.0”,
  • “jest-environment-jsdom-fourteen”: “^0.1.0”,
  • “jest-localstorage-mock”: “2.4.0”,
  • “jest-serializer-enzyme”: “1.0.0”,
  • “jest-skipped-reporter”: “0.0.4”,
  • “jest-trx-results-processor”: “0.2.0”,
  • “jest-watch-typeahead”: “0.3.0”,
  • @testing-library/react”: “^9.3.0”,
  • “react-hooks-testing-library”: “0.4.0”,
  • “ts-jest”: “24.1.0”,
  • “react”: “16.9”,
  • “react-dom”: “16.9”,
  • node version: v8.16.1
  • yarn “1.17.3”

What you did:

when 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.

Things I’ve tried

using “jest-environment-jsdom-fourteen”: “^0.1.0”, checking to make sure input fields have type set.

example test

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'));
    });

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 20 (9 by maintainers)

Most upvoted comments

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.

This is killing me

@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).

@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.

Ive had the same issue using function callback in setState. With object literal it works:

  // This doesnt work:
  this.setState((state) => ({
     value: e.target.value
  }));
  
  // This does:
  this.setState({value: e.target.value});

Simulate doesn’t fire events. Simulate is cheating, which is why we don’t use it.