Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to test react-select with react-testing-library

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

like image 237
user2133814 Avatar asked Apr 08 '19 14:04

user2133814


People also ask

How do you use React with select?

To select a default option in React, the selected attribute is used in the option element. In React, though, instead of using the selected attribute, the value prop is used on the root select element. So, you can set a default value by passing the value of the option in the value prop of the select input element.

How do you simulate a dropdown in Jest?

const component = mount(<MyComponent/>); component. find("#dropdown"). simulate("change", { target: { value: "item1", selectedIndex: 1 } });


1 Answers

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');    ( ... )  } 
like image 92
momimomo Avatar answered Oct 08 '22 02:10

momimomo