3

I'm having some problems that I'm not able to test the MUI dropdown. I'm getting this error: Unable to find an accessible element with the role "option" and name "/ninica/i"

I have an example code here: https://codesandbox.io/s/react-testing-library-material-ui-dropdown-5knbgu

My test:

test("select", () => {
  render(<App />);

  // Get and click in the dropdown
  const dropdownButton = screen.getByRole("button", { name: /dog name ​/i });
  fireEvent.click(dropdownButton);

  // Get and click in the dropdown item
  const dropdownItem = screen.getByRole("option", { name: /ninica/i });
  fireEvent.click(dropdownItem);
});

I already try to use getByTestId but have the same result, can't find.

3 Answers 3

6

First of all, for component interaction, prefer the use of userEvent instead fireEvent as testing-library describes:

The built-in fireEvent is a utility to easily dispatch events. It dispatches exactly the events you tell it to and just those - even if those exact events never had been dispatched in a real interaction in a browser.

user-event on the other hand dispatches the events like they would happen if a user interacted with the document. That might lead to the same events you previously dispatched per fireEvent directly, but it also might catch bugs that make it impossible for a user to trigger said events. This is why you should use user-event to test interaction with your components.

You can check more about it here.

Related to test not find option role, it´s because the element take some milliseconds to appear on screen and because of that your test should be async and you need to use await and findBy query to succeed in the test:

import { render, screen, cleanup } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("select", async () => {
  render(<App />);

  const dropdownButton = screen.getByRole("button");

  userEvent.click(dropdownButton);

  const dropdownItem = await screen.findByRole("option", { name: /ninica/i });

  userEvent.click(dropdownItem);

  const typographyEl = await screen.findByText(/Chosen name: ninica/i);

  expect(typographyEl).toBeInTheDocument();
});

You can check more about async/await and findBy query here.

You can also check the difference of queries here.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey, thanks for your time, the help and for the references. I already update the project if you can and want to check out :) (Sorry, I didn’t reply sooner, I didn’t check 😅)
2

Try

test("select", async () => {
  render(<App />);

  // Get and click in the dropdown
  const dropdownButton = screen.getByRole("button", { name: /dog name ​/i });
  fireEvent.click(dropdownButton);

  // Wait for dropdown item and click it
  const dropdownItem = await screen.findByTestId("name-item-2");
  fireEvent.click(dropdownItem);
});

There are some ms in between the click and the apearance on the screen of the element, so you have declare your function as async and to await for your element to appear (and use findBy instead of getBy in order to work as async).

you can read more about testing-library async methods here

4 Comments

Hey, thanks for your time, but I tried, and it’s not working, keeps showing error. I already update the project if you can and want to check out :) (Sorry, I didn’t reply sooner, I didn’t check 😅)
Hello! Is working for me: ibb.co/jZykCFw
But I think codesanbox is not the best in properly giving the tests results due to catching, so I would advise you to try on your local machine as well (or at least try to access the link in an incognito window)
Ohhh, yap, it's now working for me too 🤦
1

In my case element.click() event does not trigger dropdown open, so I had to come up with code changes in my component where I can open it via {open} and bind to select itself here is how I have done it.

  import React from 'react';
  import InputLabel from '@material-ui/core/InputLabel';
  import MenuItem from '@material-ui/core/MenuItem';
  import FormControl from '@material-ui/core/FormControl';
  import Select from '@material-ui/core/Select';
  import Button from '@material-ui/core/Button';
    
    export default function ControlledOpenSelect() {
      const [value, setValue] = React.useState('');
      const [open, setOpen] = React.useState(false);
    
      const handleChange = (event) => {
        setValue(event.target.value);
      };
    
      return (
        <div>
          <FormControl >
            <Select
              open={open}
              onClick={()=> setOpen(!open)}
              value={value}
              onChange={handleChange}
            >
              <MenuItem value="">
                <em>None</em>
              </MenuItem>
              <MenuItem value={10}>Ten</MenuItem>
              <MenuItem value={20}>Twenty</MenuItem>
              <MenuItem value={30}>Thirty</MenuItem>
            </Select>
          </FormControl>
        </div>
      );
    }

in any testing now click event triggers open of select, Not sure if it's an bad pratice, but yeah it works :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.