JedWatson / react-select

The Select Component for React.js
https://react-select.com/
MIT License
27.42k stars 4.1k forks source link

Menu is closing inside tests #5867

Open RichMatthews opened 4 months ago

RichMatthews commented 4 months ago
     <AsyncReactSelect
        defaultOptions
        loadOptions={async () => [
          { value: "Pear", label: "Pear" },
          { value: "Banana", label: "Banana" },
          { value: "Raspberry", label: "Raspberry" },
        ]}
        closeMenuOnSelect={false}
        isMulti
        onMenuClose={() => {
          console.log("called the close!!")
        }}
      />

In the browser is fine. I select an option, menu stays open and option populates into select

In my tests however it seems to close at this point

    await act(async () => {
      // assert option not selected yet
      expect(screen.queryByLabelText("Remove Dr Jimmy Carter")).toBe(null)

      // open the dropdown
      const selectDropdown = screen.getAllByRole("combobox")[0]
      await userEvent.click(selectDropdown)

      await screen.findByText("Pear")

      await userEvent.keyboard("{enter}")
      await screen.findByLabelText("Remove Pear")

      screen.debug()
    })

I notice that this line await userEvent.keyboard("{enter}") correctly selects the option but closes the menu. I verified this by seeing "called the close!!" being called in my tests. This is only called in the browser when I click outside (as expected). Anything wrong in the component or is it the testing library?

Krishna8691 commented 4 months ago

I tested this locally and as mentioned in the description I also get the same issue. But then I cloned the official repo and after spending some time digging into this I found that there is blurInputOnSelect prop (whose default value depends on if device supports TouchEvent). In test environment this value is always true. But in desktop browser this value is false. When this prop is true (in test enviroment) the blur event is triggered on the input element after selecting an option and hence the menu is closed and the focus is no longer with the input element so the test case fails if we try to consecutively make enter keyboard events and assert for the selected options.

To set the value of blurInputOnSelect react-select is using this function here - https://github.com/JedWatson/react-select/blob/06e34882638d1526b9f5a1238bb567a3e9460ce5/packages/react-select/src/utils.ts#L324 and in testing environment this always returns true.

I wrote these very simple test cases to check this behavior. Both test cases are passing for me (after setting the above prop to false which doesn't let the onBlur callback to be called). with userEvent -https://github.com/Krishna8691/react-select-test-cases/blob/main/user-event.js

with fireEvent - https://github.com/Krishna8691/react-select-test-cases/blob/main/fire-event.js

As per the documentation the blurInputOnSelect is used for this

Remove focus from the input when the user selects an option (handy for dismissing the keyboard on touch devices)

I am not sure if you can disabled the touch events though within the testing library (cannot find anything about this) but looks like its not a problem on react-select side of things yet there is the above prop which I think maybe is present exactly for this because of the functionality differences on touch and non touch devices possibly not sure :)

Edit: I don't see this mentioned anywhere in the documentation maybe worth mentioning in the documentation.

RichMatthews commented 4 months ago

thanks a lot for the great insight @Krishna8691 @JedWatson are you able to help out or advise anything here? thanks

Krishna8691 commented 4 months ago

thanks a lot for the great insight @Krishna8691 @JedWatson are you able to help out or advise anything here? thanks

No problem. I don't think this is a bug or an issue as such so most likely this can be closed.

Krishna8691 commented 4 months ago

I don't see any explicit details or hints about the behavior in the below linked comment of this thread in the documentation. I think and If you @JedWatson also think then let me know I would like to make a contribution towards the documentation regarding this if the behavior is just as expected. Thanks.

https://github.com/JedWatson/react-select/issues/5867#issuecomment-1975123337