Babel.js 如何对Next.js动态组件进行单元测试?

ws51t4hk  于 2022-12-08  发布在  Babel
关注(0)|答案(6)|浏览(202)

Next.jsdynamic()HOC组件并不是很容易测试。

  • 第一个jest无法正确编译动态导入(require.resolveWeak is not a function-似乎是由下一个babel插件添加的)
  • 第二,我不能很好地覆盖modules逻辑;看起来像是在尝试呈现动态组件时没有运行。
kpbwa7wx

kpbwa7wx1#

让我们假设我们有一个这样的组件(使用动态导入):

import dynamic from 'next/dynamic';

const ReactSelectNoSSR = dynamic(() => import('../components/select'), {
    loading: () => <Input />,
    ssr: false
});

export default () => (
    <>
        <Header />
        <ReactSelectNoSSR />
        <Footer />
    </>
);

Next.js提供的动态导入支持并没有公开在Jest环境中预加载动态导入组件的方法。然而,由于jest-next-dynamic,我们可以呈现完整的组件树,而不是加载占位符。
您需要将babel-plugin-dynamic-import-node添加到.babelrc中,如下所示。

{
  "plugins": ["babel-plugin-dynamic-import-node"]
}

然后,您可以使用preloadAll()来呈现组件,而不是加载占位符。

import preloadAll from 'jest-next-dynamic';
import ReactSelect from './select';

beforeAll(async () => {
    await preloadAll();
});

📝 Source

2nbm6dog

2nbm6dog2#

您可以将以下内容添加到Jest设置示例中:setupTests.ts

jest.mock('next/dynamic', () => () => {
    const DynamicComponent = () => null;
    DynamicComponent.displayName = 'LoadableComponent';
    DynamicComponent.preload = jest.fn();
    return DynamicComponent;
});
ctehm74n

ctehm74n3#

下面将加载所需的组件。您也可以使用类似的方法预先加载所有组件。

jest.mock('next/dynamic', () => ({
  __esModule: true,
  default: (...props) => {
    const dynamicModule = jest.requireActual('next/dynamic');
    const dynamicActualComp = dynamicModule.default;
    const RequiredComponent = dynamicActualComp(props[0]);
    RequiredComponent.preload
      ? RequiredComponent.preload()
      : RequiredComponent.render.preload();
    return RequiredComponent;
  },
}));
hm2xizp9

hm2xizp94#

虽然这是一个很笨拙的解决方案,但我所做的只是通过提取导入路径并返回该导入来模拟next/dynamic

jest.mock('next/dynamic', () => ({
  __esModule: true,
  default: (...props) => {
    const matchedPath = /(.)*(\'(.*)\')(.)*/.exec(props[0].toString());
    if (matchedPath) return require(matchedPath[3]);
    else return () => <></>;
  },
}));
q0qdq0h2

q0qdq0h25#

下面是一个简单的修复方法:

  • 不需要任何第三方库
  • 仍呈现动态组件(例如,快照将起作用)
    解决方案:

1.通过在__mocks__/next/dynamic.js Jest docs中创建一个模拟文件来模拟next/dynamic模块
1.复制并粘贴以下代码:

const dynamic = (func) => {
    const functionString = func.toString()
    const modulePath = functionString.match(/"(.*?)"/)[1]

    const namedExport = functionString.match(/mod\.(.+?(?=\)))/)
    const componentName = namedExport ? namedExport[1] : 'default'

    return require(modulePath)[componentName]
}

export default dynamic

1.上面的代码假定您使用defaultnamed exportsdynamic()函数,如Next.js docs中所述。即:

// default
const DynamicHeader = dynamic(() =>
  import('../components/header')
)

// named export
const DynamicComponent = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
)

就是这样!现在动态导入应该可以在所有的测试套件中工作了:)

uemypmqf

uemypmqf6#

如果您遇到的是Next8的第一个问题,您可以使用以下代码模拟动态导入:

jest.mock('next-server/dynamic', () => () => 'Dynamic');

有关参考,请参见:
https://spectrum.chat/next-js/general/with-jest-and-dynamic-imports-broken~25905aad-901e-41d8-ab3e-9f97eeb51610?m=MTU1MzA5MTU2NjI0Nw==
https://github.com/zeit/next.js/issues/6187#issuecomment-467134205

相关问题