Testing next.js title using next/head with jest and react-testing-library giving false positives
Asked Answered
J

2

9

I have started using Next.js in my newest project and I would like to implement some tests for the pages. I have created a _document file where I set up all of the meta tags which I want to use, including the title of the page.

<html>
<InlineStylesHead />

<body>
    <Main />
    <NextScript />

    <Head>
     <title>testing title</title>
    </Head>
</body>

</html>

then I set my test to render this page(which should include this _document as a part of it)

It's working as expected(including SSR).

So then I have tried to test it using react-testing-library and jest

here is my test:

it('should render the title', () => {
      render(<Page />);
      waitFor(() => {
          expect(document.title).toEqual('test title');
      });
});

Unfortunately, it's giving me false positives, and expect block is giving true no matter what. I have also tried to set the Head directly on the page, unfortunately, the same issue.

Have you used any other technique to test this kind of things? thanks!

Jazzman answered 9/6, 2020 at 7:46 Comment(0)
F
3

expect doesn't give true, it's just ignored in the test. waitFor is asynchronous due to its nature and should be awaited in order to affect test result.

It should be:

it('should render the title', async () => {
      ...
      await waitFor(() => {
          expect(document.title).toEqual('test title');
      });
});
Fluvial answered 9/6, 2020 at 9:43 Comment(7)
the problem comes, that I am either getting false positives(just try to replace 'test title' with any other, it will give you false positive), or it shows:Jazzman
received value must be an HTMLElement or an SVGElement. Received has type: string Received has value: ""Jazzman
Do you have false positives with await waitFor? In OP it's not really false positive, the assertion just happens outside the test (it likely would show uncaught exception if test run were long enough). I'm not sure why received value must be an HTMLElement or an SVGElement can happen here. toEqual shouldn't cause this error, unless it was modified. Please, provide stackoverflow.com/help/mcve that can reproduce the problem. Try repl.it/languages/jestFluvial
just created a repl.it test ;)Jazzman
repl.it/repls/MassiveAnimatedProprietarysoftware#index.spec.jsJazzman
hey @Estus Flask , do you mind to have another look at this repl.it example? :)Jazzman
It doesn't show the error you mentioned, it's more meaningful, Expected: "dsaijijdaijda" Received: "". It makes sense because you try to change a title in _documents but render only Page. I'm not sure if it's a good idea to test Next with react-testing-library after all. It's supposed to test real behaviour but you'll be able to test components only partially without Next-specific things . Also notice that a title in _documents is mistake, github.com/vercel/next.js/blob/master/errors/…. You likely need to test _apps instead and mock Head component with jest.mock.Fluvial
L
3

You could mock next/head to make it render its children:

jest.mock('next/head', () => {
  return {
    __esModule: true,
    default: ({ children }: { children: Array<React.ReactElement> }) => {
      return <>{children}</>;
    },
  };
});

I got the solution from here: https://github.com/vercel/next.js/discussions/11060#discussioncomment-33628

Lattice answered 11/11, 2022 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.