Skip to content

[BUG] jest/testing-library Tests are breaking and tooltip content is not shown #1082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fmacherey opened this issue Aug 9, 2023 · 5 comments
Labels

Comments

@fmacherey
Copy link

fmacherey commented Aug 9, 2023

Bug description
Jest tests are breaking and the tooltip is sometimes visible and sometimes not, when clicked with user-event. This makes our snapshot and text selector tests not working properly.

But I get an error from testing-library

Unable to find role="tooltip"

Ignored nodes: comments, script, style

Version of Package
5.20.0

To Reproduce
The component

import React, { useId } from "react";
import dayjs from "dayjs";
import { type ForecastAstronomy } from "../[...]/types/astronomy";
import { Tooltip } from "react-tooltip";
import { CloseButton, Grid, TooltipReference } from "./styles";

export type AstronomyTooltipProps = {
    astronomy: ForecastAstronomy;
};

export const AstronomyTooltip: React.FC<AstronomyTooltipProps> = ({
    astronomy,
}) => {
    const id = useId();
    const tooltipId = `astronomy-tooltip-${id}`;

    return (
        <TooltipReference data-tooltip-id={tooltipId} role="button">
            {typeof astronomy.moonphase.value === "number" ? (
                <span
                    className={`icon-moonphase-${astronomy.moonphase.value}`}
                />
            ) : null}
            {astronomy.moonphase.text}
            <span className="icon-help" />
            <Tooltip id={tooltipId} place="bottom" openOnClick>
                <CloseButton role="button">&times;</CloseButton>
                Astronomie
                <Grid>
                    <div>Mondaufgang:</div>
                    <div>
                        {astronomy.moonrise !== null
                            ? `${dayjs(astronomy.moonrise).format("HH:ss")} Uhr`
                            : null}
                    </div>
                    <div>Monduntergang:</div>
                    <div>
                        {astronomy.moonset !== null
                            ? `${dayjs(astronomy.moonset).format("HH:ss")} Uhr`
                            : null}
                    </div>
                    <div>Mondphase:</div>
                    <div>{astronomy.moonphase.text}</div>
                    <div>Tierkreiszeichen:</div>
                    <div>{astronomy.moonzodiac.text}</div>
                </Grid>
            </Tooltip>
        </TooltipReference>
    );
};

The jest test

import forecastWeatherNearbyResponse from "../[...]/mockedResponses/forecastWeatherNearby.json";
import { render, waitFor } from "@testing-library/react";
import { AstronomyTooltip } from "./index";
import userEvent from "@testing-library/user-event";

describe("AstronomyTooltip", () => {
    const astronomyData = {
        ...forecastWeatherNearbyResponse.data.items[0].summary.astronomy,
    };

    test("component should display astronomy data when button is clicked", async () => {
        const wrapper = await render(
            <AstronomyTooltip astronomy={astronomyData} />
        );
        const user = userEvent.setup();

        await user.click(wrapper.getByRole("button"));

        await waitFor(async () => {
            expect(wrapper.getByRole("tooltip")).toBeInTheDocument();

            expect(await wrapper.findByText(/Astronomie/)).toBeInTheDocument();
            expect(await wrapper.findByText(/Mondaufgang/)).toBeInTheDocument();
            expect(
                await wrapper.findByText(/Monduntergang/)
            ).toBeInTheDocument();
            expect(await wrapper.findByText(/Mondphase/)).toBeInTheDocument();
            expect(
                await wrapper.findByText(/Tierkreiszeichen/)
            ).toBeInTheDocument();
            expect(wrapper).toMatchSnapshot();
        });
    });
});

Expected behavior
Tests should be always working

Smartphone (please complete the following information if possible or delete this section):

  • Frameworks Next.js 13

Additional context
n/a

@fmacherey fmacherey added the Bug label Aug 9, 2023
@fmacherey
Copy link
Author

Additional info: I also tried to use act with the user click, but without success

await act(async () => {
    await user.click(wrapper.getByRole("button"));
});

@gabrieljablonski
Copy link
Member

We've been having some inconsistency issues with our own tests (see #1080), might be related.

Will be investigating soon.

@Steffan-Harris
Copy link

Steffan-Harris commented Oct 24, 2023

I'm experiencing a similar issue with jest not working:

My test

it.only('Tooltip test', async () => {
  render(
    <>
      <button
        data-tooltip-id="react-tooltip"
        data-tooltip-content="Hello World"
      >
        Test
      </button>
      <Tooltip id="react-tooltip" />
    </>
  );

  const test = screen.getByRole('button', { name: 'Test' });

  await userEvent.hover(test);

  let tooltip = null;

  await waitFor(() => {
    tooltip = screen.getByRole('tooltip');
    expect(tooltip).toHaveAttribute('style');
  });
});

