Next.js: Cannot read property "then" of undefined when testing next/link with @testing-library/react

Created on 13 Sep 2019  路  4Comments  路  Source: vercel/next.js

Bug report

Preamble

Thank you so much for this awesome library and what you do for the community! I would not be here asking this question if I didn't really appreciate what you do! The same goes for the whole testing-library community, if you think I should reach out to them with the issue instead.

What I am trying to achieve

  1. I want to use the Link component in the actual app due to accessibility and performance
  2. I want to test transitions from and to pages

Describe the bug

The click simulation throws an error when using @testing-library/react

To Reproduce

Reproduction available in this code sandbox:

https://codesandbox.io/embed/hello-world-u8r6s

Run npm run test and the error will appear.

Expected behavior

The simulation should work, i.e. one should be navigated to the other page in the test (An alternative would be to suggest a way to simulate that behavior myself).

Screenshots

Screenshot from 2019-09-13 10-05-16

System information

  • OS: Ubuntu 18
  • Version of Next.js: 9.0.6

Most helpful comment

From what I can see, the issue with your test is that you're asking the link to handle the click without a router. Normally the router is created by the client when the page loads, but there's no client since you're just rendering a component in isolation.

For this test, you can setup a mock router to confirm that when the link is clicked that the correct path is pushed. For example:

import Router from 'next/router';
const routerPushed = jest.fn();
const mockedRouter = {
  push: (path) => {
    routerPushed(path);
    return new Promise((resolve, reject) => resolve());
  }
};
Router.router = mockedRouter;

And in your test...

    test("should navigate to the about page", async () => {
      const { getByText, queryByText } = result;
      fireEvent.click(getByText(/about/i));
      expect(routerPushed).toHaveBeenCalledWith('/about')

If you are trying to test page navigation, I think you're going to need a running server. See the client-navigation tests for an example of how navigation is tested.

All 4 comments

From what I can see, the issue with your test is that you're asking the link to handle the click without a router. Normally the router is created by the client when the page loads, but there's no client since you're just rendering a component in isolation.

For this test, you can setup a mock router to confirm that when the link is clicked that the correct path is pushed. For example:

import Router from 'next/router';
const routerPushed = jest.fn();
const mockedRouter = {
  push: (path) => {
    routerPushed(path);
    return new Promise((resolve, reject) => resolve());
  }
};
Router.router = mockedRouter;

And in your test...

    test("should navigate to the about page", async () => {
      const { getByText, queryByText } = result;
      fireEvent.click(getByText(/about/i));
      expect(routerPushed).toHaveBeenCalledWith('/about')

If you are trying to test page navigation, I think you're going to need a running server. See the client-navigation tests for an example of how navigation is tested.

Very, very helpful! :+1:

Thank you for taking the time. I will indeed be using the first way predominately, but it is also nice to know that if I actually needed page navigation it is possible.

I'm still having this issue, even when I followed the above solution it still gave me the error Cannot read property "then" of undefined, is there a reference to testing for the next/link somewhere? I checked the source code and couldn't find any

We are seeing same issue on 9.5.5. mock Router.router push doesn't work

Was this page helpful?
0 / 5 - 0 ratings

Related issues

renatorib picture renatorib  路  3Comments

lixiaoyan picture lixiaoyan  路  3Comments

havefive picture havefive  路  3Comments

rauchg picture rauchg  路  3Comments

olifante picture olifante  路  3Comments