Test text input with react and jest

16.8k Views Asked by At

I have a simple SearchBar component in a small test project of mine. This SearchBar consists mainly of a text input and a button, where the button click executes a callback with the text from the input field.

My Searchbar.render method looks like this:

  return (
    <FormGroup controlId="keywords">
      <InputGroup>
        <FormControl type="text"
                     placeholder="Keywords…"
                     value={this.state.keywords}
                     onChange={this.updateKeywords} />
        <InputGroup.Button
          onClick={() => {this.props.onSearch(this.state.keywords);}}
          ref="searchInput">
          <Button ref="searchButton">
            <Glyphicon glyph="search"/>
          </Button>
        </InputGroup.Button>
      </InputGroup>
    </FormGroup>
  );

I've written a test for it using jest:

it("should adjust keywords and trigger onSearch correctly", () => {
  const handleSearch = jest.fn();

  const searchBar = ReactTestUtils.renderIntoDocument(
    <Searchbar onSearch={handleSearch}/>
  );
  expect(searchBar.state.keywords).toBe("");

  const button = ReactDOM.findDOMNode(searchBar.refs.searchButton);
  const input = ReactDOM.findDOMNode(searchBar.refs.searchInput);

  ReactTestUtils.Simulate.change(input, {target: {value: "test"}});

  ReactTestUtils.Simulate.click(button);
  expect(handleSearch).toHaveBeenCalledWith("test");
});

Now the callback in this test works and the function stored in callMe get's called as expected. The SearchBar also works in my application so I think that the SearchBar code is correct. But when I use npm test to run my tests the test fails with:

expect(jest.fn()).toHaveBeenCalledWith(expected)

Expected mock function to have been called with:
  ["test"]
But it was called with:
  [""]

In the comments Andreas Köberle pointed me to the problem that the updateKeywords method appears to not be called which should be the reason for the failing test. Sadly I cannot figure out why this method isn't called in the test.

1

There are 1 best solutions below

4
On

You have to pass the event data by yourself, as it does not really trigger the event on a DOM element. From the docs:

You will have to provide any event property that you're using in your component (e.g. keyCode, which, etc...) as React is not creating any of these for you.

Is also common to just put a spy function as callback into your component, and test this after simulate the event.

const handleSearch = jest.fn();
const searchBar = ReactTestUtils.renderIntoDocument(
    <Searchbar onSearch={handleSearch}/>
);
ReactTestUtils.Simulate.change(input, {target: {value: 'test'}});
expect(handleSearch).toHaveBeenCalledWith('test')