How do I trigger the change event on a react-select component with react-testing-library?
Asked Answered
B

3

19

Given that I can't test internals directly with react-testing-library, how would I go about testing a component that uses react-select? For instance, if I have a conditional render based on the value of the react-select, which doesn't render a traditional <select/>, can I still trigger the change?

import React, { useState } from "react";
import Select from "react-select";

const options = [
  { value: "First", label: "First" },
  { value: "Second", label: "Second" },
  { value: "Third", label: "Third" },
];

function TestApp() {
  const [option, setOption] = useState(null);
  return (
    <div>
      <label htmlFor="option-select">Select Option</label>
      <Select
        value={option}
        options={options}
        onChange={option => setOption(option)}
      />
      {option && <div>{option.label}</div>}
    </div>
  );
}

export default TestApp;

I'm not even sure what I should query for. Is it the hidden input?

Bib answered 24/2, 2019 at 3:13 Comment(0)
D
3

You can try the following to get it working:

  1. Fire focus event on the ReactSelect component .react-select input element.
  2. Fire a mouseDown event on the .react-select__control element
  3. Fire a click on the option element that you want to select

You can add a className and classNamePrefix props with the value of "react-select" in order to specifically select the component you are trying to test.

PS: In case you are still stuck I'd encourage you to take a look at this conversation from where the above answer is borrowed - https://spectrum.chat/react-testing-library/general/testing-react-select~5857bb70-b3b9-41a7-9991-83f782377581

Dennison answered 24/2, 2019 at 6:22 Comment(2)
I saw @gpx mention in that thread to mock it. I don't think I've ever mocked out a component. Does it work the same?Bib
Thanks. I found this one on spectrum too, which has an example test. .Bib
T
32

My team has a test utility in our project that lets us select an item easily after spending too much time trying to figure out how to do this properly. Sharing it here to hopefully help others.

This doesn't rely on any React Select internals or mocking but does require you to have set up a <label> which has a for linking to the React Select input. It uses the label to select a given choice value just like a user would on the real page.

const KEY_DOWN = 40

// Select an item from a React Select dropdown given a label and
// choice label you wish to pick.
export async function selectItem(
  container: HTMLElement,
  label: string,
  choice: string
): Promise<void> {
  // Focus and enable the dropdown of options.
  fireEvent.focus(getByLabelText(container, label))
  fireEvent.keyDown(getByLabelText(container, label), {
    keyCode: KEY_DOWN,
  })

  // Wait for the dropdown of options to be drawn.
  await findByText(container, choice)

  // Select the item we care about.
  fireEvent.click(getByText(container, choice))

  // Wait for your choice to be set as the input value.
  await findByDisplayValue(container, choice)
}

It can be used like this:

it('selects an item', async () => {
  const { container } = render(<MyComponent/>)

  await selectItem(container, 'My label', 'value')
})
Teocalli answered 10/5, 2019 at 22:54 Comment(1)
This answer has been extracted into an npm package: github.com/romgain/react-select-eventWollis
D
3

You can try the following to get it working:

  1. Fire focus event on the ReactSelect component .react-select input element.
  2. Fire a mouseDown event on the .react-select__control element
  3. Fire a click on the option element that you want to select

You can add a className and classNamePrefix props with the value of "react-select" in order to specifically select the component you are trying to test.

PS: In case you are still stuck I'd encourage you to take a look at this conversation from where the above answer is borrowed - https://spectrum.chat/react-testing-library/general/testing-react-select~5857bb70-b3b9-41a7-9991-83f782377581

Dennison answered 24/2, 2019 at 6:22 Comment(2)
I saw @gpx mention in that thread to mock it. I don't think I've ever mocked out a component. Does it work the same?Bib
Thanks. I found this one on spectrum too, which has an example test. .Bib
H
0

Environment Setup react-v18.2.0 react-select-v5.7.0

Issue: Click Event is not simulating and triggering react-select dropdown in order to automate the process.

Solution: You have to follow these steps in order to achieve this.

  1. We will be using CSS selectors so in order to avoid any arbitrary classes, we have to configure the component.

import Select from 'react-select';

<Select
    {...anyOtherConfig}
    id="countriesListDropdown"
    name="countriesList"
    instanceId="countriesList"
    inputId="countriesListInput"
    classNamePrefix='list'
/>
  1. Now we will simulate the mousedown event on dropdown Indicator

    triggerMouseEvent(document.querySelector("#countriesListDropdown .list__dropdown-indicator"), "mousedown");

    This will open the dropdown menu and list of items will be rendered in dom as well in div element.

  2. Lastly we have to match the inner text of each div item and simulate click event on it, example:

document.querySelector("#react-select-countriesList-option-1").click()

Debugging: Once you run trigger step 2 event don't click anywhere on dom and just navigate from Elements Inspect, if you click anywhere on dom dropdown menu will hide itself.

Hebraism answered 16/5, 2023 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.