vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.78k stars 26.95k forks source link

Jest tests failing when testing components with dynamic import in Next 10.2.0 #24566

Closed bcomnes closed 3 years ago

bcomnes commented 3 years ago

What version of Next.js are you using?

10.2.0

What version of Node.js are you using?

14

What browser are you using?

N/A (but JSDOM in the test runner)

What operating system are you using?

macos linux

How are you deploying your application?

Pre deploy failure

Describe the Bug

I'm still putting together a minimal reproduction case (will post shortly), but(added) My jest tests that test rendering of components that make use of next/dynamic began failing on next 10.2.0.

The error:

project % npx jest components/header/header.test.jsx
 FAIL  components/header/header.test.jsx
  ● Test suite failed to run

    /project/components/header/header.jsx: The "from" argument must be of type string. Received undefined

      at Import (node_modules/next/build/babel/plugins/react-loadable-plugin.ts:154:21)
      at NodePath._call (node_modules/@babel/traverse/lib/path/context.js:55:20)
      at NodePath.call (node_modules/@babel/traverse/lib/path/context.js:42:17)
      at NodePath.visit (node_modules/@babel/traverse/lib/path/context.js:92:31)
      at TraversalContext.visitQueue (node_modules/@babel/traverse/lib/context.js:116:16)
      at TraversalContext.visitSingle (node_modules/@babel/traverse/lib/context.js:85:19)
      at TraversalContext.visit (node_modules/@babel/traverse/lib/context.js:144:19)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        2.54 s
Ran all test suites matching /components\/header\/header.test.jsx/i.

The simplified component in question:

import dynamic from 'next/dynamic'

const SomeDynamicComp = dynamic(() =>
  import('./some-dynamic-comp').then((mod) => mod.SomeDynamicComp),
{ ssr: false })

export function SomeComp () {
  return (
    <div>
      Hello world
      <SomeDynamicComp />
    </div>
    )
}

This is the code that causes the test to fail with the above error:

const SomeDynamicComp = dynamic(() =>
  import('./some-dynamic-comp').then((mod) => mod.SomeDynamicComp),
{ ssr: false })

The test that fails:

import React from 'react'
import { render } from '@testing-library/react'

import { SomeComp } from './some-comp'

it('renders without error', () => {
  render(<SomeComp />)
})

When those were removed, the tests passed again on 10.2.0. Leaving them in and pinning next to 10.1.3, things worked again.

Expected Behavior

That I can test react components in jest that utilize next/dynamic.

To Reproduce

Reproducible gist incoming. I need to extract out a simplified example. Hang tight.

Failing example: https://github.com/ballpit/dynamic-10.2-bug/tree/master/components Passing workaround: https://github.com/ballpit/dynamic-10.2-bug/compare/workaround

To run, just clone and run npm run test. Jest is configured to use the following babel config:

{
  "presets": ["next/babel"],
  "plugins": []
}
bcomnes commented 3 years ago

Possibly related to https://github.com/vercel/next.js/pull/24281 ?

bcomnes commented 3 years ago

Ok added a reproducible example:

Failing example: https://github.com/ballpit/dynamic-10.2-bug/tree/master/components Passing workaround: https://github.com/ballpit/dynamic-10.2-bug/compare/workaround

To run, just clone and run npm run test. Jest is configured to use the following babel config:

{
  "presets": ["next/babel"],
  "plugins": []
}
stscoundrel commented 3 years ago

Suffering from same issue. jest-next-dynamic also stopped working with 10.2 update. Workarounds other than downgrading Next.js to 10.1.3 would be appreciated.

pedroct92 commented 3 years ago

We have just updated our project and stated to experience the same issue!

Indeed, it seems related to #24281

We are also using jest-next-dynamic which has an issue open too but it seems the issue is directly here.

It would be nice if we could provide a better API for testing and have the behaviour of jest-next-dynamic directly from nextjs.

Let me know if we could help in any way.

maccman commented 3 years ago

Experiencing this issue too.

travisbloom commented 3 years ago

Having the same errors from the same line in react-loadable-plugin when trying to run storybook with next@10.2.

sct commented 3 years ago

Nearly the same issue when using extract-react-intl-messages. Breaks on any file with dynamic imports.

TypeError: /src/components/LanguageSelector/index.tsx: Cannot read property 'pagesDir' of undefined
    at Import (/node_modules/next/dist/build/babel/plugins/react-loadable-plugin.js:25:864)
    at NodePath._call (/node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:55:20)
    at NodePath.call (/node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:42:17)
    at NodePath.visit (/node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:92:31)
    at TraversalContext.visitQueue (/node_modules/@babel/core/node_modules/@babel/traverse/lib/context.js:115:16)
    at TraversalContext.visitSingle (/node_modules/@babel/core/node_modules/@babel/traverse/lib/context.js:84:19)
    at TraversalContext.visit (/node_modules/@babel/core/node_modules/@babel/traverse/lib/context.js:143:19)
    at Function.traverse.node (/node_modules/@babel/core/node_modules/@babel/traverse/lib/index.js:82:17)
    at NodePath.visit (/node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:99:18)
    at TraversalContext.visitQueue (/node_modules/@babel/core/node_modules/@babel/traverse/lib/context.js:115:16)
bcomnes commented 3 years ago

Looks like a fix is being developed in https://github.com/vercel/next.js/pull/24751

Thanks you maintainers!

luiznasciment0 commented 3 years ago

I'm experiencing this same issue just after update Next.js version to 10.2 and webpack from 4 to 5.

Component:

import dynamic from 'next/dynamic'
import { Icons, IconProps } from './Icon'

export type TIcon = Icons

export const Icon = dynamic<IconProps>(() => import('./Icon'), {
  ssr: false,
})

