Skip to content

onChange event not firing #637

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
laurage opened this issue Apr 15, 2020 · 10 comments
Closed

onChange event not firing #637

laurage opened this issue Apr 15, 2020 · 10 comments

Comments

@laurage
Copy link

laurage commented Apr 15, 2020

  • @testing-library/react version: ^9.3.2
  • react version: ^16.13.1
  • node version: v8.12.0
  • npm (or yarn) version: 6.4.1

Relevant code or config:

Input.js

import React, { useState } from 'react'

function Input({startingText}) {
  const [text, setText] = useState(startingText)

  function handleOnChange(event) {
    event.preventDefault()
    setText(event.target.value)
  }

  return (
    <input type="text" aria-label="user-input" value={text} onChange={handleOnChange} />
  )
}

export default Input

Input.test.js

import React from 'react'
import { Simulate } from 'react-dom/test-utils';
import { render } from '@testing-library/react'
import Input from './Input'

const inputContainer = render(<Input startingText="write"></Input>)
const input = inputContainer.getByLabelText("user-input")

test('user input is added after starting text', () => {
  Simulate.change(input, { target: { value: 'a' } })
  expect(input.value).toBe('writea')
})

OR if using fireEvent:
Input.test.js

import React from 'react'
import Input from './Input'
import { render, fireEvent } from '@testing-library/react'

const inputContainer = render(<Input startingText="write"></Input>)
const input = inputContainer.getByLabelText("user-input")

test('user input is added after starting text', () => {
  fireEvent.change(input, { target: { value: 'a' } })
  expect(input.value).toBe('writea')
})

What you did:

I am using the latest version of create-react-app.
I created an input which value changes when a user inputs something new.
"write" + a inputed becomes "writea". This works.

What happened / Problem description:

When testing it, it doesn't seem to work.
If I use fireEvent, I receive "a"

If I use Simulate, I receive "write"
and get an error: "Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. in Input (at Input.test.js:6)"

Suggested solution:

I had a look here: #359 but couldn't identify what might be the problem.
It might just be me badly implementing something - if so, my apologies!

@eps1lon
Copy link
Member

eps1lon commented Apr 15, 2020

What is the expected behavior you're looking for? It seems like you have an issue with react-dom/test-utils not @testing-library/react. If you're using @testing-library/react you don't need react-dom/test-utils anymore. These libraries have different semantics for events.

@laurage
Copy link
Author

laurage commented Apr 15, 2020

Hi,

Expected behaviour:
As explained above, I created an input which value changes when a user inputs something new.
if startingText = "write"
and the user inputs a,
The result displayed should be "writea"
This works in the browser.

Issue:
I've tried with two options, as you can see above.
Option #1 which uses Simulate does use 'react-dom/test-utils', but Option #2 using fireEvent doesn't. So if react-dom/test-utils' was the only problem, option #2 should work.

@kentcdodds
Copy link
Member

I believe to get what you want you'd need to do:

fireEvent.change(input, { target: { value: `${input.value}a` } })

Alternatively, I believe this should work (using @testing-library/user-event):

userEvent.type(input, 'a')

@laurage
Copy link
Author

laurage commented Apr 17, 2020

Thanks!

So I'm not sure the first option would be useful for this test, as (if I understand correctly), I would essentially be triggering a user input which would be ${input.value}a (= writea), and then checking that this is indeed what I would have received. This efficiently checks that the initial input.value is "write", but doesn't check that the function handleOnChange does its job. And I've already checked the first part via another test (that I didn't write in my initial post to simplify).

The second option you're suggesting seems that it would indeed check what I want to check, however I do not seem to be able to find userEvent, which comes back as undefined. @testing-library/user-event was already installed as part of create-react-app and I've tried to re-add it with npm just in case, but this doesn't change anything.

Checking the docs I also tried to add await in front of userEvent in case that would make a difference, but I then get an error saying I am not in an async function.

--
Update:
If I try to mock the handleOnChange function and test
expect(mockHandleOnChange).toHaveBeenCalledTimes(1)
then I can see that mockHandleOnChange is called 0 times. So it really seems as if fireEvent.change doesn't work I think.

--
Any idea what might be at play here?

@kentcdodds
Copy link
Member

Make sure you do:

import userEvent from '@testing-library/user-event'

@laurage
Copy link
Author

laurage commented Apr 17, 2020

Ah of course my bad, I had placed userEvent in curly brackets. Sorry for that!
I still get the same result than when using fireEvent though; handleOnChange doesn't seem to be fired, and so my result is the new value passed to the input via userEvent, and not updated by handleOnChange.

@kentcdodds
Copy link
Member

Well it works in my apps when I do it 🤷‍♂️ Without an actual example (like on in https://kcd.im/rtl-help) there's not much we can do for you. So feel free to make one there if you'd like more help.

Also, because this is most likely not a bug in Testing Library, I'm going to close this and refer you to https://spectrum.chat/testing-library if you have further questions. Thanks :)

@ashifiqbal-ai
Copy link

I am also facing the same issue. The value that I am getting is the updated one but the onChange event is not getting triggered.

@weyert
Copy link
Contributor

weyert commented Aug 8, 2020

Would be great if you could make a reproducible case e.g. with Codesandbox.com

@ashifiqbal-ai
Copy link

ashifiqbal-ai commented Aug 8, 2020

This is pretty strange. The test is passing in codesandbox but the same code is not passing on my codebase.
Here is the link to the codesandbox:
https://codesandbox.io/s/react-testing-library-onchange-2iqie?file=/src/input.component.spec.js

Update:
Sorry to bother, the problem is with the component I am using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants