8

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!

devvvyloper
  • 101
  • 1
  • 4

2 Answers2

2

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');
      });
});
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • 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: – devvvyloper Jun 09 '20 at 10:24
  • ```received value must be an HTMLElement or an SVGElement. Received has type: string Received has value: ""``` – devvvyloper Jun 09 '20 at 10:25
  • 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 https://stackoverflow.com/help/mcve that can reproduce the problem. Try https://repl.it/languages/jest – Estus Flask Jun 09 '20 at 10:52
  • just created a repl.it test ;) – devvvyloper Jun 09 '20 at 12:45
  • https://repl.it/repls/MassiveAnimatedProprietarysoftware#index.spec.js – devvvyloper Jun 09 '20 at 12:45
  • hey @Estus Flask , do you mind to have another look at this `repl.it` example? :) – devvvyloper Jun 10 '20 at 08:23
  • 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, https://github.com/vercel/next.js/blob/master/errors/no-document-title.md. You likely need to test _apps instead and mock `Head` component with jest.mock. – Estus Flask Jun 10 '20 at 16:39
1

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

Guilherme Garnier
  • 2,208
  • 23
  • 22