React testing library: The given element does not have a value setter when fireEvent change on input form

I want to change the value of material UI TextField in react testing library. I already set up the data-testid. Then using getByTestId i picked up the input element.

// the component
<TextField
  data-testid="input-email"
  variant="outlined"
  margin="normal"
  required
  fullWidth
  id="email"
  label="Email Address"
  name="email"
  value={email}
  onChange={e => setEmail(e.target.value)}
  autoComplete="email"
  autoFocus
/>
// the test 
//...
let userInput = getByTestId('input-email')
fireEvent.change(userInput, { target: { value: '[email protected]' } })

but this doesn't work as it's returning error: The given element does not have a value setter. Isn't the element uses e.target.value on it's onChange attribute? What am I do wrong?

Answers:

Answer

Problem here is TextField is an abstraction in MaterialUI. It consists of FormControl, Label and Input. Clean way of solving this problem is:

  • First, add InputProps on your TextField, with data-testid attribute.
// YourComponent.js

<TextField
  onChange={event => setContent(event.target.value)}
  id="content"
  inputProps={{ "data-testid": "content-input" }}
  value={content}
  label="Content"
/>
  • Then simply query using this ID.
// YourComponent.test.js

const contentInput = getByTestId("content-input");
fireEvent.change(contentInput, {
  target: { value: "new content" }
});

// and then assert stuff in here
Answer

You can use fireEvent.change on an element that supports that event like <input>. In your case, I'm not sure what you're selecting. You can try to debug(userInput) to see what it returns.

Answer

the issue here is when we use Material UI, it renders the TextField component having one of the elements inside it as an input field. And only "input" has getter and setter on it. So after you got the TextField, you have to get the "input" element of your TextField using querySelector() of your DOM object.

const field = getByTestId('input-email').querySelector('input');
// now fire your event
fireEvent.change(field, { target: { value: '[email protected]' } });

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.