Jest error:

Test suite failed to run

    /Users/c84794a/Documents/workspace/ecs-web-authorization-front/main/app/components/Icon/index.tsx: The "from" argument must be of type string. Received undefined

      at Import (node_modules/next/build/babel/plugins/react-loadable-plugin.ts:154:21)
      at NodePath._call (node_modules/@babel/traverse/lib/path/context.js:55:20)
      at NodePath.call (node_modules/@babel/traverse/lib/path/context.js:42:17)
      at NodePath.visit (node_modules/@babel/traverse/lib/path/context.js:92:31)
      at TraversalContext.visitQueue (node_modules/@babel/traverse/lib/context.js:116:16)
      at TraversalContext.visitSingle (node_modules/@babel/traverse/lib/context.js:85:19)
      at TraversalContext.visit (node_modules/@babel/traverse/lib/context.js:144:19)
      at Function.traverse.node (node_modules/@babel/traverse/lib/index.js:82:17)
omariosouto commented 3 years ago

Hi, for now I'm doing this:

####### jest.setup.js

jest.isolateModules(() => {
  const preloadAll = require('jest-next-dynamic');
  beforeAll(async () => {
    await preloadAll();
  });
});

And always using ssr false:

const ResponsiveImages = dynamic(import('components/ResponsiveImage/ResponsiveImages'), { ssr: false });

Maybe it could help you @bcomnes

bcomnes commented 3 years ago

Cool thank you for the workaround @omariosouto! I will try that.

bcomnes commented 3 years ago

Hi, for now I'm doing this:

I tried it out, however this did not solve the problem for me, same error. I had to add the following line to my jest config file to enable a setup file:

setupFilesAfterEnv: ['./jest.setup.js']

And even added the additional babel plugin they recommend:

"plugins": ["babel-plugin-dynamic-import-node"]
luiznasciment0 commented 3 years ago

unfortunately it did not solve the problem for me too :( still waiting for a solution I'll have to skip tests until the problem is solved, if it takes too long I'll have to downgrade versions

correttojs commented 3 years ago

it seems the next/dist/build/babel/plugins/react-loadable-plugin.js is causing the issue. I created a separate babel test config which doesn't include the next/babel preset

luiznasciment0 commented 3 years ago

is it possible to overwrite this plugin version? at least until a proper solution is provided

I really don’t want to downgrade next version haha

luiznasciment0 commented 3 years ago

@correttojs can you share your configs, please?

correttojs commented 3 years ago
module.exports = (api) => {
    const isTest = api.env('test');
    api.cache(true);
    if (isTest) {
        return {
            presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],

            env: {
                test: {
                    presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
                },
            },
        };
    }

    return {
        presets: ['next/babel'],
    };
}
bcomnes commented 3 years ago

module.exports = (api) => { const isTest = api.env('test'); api.cache(true); if (isTest) { return { presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],

        env: {
            test: {
                presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
            },
        },
    };
}

return {
    presets: ['next/babel'],
};

}

Great! This workaround worked for me. For a project not using typescript, but using styled-jsx, this is what my config looks like:

// .babelrc.js
module.exports = (api) => {
  const isTest = api.env('test')
  api.cache(true)

  // remove this part when https://github.com/vercel/next.js/issues/24566 is closed
  if (isTest) {
    return {
      presets: ['@babel/preset-env', '@babel/preset-react'],
      plugins: ['styled-jsx/babel'],
      env: {
        test: {
          presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
        }
      }
    }
  }

  return {
    presets: ['next/babel']
  }
}

This appears to be a valid work around until https://github.com/vercel/next.js/pull/24751 is landed.

klapec commented 3 years ago

I can confirm that this workaround works well. The only think I had to adjust was to extend the @babel/preset-react with a runtime: automatic option, otherwise jest would fail on ReferenceError: React is not defined error.

[
  "@babel/preset-react",
  {
    "runtime": "automatic"
  }
]
binary64 commented 3 years ago

Not sure if completely related but in next@10.2 I get this (it worked fine in next@10.0)

 FAIL  src/lib/show-more/ShowMore.spec.tsx
  ● Test suite failed to run

    /home/user/Code/monorepo/libs/ui/src/lib/myform/SettingElementTextBlock.tsx: The "from" argument must be of type string. Received undefined

      at Import (../../node_modules/next/build/babel/plugins/react-loadable-plugin.ts:154:21)
      at NodePath._call (../../node_modules/@babel/traverse/lib/path/context.js:55:20)
      at NodePath.call (../../node_modules/@babel/traverse/lib/path/context.js:42:17)
      at NodePath.visit (../../node_modules/@babel/traverse/lib/path/context.js:92:31)
      at TraversalContext.visitQueue (../../node_modules/@babel/traverse/lib/context.js:116:16)
      at TraversalContext.visitSingle (../../node_modules/@babel/traverse/lib/context.js:85:19)
      at TraversalContext.visit (../../node_modules/@babel/traverse/lib/context.js:144:19)
      at Function.traverse.node (../../node_modules/@babel/traverse/lib/index.js:82:17)

my .babelrc.js is just

module.exports = {
  presets: [['next/babel']]
}
bcomnes commented 3 years ago

Not sure if completely related but in next@10.2 I get this (it worked fine in next@10.0)

Yup, thats the exact error if that component has a dynamic import in it.

bcomnes commented 3 years ago

Just to follow up because people have asked me about this, after https://github.com/vercel/next.js/pull/24751 was landed, I was able to revert back to a simple .babelrc

{
  "presets": ["next/babel"],
  "plugins": []
}

and everything worked fine.

balazsorban44 commented 2 years ago

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.