React-testing-library: Form Inputs not updating after change event is fired

Created on 3 Aug 2018  Â·  21Comments  Â·  Source: testing-library/react-testing-library

  • react-testing-library version: 4.1.5
  • react version: 16.4.1
  • node version: 8.6.0
  • npm (or yarn) version: 6.2.0

Relevant code or config:

test('submits form successfully', async () => {

const { getByText, queryByText, getByLabelText, debug } = renderWithRouter(
<SignIn setCurrentUser={jest.fn()} isSignedIn={false} history={{}} />
);

const submitButton = getByText('Sign In');
const emailInput = getByLabelText('Email');
const passwordInput = getByLabelText('Password');

emailInput.value = '[email protected]';
passwordInput.value = '12345678';

fireEvent.change(emailInput);
fireEvent.change(passwordInput);

debug();
/* 
In debug email has value of '[email protected]' and password has a value of ' ' 
*/

fireEvent.click(submitButton);

const emailErrorNode = queryByText('Email is required');
const passwordErrorNode = queryByText('Password is required')

expect(emailErrorNode).toBeNull();
expect(passwordErrorNode).toBeNull();

});

What you did:

Test a sign in form by setting username to '[email protected]' and password to '12345678'

What happened:

When updating 2 inputs in a test, only one input gets updated the second input's value is ' ' (empty)

Reproduction:


https://codesandbox.io/s/0xwn98wo1p

Problem description:


I can't test forms with more than one field change

Suggested solution:

help wanted needs investigation

Most helpful comment

Ok, so this bug happened due to the way React works, and now dom-testing-library's fireEvent utility supports setting properties on the target element when you fire an event. This allows you to set the value at the time of the event and dom-testing-library will set it in a way that works around how React tracks input value changes.

Here's how you use it: https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?module=%2Fsrc%2F__tests__%2Fon-change.js&previewwindow=tests

Here's the basic example:

fireEvent.change(passwordInput, {target: {value: '12345678'}})

:tada:

Thanks! Now we gotta figure out how to help people avoid this in the future 🤔

All 21 comments

Hi @pcfields,

Thanks for this. Please ping in here when you've added the minimal reproduction codesandbox. I definitely want to improve this so testing this kind of experience is more obvious.

FWIW, change is one of the events that we do some trickery for because the change event works differently with React than it does in a real browser. I'd love to do away entirely with this code: https://github.com/kentcdodds/react-testing-library/blob/9667967a085e438919fe3d02bc36761735bb2732/src/index.js#L50-L56

@kentcdodds I've updated the codesandbox https://codesandbox.io/s/0xwn98wo1p

Let me know how I can help you fix this? This is my first ever Github issue or contribution so i'm more than happy to help

Sounds great! Could you strip down your example to be as minimal as possible? The less code in there to reproduce the issue the better as it makes it easier for us to determine what could cause the issue.

@kentcdodds I've stripped down the code. Let me know if this is enough.

Let's try for something even simpler: https://codesandbox.io/s/2pokxwn2y0

I try to reduce it down to the smallest possible amount of code to still reproduce the bug :)

Ok, so I'm pretty sure that if we just remove this code we're golden. I didn't put that code there and I didn't quite understand why we needed it in the first place. But if I remove it then that test case works. Can you try removing that code from your node_modules to see if that causes any issues for you?

@kentcdodds Yes. But I remember, we had the discussion on the same lines of code before somewhere, I tried to search our issues/PR but no luck. Looks like Jomaxx have added these files, when we moved from React Simulate to native events. Not sure the reason behind it. @jomaxx any reasons?

👋 Hello, I’m traveling today but can take a look sometime next week. If
removing the code doesn’t break tests then I say go for it.
On Sat, Aug 4, 2018 at 9:59 AM antsmartian notifications@github.com wrote:

@kentcdodds https://github.com/kentcdodds Yes. But I remember, we had
the discussion on the same lines of code before somewhere, I tried to
search our issues, but no luck. Looks like Jomaxx have added these files,
when we moved from React Simulate to native events. Not sure the reason
behind it. @jomaxx https://github.com/jomaxx any reasons?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/kentcdodds/react-testing-library/issues/152#issuecomment-410435208,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACnsIBMf9KmMfhOewUg4Y15tMof0KxDvks5uNWJzgaJpZM4VupTF
.

Hi friends! So it doesn't quite do it for us. Test cases definitely fail because even though the value _does_ change, the event handlers are not called. I've figured out a way to fix this for onChange, but still need to work on the other three. I think I want these changes in dom-testing-library instead though.

I've opened a PR for this in react-testing-library to show how it works: #153

@pcfields, if you'd like to open a PR that makes this work in dom-testing-library that'd be great. I think that's the right place for this change because even though it's kind of an implementation detail for react it doesn't impact how things work for other frameworks and I believe that Cypress (another framework-agnostic tool) handles this case.

We'll definitely want some good comments for this though...

@kentcdodds I am only now seeing your message. What would you like me to do?

Ok, so this bug happened due to the way React works, and now dom-testing-library's fireEvent utility supports setting properties on the target element when you fire an event. This allows you to set the value at the time of the event and dom-testing-library will set it in a way that works around how React tracks input value changes.

Here's how you use it: https://codesandbox.io/s/github/kentcdodds/react-testing-library-examples/tree/master/?module=%2Fsrc%2F__tests__%2Fon-change.js&previewwindow=tests

Here's the basic example:

fireEvent.change(passwordInput, {target: {value: '12345678'}})

:tada:

Thanks! Now we gotta figure out how to help people avoid this in the future 🤔

Is that now the recommended way to change an input value then? Should the readme be updated?

Yes, if you're going to fire a change event then that's how the value should be changed. Otherwise manipulating the value should work fine.

Hmm, should this work with the latest version of this package on npm? It's not for working for me

Please be more specific @weyert. A reproduction would be helpful.

@kentcdodds Sorry, I am was goofing up! Checked the wrong form field! All working as expected. Amazingly awesome :D 🎉

fireEvent.change(passwordInput, {target: {value: '12345678'}})

This should definitely be added to the README file.

It is in the readme. Search for the string "fireEvent.change" in the README, and you'll find this:

fireEvent.change(comment, {
  target: {value: 'Great advice, I love your posts!'},
})
Was this page helpful?
0 / 5 - 0 ratings