App.js
import React, { Component } from "react";
import Select from "react-select";
const SELECT_OPTIONS = ["FOO", "BAR"].map(e => {
return { value: e, label: e };
});
class App extends Component {
state = {
selected: SELECT_OPTIONS[0].value
};
handleSelectChange = e => {
this.setState({ selected: e.value });
};
render() {
const { selected } = this.state;
const value = { value: selected, label: selected };
return (
<div className="App">
<div data-testid="select">
<Select
multi={false}
value={value}
options={SELECT_OPTIONS}
onChange={this.handleSelectChange}
/>
</div>
<p data-testid="select-output">{selected}</p>
</div>
);
}
}
export default App;
App.test.js
import React from "react";
import {
render,
fireEvent,
cleanup,
waitForElement,
getByText
} from "react-testing-library";
import App from "./App";
afterEach(cleanup);
const setup = () => {
const utils = render(<App />);
const selectOutput = utils.getByTestId("select-output");
const selectInput = document.getElementById("react-select-2-input");
return { selectOutput, selectInput };
};
test("it can change selected item", async () => {
const { selectOutput, selectInput } = setup();
getByText(selectOutput, "FOO");
fireEvent.change(selectInput, { target: { value: "BAR" } });
await waitForElement(() => getByText(selectOutput, "BAR"));
});
This minimal example works as expected in the browser but the test fails. I think the onChange handler in is not invoked. How can I trigger the onChange callback in the test? What is the preferred way to find the element to fireEvent at? Thank you
In my project, I'm using react-testing-library and jest-dom. I ran into same problem - after some investigation I found solution, based on thread: https://github.com/airbnb/enzyme/issues/400
Notice that the top-level function for render has to be async, as well as individual steps.
There is no need to use focus event in this case, and it will allow to select multiple values.
Also, there has to be async callback inside getSelectItem.
const DOWN_ARROW = { keyCode: 40 };
it('renders and values can be filled then submitted', async () => {
const {
asFragment,
getByLabelText,
getByText,
} = render(<MyComponent />);
( ... )
// the function
const getSelectItem = (getByLabelText, getByText) => async (selectLabel, itemText) => {
fireEvent.keyDown(getByLabelText(selectLabel), DOWN_ARROW);
await waitForElement(() => getByText(itemText));
fireEvent.click(getByText(itemText));
}
// usage
const selectItem = getSelectItem(getByLabelText, getByText);
await selectItem('Label', 'Option');
( ... )
}