hc-oss / react-multi-select-component

Lightweight (~5KB gzipped) multiple selection dropdown component
https://codesandbox.io/s/react-multi-select-example-uqtgs
MIT License
386 stars 89 forks source link

Testing with React Testing Library #119

Closed JeffersonCarvalh0 closed 4 years ago

JeffersonCarvalh0 commented 4 years ago

Greetings,

I'd like to know if there is any recommended way to test interactions with this component using RTL. Currently, with the most updated versions of @testing-library/react (10.4.9) and @testing-library/user-event (12.1.3) I'm not able to simulate options being select by the user.

I've already tried simulating click events choosing the select by its placeholder (e.g: userEvent.click(getByText('Select...'))) but it didn't show the options inside the testing environment so I could simulate another click event on one of them. I've also already tried simulating clicks on the parent div elements of the placeholder node, but it didn't work either. Apart from that, I cannot use userEvent.selectOptions because react-multi-select-component doesn't render to an html select component.

So, can someone shed me a light on this? Thanks in advance!

harshzalavadiya commented 4 years ago

Hi @JeffersonCarvalh0,

I don't have much idea on @testing-library/react but in general you want to perform programmatic toggle, you may try targeting dropdown-heading class I tried with pure JavaScript and it worked so should work for testing-library as well.

document.querySelector(".dropdown-heading").click()
harshzalavadiya commented 4 years ago

closing this as of now if still having issues feel free to reopen or create a new issue

JeffersonCarvalh0 commented 4 years ago

Hi @harshzalavadiya Sorry for taking so long to answer. Unfortunately, it didn't solve my problem. Probably it is something with RTL then

jonpepler commented 3 years ago

Hi, this is quite an old issue but I just wanted to share some example code for how you might interact with this component with Testing Library. I don't know if anything relevant to this has changed since 10.4.9, but I can confirm that this example is functional in @testing-library/react 11.2.5. Selecting based on the placeholder works as described, but you can also select options via getByLabelText:

Component:

<MultiSelect
  options={[
    { label: 'A', value: 'A' },
    { label: 'B', value: 'B' },
    { label: 'C', value: 'C' }
  ]}
  value={selected}
  onChange={setSelected}
  overrideStrings={{ selectSomeItems: 'My Specific Select Text' }}
/>

Test:

import { render, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

it('selects', async () => {
  const labels = ['A', 'B', 'C']
  const selectText = 'My Specific Select Text'
  const { getByLabelText, getByText } = render(<MyComponentWithMultiSelect />)

  ...

  // Check that MultiSelect component is present
  expect(getByText(selectText)).toBeInTheDocument())

  // Open dropdown with userEvent
  userEvent.click(getByText(selectText))

  // Check that the labels you expect to see are present 
  await waitFor(() => {
    labels.forEach(label => expect(getByLabelText(label)))
  })

  // Select an option
  const optionB = getByLabelText('B')
  userEvent.click(optionB)

  ...
})

By using the overrideStrings you can ensure that you're always selecting the right MultiSelect component even when you have multiple in a page. Hope that helps 😄 🐙