Test output

    console.error
    Warning: An update to O inside a test was not wrapped in act(...).
    
    When testing, code that causes React state updates should be wrapped into act(...):
    
    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */
    
    This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
        at O (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-tooltip/dist/react-tooltip.min.cjs:7:3781)
        at Object.<anonymous>.exports.Tooltip (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-tooltip/dist/react-tooltip.min.cjs:8:1115)
        at ModalProvider (/Users/steffan.harris/git/work/retail-trade-desk-ui/src/components/library/modals/base/provider.tsx:48:11)
        at ModalProvider (/Users/steffan.harris/git/work/retail-trade-desk-ui/src/components/tailwind/modal/modal-provider.tsx:6:30)
        at RenderedRoute (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-router/lib/hooks.tsx:635:26)
        at Routes (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-router/lib/components.tsx:460:3)
        at Router (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-router/lib/components.tsx:378:13)
        at MemoryRouter (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-router/lib/components.tsx:192:3)
        at TestingRoute (/Users/steffan.harris/git/work/retail-trade-desk-ui/src/utils/testing/TestingRoute.tsx:10:3)
        at NotificationProvider (/Users/steffan.harris/git/work/retail-trade-desk-ui/src/components/tailwind/notification/notification-provider.tsx:5:37)
        at Object.<anonymous>.exports.ThemeProvider (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/styled-components/src/models/ThemeProvider.js:24:7)
        at QueryClientProvider (/Users/steffan.harris/git/work/retail-trade-desk-ui/node_modules/react-query/lib/react/QueryClientProvider.js:45:21)
        at AllTheProviders (/Users/steffan.harris/git/work/retail-trade-desk-ui/src/utils/testing/utils.tsx:41:3)
        at wrapper

      772 |       const test = screen.getByRole('button', { name: 'Test' });
      773 |
    > 774 |       await userEvent.hover(test);
          |       ^
      775 |
      776 |       let tooltip = null;
      777 |

      at printWarning (node_modules/react-dom/cjs/react-dom.development.js:67:30)
      at error (node_modules/react-dom/cjs/react-dom.development.js:43:5)
      at warnIfNotCurrentlyActingUpdatesInDEV (node_modules/react-dom/cjs/react-dom.development.js:24064:9)
      at dispatchAction (node_modules/react-dom/cjs/react-dom.development.js:16135:9)
      at Ee (node_modules/react-tooltip/dist/react-tooltip.min.cjs:7:4804)
      at HTMLButtonElement._e (node_modules/react-tooltip/dist/react-tooltip.min.cjs:7:5442)
      at HTMLButtonElement.<anonymous> (node_modules/react-tooltip/dist/react-tooltip.min.cjs:7:1340)
      at HTMLButtonElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLButtonElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLButtonElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLButtonElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
      at node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:47:43
      at Object.eventWrapper (node_modules/@testing-library/dom/dist/config.js:25:23)
      at Object.wrapEvent (node_modules/@testing-library/user-event/dist/cjs/event/wrapEvent.js:29:24)
      at Object.dispatchEvent (node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:47:22)
      at Object.dispatchUIEvent (node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:24:26)
      at node_modules/@testing-library/user-event/dist/cjs/system/pointer/mouse.js:65:50
          at Array.forEach (<anonymous>)
      at Object.enter (node_modules/@testing-library/user-event/dist/cjs/system/pointer/mouse.js:65:27)
      at PointerHost.move (node_modules/@testing-library/user-event/dist/cjs/system/pointer/index.js:53:73)
      at pointerAction (node_modules/@testing-library/user-event/dist/cjs/pointer/index.js:67:39)
      at Object.pointer (node_modules/@testing-library/user-event/dist/cjs/pointer/index.js:35:15)
      at Object.<anonymous> (src/pages/tailwind/campaigns/campaign-table.test.tsx:774:7)
    Tooltip test

    Unable to find role="tooltip"

    Ignored nodes: comments, script, style
    <body>
      <div>
        <button
          data-tooltip-content="Hello World"
          data-tooltip-id="react-tooltip"
        >
          Test
        </button>
      </div>
    </body>

      776 |       let tooltip = null;
      777 |
    > 778 |       await waitFor(() => {
          |                    ^
      779 |         tooltip = screen.getByRole('tooltip');
      780 |         expect(tooltip).toHaveAttribute('style');
      781 |       });

      at waitForWrapper (node_modules/@testing-library/react/node_modules/@testing-library/dom/dist/wait-for.js:166:27)
      at Object.<anonymous> (src/pages/tailwind/campaigns/campaign-table.test.tsx:778:20)

package.json

{
    "@testing-library/react": "12.1.5",
    "@testing-library/user-event": "14.5.1",
    "react-tooltip": "5.21.5"
    "react-scripts": "5.0.1",
}

react-scripts uses jest version 27.5.1

Copy link

This issue is stale because it has not seen activity in 30 days. Remove the stale label or comment within 14 days, or it will be closed.

@github-actions github-actions bot added the Stale This has not seen activity in quite some time label Jan 23, 2024
@gabrieljablonski gabrieljablonski removed the Stale This has not seen activity in quite some time label Jan 23, 2024
@gabrieljablonski
Copy link
Member

gabrieljablonski commented Feb 10, 2024

Working on some test refactoring on #1171. Everything seems to be working now.

For future reference, when testing the tooltip NOT to be on screen, we recommend the following (using @testing-library/react):

await waitFor(() => {
  expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
})

When getting a reference to the tooltip, we recommend this:

const tooltip = await screen.findByRole('tooltip')
expect(tooltip).toHaveAttribute('style')

Waiting for the tooltip to have the react-tooltip__show (or react-tooltip__closing) class is often not necessary, but may be useful when testing both opening and closing the tooltip on the same spec.

await waitFor(() => {
  // also useful with `react-tooltip__closing`
  expect(screen.queryByRole('tooltip')).toHaveClass('react-tooltip__show')
})

Will be closing this for now. Please open a new issue if you have further problems with writing tests for the tooltip. The internal tooltip tests should all pass after #1171 is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants