Skip to main content

The issue between react-testing-library and Tooltip component from material UI

· 3 min read
Ruihua Niu
cover image

Overview​

When using getByRole from react-testing-library to retrieve the component/element content, it should be quite straightforward, but when the component/element is wrapped with the Tooltip component from Material UI, something weird happen: getByRole can only get the content of the tooltip rather than the component/element content. This article is going to explain why such issue happen and how to fix it.

Step to reproduce the issue with Tooltip component​

The code below shows the issue in details: getByRole can only get the tooltip content but not the element content itself.

<Tooltip title="tooltip content" placement="bottom-start">
<Typography variant="h6" gutterBottom>
typography content
</Typography>
</Tooltip>

//This assertion with react-testing-library doesn't work:
expect(screen.getByRole("heading", { level: 6, name: "typography content" })).toBeInTheDocument()


// This assertion below works:
expect(screen.getByRole("heading", { level: 6, name: "tooltip content" })).toBeInTheDocument()

There are two weird things happen here:

  1. getByRole cannot get the element content but the tooltip content

    expect(screen.getByRole("heading", { level: 6, name: "typography content" })).toBeInTheDocument() doesn't work, but expect(screen.getByRole("heading", { level: 6, name: "tooltip content" })).toBeInTheDocument() works

  2. the tooltip content is not in h6, but getByRole("heading", { level: 6, name: "tooltip content" }) works

The real cause of the issue​

Actually, if we take a look of the element that wrapped within tooltip in Chrome Dev tools, we can see there is an aria-label attribute attached to it, with the content of the tooltip.

<h6 
class="MuiTypography-root"
aria-label="tooltip content" // Here is the trick
data-mui-internal-clone-element="true"
>
typography content
</h6>

The reason is that Material UI automatically add the aria-label attribute to any element wrapped in Tooltip component in order to improve the accessibility.

Why getByRole take aria-label precedence over element content​

As the react-testing-library document says:

The accessible name is for simple cases equal to e.g. the label of a form element, or the text content of a button, or the value of the aria-label attribute https://testing-library.com/docs/queries/byrole

The name property within getByRole means the accessible name, and accessible name is not simply equal to the element text content. And the accessible name provided by ARIA has a higher precedence than that derived from the element content.

How to fix it​

One workaround is to use a different query api from react-testing-library to avoid the issue caused by getByRole, it should be something like this:

<Tooltip title="tooltip content" placement="bottom-start">
<Typography variant="h6" gutterBottom>
typography content
</Typography>
</Tooltip>

//This assertion with react-testing-library works:
expect(screen.getByText( "typography content", {selector:"h6"})).toBeInTheDocument()

Final​

It's an issue caused by both getByRole from react-testing-library and Tooltip component from Material UI. More importantly, it should be clear about what an accessible name is.