How to test material ui autocomplete with react testing library How to test material ui autocomplete with react testing library reactjs reactjs

How to test material ui autocomplete with react testing library


Since the list items are not "visible" in the DOM itself you need to use a different approach.

You have to locate the autocomplete and input DOM elements on which you will trigger events.

The autocomplete is usually found in the DOM by the role attribute e.g. role="combobox" but it's best to give it a unique identifier such as data-testid="autocomplete"

The following code shows how to test item selection in autocomplete:

   const autocomplete = getByTestId('autocomplete');   const input = within(autocomplete).querySelector('input')   autocomplete.focus()   // assign value to input field   fireEvent.change(input, { target: { value: value } })   await wait()   // navigate to the first item in the autocomplete box   fireEvent.keyDown(autocomplete, { key: 'ArrowDown' })   await wait()   // select the first item   fireEvent.keyDown(autocomplete, { key: 'Enter' })   await wait()   // check the new value of the input field   expect(input.value).toEqual('some_value')

You need to insert a value on the input element then trigger the change. After that the listbox opens which permits selecting the first value by firing the enter key. The selected value will replace the entered initial value used to search/open the autocomplete.


First of all, you need to make sure the options are not empty array, then do the following:

const autocomplete = getByTestId('autocomplete');const input = within(autocomplete).getByRole('textbox')autocomplete.focus()// the value here can be any string you want, so you may also consider to // wrapper it as a function and pass in inputValue as parameterfireEvent.change(input, { target: { value: 'a' } })fireEvent.keyDown(autocomplete, { key: 'ArrowDown' })fireEvent.keyDown(autocomplete, { key: 'Enter' })


// make sure autocomplete reactions/results do not already existexpect(screen.queryByText(/Loading/)).not.toBeInTheDocument()expect(screen.queryByText(/Van Halen/)).not.toBeInTheDocument()// fill out autocompleteconst faveBand = screen.getByLabelText(/Favorite Band/)userEvent.type(faveBand, 'Van H')expect(faveBand).toHaveValue('Van H')// witness autocomplete workingexpect(screen.getByText(/Loading/)).toBeInTheDocument()// wait for response (i used an async Material-UI autocomplete)// favebands is a data-testid attribute value in my autocomplete // component, e.g. ListboxProps={{ 'data-testid': 'favebands' }}await waitFor(() => getByTestId('favebands'))// verify autocomplete items are visibleexpect(screen.getByText(/Van Halen/)).toBeInTheDocument()// click on autocomplete itemconst faveBandItem = screen.getByText('Van Halen')userEvent.click(faveBandItem)// verify autocomplete has new valueexpect(faveBand).toHaveValue('Van Halen')    

I import userEvent, waitFor, and screen like so...

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