2

I am trying to test that when I hover over an icon, a tooltip appears with certain text.

Using Jest, react testing library, and the tooltip is a MUI 4 component.

The icon and tooltip

<div
   data-testid="tooltip-icon"
   className={classes.infoTooltipIcon}
>
   <Tooltip
      data-testid="tooltip-text"
      title="Tooltip text"
   >
      <InfoIcon/>
   </Tooltip>
</div>

Slimmed down test

it('has a tooltip on the info icon', () => {
    render(<Component />);

    const infoIcon = screen.getByTestId('tooltip-icon');
    userEvent.hover(infoIcon); // works
    
    const infoTooltip = screen.getByTestId('tooltip-text')
    expect(infoTooltip.title).toEqual('Tooltip text);
  });

Currently, this results in

actual: undefined
expected: 'Tooltip text'

If I screen.debug(infoTooltip) the title is there and has the correct text, but its an <svg/> could this cause an issue?

Output of screen.debug(infoTooltip)

<svg
      aria-hidden="true"
      class="MuiSvgIcon-root makeStyles-center-52"
      data-testid="tooltip-text"
      focusable="false"
      title="Tooltip text"
      viewBox="0 0 24 24"
    >
      <path
        d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"
      />
    </svg>

Additionally, I have also tried screen.getByTitle('Tooltip text') and it does not work.

2
  • Can you try to use queryByTestId rather than getByTestId? Commented Sep 2, 2021 at 16:37
  • Same thing, actual: undefined, I have posted the output of screen.debug() Commented Sep 2, 2021 at 16:53

3 Answers 3

2

It seems like MUI applies the tooltip to whatever the child of the <Tooltip/> is, in my case it was the <svg/> generated by <InfoIcon/>. If you wrap the <InfoIcon/> in a <span> tag the tooltip title will then be applied to the <span/>, making it possible to explicitly look for the tooltip text.

My UI

<div
   data-testid="tooltip-icon"
   className={classes.infoTooltipIcon}
>
   <Tooltip
      data-testid="tooltip-text"
      title="Tooltip text"
   >
      <span>
         <InfoIcon/>
     </span>
   </Tooltip>
</div>

My test

it('has a tooltip on the info icon', () => {
    render(<Component />);

    const infoIcon = screen.getByTestId('tooltip-icon');
    userEvent.hover(infoIcon);
    
    const infoTooltip = screen.getByTestId('tooltip-text')
    expect(infoTooltip.title).toEqual('Tooltip text);
  });

This way if I have multiple tooltips I can ensure I'm grabbing the exact one I want via test id.

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

Comments

0

The better solution is that you should just use the InfoIcon with titleAccess props. https://material-ui.com/api/svg-icon

<InfoIcon titleAccess="Tooltip Text" />

After that, you could test the component like this as an example.

expect(
      getByRole('tooltip', { hidden: true, name: 'Tooltip Text' }),
    ).toBeInTheDocument();

1 Comment

If you change the role from tooltip to img this works, I think MUI applies the tooltip to whatever the child element is, and in this case it was the <svg/> opting for a different more explicit solution because I have some components with multiple tooltips this would not work/be less clean for.
0

Your suggestion with the span is good! If you don't want to add a span, then I think you just need to adjust the query to look for aria-hidden elements.(Since the svg has aria-hidden=true it gets excluded from the accessibility tree). The query would look like: const tooltip = screen.getByTitle("Tooltip text", { hidden: true } )

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.