Tooltip MUI and React testing library
Asked Answered
L

2

8

I'm trying to test an Info HOC on my react app :

const InfoHOC = (HocComponent) => ({ message }) => (
  <>
    <Tooltip title={message}>
      <InfoIcon />
    </Tooltip>
    {HocComponent}
  </>
);

export default InfoHOC;

I've simplified it. But as it's using material ui Tooltip component, I can't test if message is displayed on mouseover...

it('should display info message on <div /> mouseover', () => {
  const Component = InfoHoc(<div>jest div</div>)({ message: 'jest infoHoc message' });
  const { getByTitle, getByDisplayValue } = render(Component);
  const icon = getByTitle('jest infoHoc message');
  act(() => {
    fireEvent(
      icon,
      new MouseEvent('mouseover', {
        bubbles: true,
      }),
    );
  });
  expect(getByDisplayValue('jest infoHoc message')).toBeInTheDocument();
});

My last line is wrong... I think it's because mui tooltip display the message in a div at the end of the body, so not really in my rtl tree... BUT the first element of this tree is body ! I know that I should not test mui component, but here is not the purpose, I just want to be sure that InfoHoc has the right comportment, using mui tooltip or something else.

Here is the RTL tree after mouseover action :

<body>
  <div>
    <div
      class="infoHoc"
    >
      <div>
        jest div
      </div>
      <svg
        aria-hidden="true"
        class="MuiSvgIcon-root icon--right"
        focusable="false"
        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>
    </div>
  </div>
</body>

The event is good because icon has a title attr with message as value till mouseover is fired. As title attr is not here on my tree, I assume my event is well executed ;p

I am wrong testing that ? If not do you have an idea to solve my problem ?

Thank you all !

Longeron answered 9/10, 2020 at 7:29 Comment(0)
A
7

In case this can still help you, you need to findBy instead of getBy as the Tooltip is showing the tooltip after a delay

it('should display info message on <div /> mouseover', async () => {
  const Component = InfoHoc(<div>jest div</div>)({ message: 'jest infoHoc message' });
  const { getByTitle, findByDisplayValue } = render(Component);
  const icon = getByTitle('jest infoHoc message');

  act(() => {
    fireEvent(
      icon,
      new MouseEvent('mouseover', {
        bubbles: true,
      }),
    );
  });

  // Wait for the tooltip to show up
  const tooltipText = await findByDisplayValue('jest infoHoc message')

  expect(tooltipText).toBeInTheDocument();
});

Side note 1: I am not sure if you really need the act around fireEvent. testing-library should do it for you.

Side note 2: you can use user-event which has a cleaner syntax (and a .hover function)

Annaleeannaliese answered 2/3, 2021 at 15:17 Comment(1)
I'll test it in my next project ! ThxLongeron
A
10

I think this is the cleanest way.

  it('Renders tooltip when hovering over button', async () => {
    render(<Search />);
    const button = await screen.findByRole('button');
    await userEvent.hover(button);
    const tip = await screen.findByRole('tooltip');
    expect(tip).toBeInTheDocument();
  });
Aryanize answered 19/4, 2022 at 21:15 Comment(2)
Then you can do something like this to check the tooltip's text: expect(tip.textContent).toBe('blah blah');Nonsmoker
I am using this now for assertion: await user.hover(moveLeftButton); const leftTooltip = await screen.findByRole('tooltip'); expect(leftTooltip).toContain(leftTooltip);Aryanize
A
7

In case this can still help you, you need to findBy instead of getBy as the Tooltip is showing the tooltip after a delay

it('should display info message on <div /> mouseover', async () => {
  const Component = InfoHoc(<div>jest div</div>)({ message: 'jest infoHoc message' });
  const { getByTitle, findByDisplayValue } = render(Component);
  const icon = getByTitle('jest infoHoc message');

  act(() => {
    fireEvent(
      icon,
      new MouseEvent('mouseover', {
        bubbles: true,
      }),
    );
  });

  // Wait for the tooltip to show up
  const tooltipText = await findByDisplayValue('jest infoHoc message')

  expect(tooltipText).toBeInTheDocument();
});

Side note 1: I am not sure if you really need the act around fireEvent. testing-library should do it for you.

Side note 2: you can use user-event which has a cleaner syntax (and a .hover function)

Annaleeannaliese answered 2/3, 2021 at 15:17 Comment(1)
I'll test it in my next project ! ThxLongeron

© 2022 - 2024 — McMap. All rights reserved.