2

I'm new to React testing and I'm having a hard time figuring out the following issue:

I'm trying to simulate an input onChange event. It's a text input that filters the results in a table. InteractiveTable has a controlled input field (ControlledInput) and an instance of Facebook's FixedDataTable.

This is the test:

let filter = ReactTestUtils.findRenderedComponentWithType(component, ControlledInput);
let input = ReactTestUtils.findRenderedDOMComponentWithTag(filter, 'input');
input.value = 'a';
ReactTestUtils.Simulate.change(input);
console.log(component.state);

On input change the component updates its state with the value of the input, but since setState is asynchronous, here the console.log will log out the previous state, and I can't query the structure of the component for testing, because it's not updated yet. What am I missing?

Edit: to be clear, if I make the assertion in a setTimeout, it will pass, so it's definitely a problem with the asynchronous nature of setState.

I found one solution, where I overwrite the componentDidUpdate method of the component:

component.componentDidUpdate = () => {
  console.log(component.state); // shows the updated state
  let cells = ReactTestUtils.scryRenderedComponentsWithType(component, Cell);
  expect(cells.length).toBe(30);
  done();
};

This wouldn't be possible if the component had its own componentDidUpdate method, so it's not a good solution. This seems to be a very common problem, yet I find no solution to it.

1 Answer 1

2

Normally when I run into similar scenarios when testing, I try to break things apart a little. In your current test, (depending on your flavor of test framework), you could mock the component's setState method, and simply ensure that it's called with what you expect when you simulate a change.

If you want further coverage, in a different test you could call the real setState with some mock data, and then use the callback to make assertions about what's rendered, or ensure other internal methods are called.

OR: If your testing framework allows for simulating async stuff, you could try calling that too and test the whole thing in one go.

Sign up to request clarification or add additional context in comments.

2 Comments

That's one solution, but not too black-boxy, where I'm testing how it works instead of just the results of a user interaction in itself.
Hmm. Yea, that's true. What testing tools are you using? The approach may vary a little depending on that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.