首页 > 解决方案 > 如何模拟 loadable.lib 以使库在某些单元测试中同步加载?

问题描述

我们现在对大约 20 个用于同步loadable.lib加载 npm 模块的新文件使用延迟加载。react-toastify更改正在草稿 PR 中等待,但似乎单元测试已损坏,因为它们不等待loadable.lib-passed 模块被加载。

预期成绩

能够模拟loadable.lib,使其与以前完全一样工作,但同步加载给定的库,并且在单元测试中,这被视为loadable.lib结果组件的子级可以访问该库,并且第一次渲染成功完成。

实际结果

旧快照(充满标签和嵌套的东西和道具)和新快照 ( null) 不匹配。这些不起作用:

// TODO: not working because loadable is used in many places
// and children are not always enough to render to avoid crashes,
// and even just with children there can be crashes
jest.mock('@loadable/component', (loadfn) => ({
  lib: jest.fn(() => {
    return { toast: {} };
  }),
}));

如果可以模拟loadable.lib函数以呈现其子函数而不是等待加载某个库,我不知道如何填充代码使用的未定义变量,因为我有使用可加载的可加载的可加载的,使用可加载的等等上。

我读过有一些 WebPack 提示,例如webpackPrefetchandwebpackPreload但我不确定这是否是一条好路。

我尝试过的相关链接

  1. 我正在处理的代码(还有 19 个类似的其他文件):https://github.com/silviubogan/volto/blob/1d015c145e562565ecfa058629ae3d7a9f3e39e4/src/components/manage/Actions/Actions.jsx(我目前正在工作总是react-toastify通过加载loadable.lib。)

  2. https://medium.com/pixel-and-ink/testing-loadable-components-with-jest-97bfeaa6da0b - 我尝试做类似该文章中的代码的事情,但它不起作用:

jest.mock('@loadable/component', async (loadfn) => {
   const val = await loadfn();
   return {
     lib: () => val,
   };
});

一点点代码

取自上面的链接,这是我目前使用 react-toastify (命名LoadableToast)的方式:

/**
 * Render method.
 * @method render
 * @returns {string} Markup for the component.
 */
render() {
  return (
    <LoadableToast>
      {({ default: toast }) => {
        this.toast = toast;

        return (
          <Dropdown
            item
            id="toolbar-actions"

结论

换句话说,我如何模拟动态导入?如何让 jest 跳过延迟加载并提供一个值,而不是让测试等待接收一个值?

谢谢!

更新 1

使用以下新代码,仍然无法正常工作:

jest.mock('@loadable/component', (load) => {
  return {
    lib: () => {
      let Component;
      const loadPromise = load().then((val) => (Component = val.default));
      const Loadable = (props) => {
        if (!Component) {
          throw new Error(
            'Bundle split module not loaded yet, ensure you beforeAll(() => MyLazyComponent.load()) in your test, import statement: ' +
              load.toString(),
          );
        }
        return <Component {...props} />;
      };
      Loadable.load = () => loadPromise;
      return Loadable;
    },
  };
});

标签: javascriptreactjsunit-testingwebpackrazzle

解决方案


我们做到了

jest.mock('@loadable/component', () => ({
    lib: () => {
        const MegadraftEditor = () => {} // Name of your import
        return ({ children }) => children({ default: { MegadraftEditor } })
    },
}))

如果只有一个默认导出,也可以是

jest.mock('@loadable/component', () => ({
lib: () => {
    const HotTable = () => {} // Name of your import
    return ({ children }) => children({ default: HotTable })
},
}))

然后在测试中,您只需要潜水()并使用 childAt(),直到您拥有要延迟加载的组件的正确位置。请注意,这将不会让您的任何包装器围绕快照中的延迟加载组件。

it('renders correct', () => {
    const component = shallow(
        <View
            data={}
        />
    )
        .dive()
        .childAt(0)
        .dive()

    expect(component).toMatchSnapshot()
})


推荐阅读