next.js: Cannot test outside of a Page on Next v9.5.0 (Enzyme + Jest)

Bug report

Describe the bug

As of Next v9.5.0, Components which use the <Link> component cannot be tested in isolation. However, Pages which use <Link> can be tested fine.

To Reproduce

With this component:

// file: components/commonLink.tsx
import Link from "next/link";

export default function CommonLink() {
  return (
    <>
      <Link href="/other/page">
        <a>Click Me!</a>
      </Link>
    </>
  );
}

And this Test

// file: __tests__/components/commonLink.tsx
import { mount } from "enzyme";
import Component from "../../components/commonLink";

describe("navigation", () => {
  let wrapper;

  beforeEach(() => {
    wrapper = mount(<Component />);
  });

  afterEach(() => {
    wrapper.unmount();
  });

  test("renders", async () => {
    const html = wrapper.html();
    expect(html).toContain('href="/other/page">Click Me</a>');
  });
});

Produce the error:

    Error: Uncaught [TypeError: Cannot read property 'pathname' of null]
        at reportException (/Users/evan/workspace/grouparoo/grouparoo/core/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:62:24)
        at innerInvokeEventListeners (/Users/evan/workspace/grouparoo/grouparoo/core/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:333:9)
        at invokeEventListeners (/Users/evan/workspace/grouparoo/grouparoo/core/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)

...

        at Link (/Users/evan/workspace/grouparoo/grouparoo/core/node_modules/next/client/link.tsx:176:14)

...


    The above error occurred in the <Link> component:
        in Link (at commonLink.tsx:6)
        in CommonLink (created by WrapperComponent)
        in WrapperComponent

    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

      at logCapturedError (../node_modules/react-dom/cjs/react-dom.development.js:19527:21)
      at logError (../node_modules/react-dom/cjs/react-dom.development.js:19564:5)
      at update.callback (../node_modules/react-dom/cjs/react-dom.development.js:20708:5)
...

Expected behavior

The test should pass

In older versions of Next.js, this test passed.

Screenshots

N/A

System information

  • OS: OSX
  • Browser N/A
  • Version of Next.js: v9.5.0
  • Version of Node.js: v12, v14

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 27
  • Comments: 17 (10 by maintainers)

Commits related to this issue

Most upvoted comments

This was just fixed in 9.5.1, please upgrade!

This is also an issue when using Storybook (or similar) to render components outside the page context.

Right now i’ve fixed it by creating a custom <RouterContext.Provider> to wrap the tests/stories.

.storybook/preview.js

import React from 'react'
import { addDecorator } from '@storybook/react'
import { linkTo } from '@storybook/addon-links'
import { RouterContext } from 'next/dist/next-server/lib/router-context'
import { startCase } from 'lodash'

addDecorator((storyFn) => (
  <RouterContext.Provider
    value={{
      pathname: '/',
      basePath: '',
      push: (url, as) => {
        if (as) linkTo('Routes', as !== '/' ? startCase(as) : 'Index')()
        return Promise.resolve(true)
      },
      replace: (url, as) => {
        if (as) linkTo('Routes', as !== '/' ? startCase(as) : 'Index')()
        return Promise.resolve(true)
      },
      reload: () => {},
      prefetch: () => {},
    }}
  >
    {storyFn()}
  </RouterContext.Provider>
))

For Testing Library I had to start using a custom render method, that wraps the application with the <RouterContext>.

Ran into this as well. My (hopefully temporary) workaround was to add a Jest module mock for next/link (__mocks__/next/link.js) that returns a plain <a>.

It works fine in v9.4.5-canary.28. But this issue happen from v9.4.5-canary.29 to v9.5.0. So I checked out v9.4.5-canary.29 change log, I think one of the commit below is causing a problem.

  • Fix basepath browser back/forward issue: #14861
  • BasePath: Resolve links against router pathname instead of window.location: #14804