首页 > 解决方案 > TypeError:intlProvider.getChildContext 不是函数

问题描述

我在我的反应功能组件中使用 injectIntl​​ 来实现本地化。我正在使用酶/玩笑进行单元测试。我复制了 intl-test-helper 文件,但出现错误:“TypeError: intlProvider.getChildContext is not a function”

我已经尝试过来自 stackflow 的其他建议: 1. 删除模拟文件 --- 我没有模拟文件 2. 使用 const { IntlProvider } = jest.requireActual("react-intl"); 强制它使用实际的,而不是模拟的——不工作。

反应组件是:WarningModal.jsx:

import { FormattedMessage, injectIntl } from "react-intl";
.......

const WarningModal = ({
  .........
  ...props
}) => {
  ........

export default injectIntl(WarningModal);

intlTestHelper.js 文件是:

 * Components using the react-intl module require access to the intl context.
 * This is not available when mounting single components in Enzyme.
 * These helper functions aim to address that and wrap a valid,
 * English-locale intl context around them.
 */

import React from "react";
import { IntlProvider, intlShape } from "react-intl";
import { mount, shallow } from "enzyme"; // eslint-disable-line import/no-extraneous-dependencies

/** Create the IntlProvider to retrieve context for wrapping around. */
function createIntlContext(messages, locale) {
  const { IntlProvider } = jest.requireActual("react-intl");
  const intlProvider = new IntlProvider({ messages, locale }, {});
  const { intl } = intlProvider.getChildContext();
  return intl;
}

/** When using React-Intl `injectIntl` on components, props.intl is required. */
function nodeWithIntlProp(node, messages = {}, locale = "en") {
  return React.cloneElement(node, {
    intl: createIntlContext(messages, locale)
  });
}

/**
 * Create a shadow renderer that wraps a node with Intl provider context.
 * @param {ReactComponent} node - Any React Component
 * @param {Object} context
 * @param {Object} messages - A map with keys (id) and messages (value)
 * @param {string} locale - Locale string
 */
export function shallowWithIntl(
  node,
  { context } = {},
  messages = {},
  locale = "en"
) {
  return shallow(nodeWithIntlProp(node), {
    context: Object.assign({}, context, {
      intl: createIntlContext(messages, locale)
    })
  });
}

/**
 * Mount the node with Intl provider context.
 * @param {Component} node - Any React Component
 * @param {Object} context
 * @param {Object} messages - A map with keys (id) and messages (value)
 * @param {string} locale - Locale string
 */
export function mountWithIntl(
  node,
  { context, childContextTypes } = {},
  messages = {},
  locale = "en"
) {
  return mount(nodeWithIntlProp(node), {
    context: Object.assign({}, context, {
      intl: createIntlContext(messages, locale)
    }),
    childContextTypes: Object.assign({}, { intl: intlShape }, childContextTypes)
  });
}

这里我如何使用它来测试:

import React from "react";
import { _WM as WarningModal } from "../components/WarningModal";
// import { shallow } from "enzyme";
import { mountWithIntl } from "../utils/intlTestHelper.js";

describe("<WarningModal />", () => {
  const props = {
    discardChanges: jest.fn(),
    saveChanges: jest.fn(),
    closeWarningModal: jest.fn(),
    intl: { formatMessage: jest.fn() }
  };

  it("should have heading", () => {
    const wrapper = mountWithIntl(<WarningModal {...props} />);
    expect(wrapper.find(".confirm-title")).toBeTruthy();
  });
});

错误:

 ● <WarningModal /> › should have heading

    TypeError: intlProvider.getChildContext is not a function

      14 |   const { IntlProvider } = jest.requireActual("react-intl");
      15 |   const intlProvider = new IntlProvider({ messages, locale }, {});
    > 16 |   const { intl } = intlProvider.getChildContext();
         |                                 ^
      17 |   return intl;
      18 | }
      19 | 

      at getChildContext (src/utils/intlTestHelper.js:16:33)
      at createIntlContext (src/utils/intlTestHelper.js:23:11)
      at nodeWithIntlProp (src/utils/intlTestHelper.js:60:16)
      at Object.<anonymous> (src/tests/WarningModal.spec.js:29:21)

请照亮这个。谢谢你。

标签: jestjsenzymereact-intl

解决方案


React-Intl已将IntlProvider.getChildContext, 替换为createIntl用于测试目的,同时将 V2 迁移到 V3。

我们已经删除了 IntlProvider.getChildContext 用于测试,现在您可以使用 createIntl 在 React 之外创建一个独立的 intl 对象并将其用于测试目的。有关更多详细信息,请参阅使用 React Intl 进行测试

这是链接

所以这个的工作代码是

要解决此错误,您必须创建自定义浅组件。就像

    import { createIntl } from 'react-intl';

    const LocalLanguage  = {
       french:{},
       arabic:{},
       english:{}
    }
    const lang = getCurrentLanguage('en', LocalLanguage);
    const intl  = createIntl({ locale: 'en', lang }, {});

    export const shallowWithIntl = (node) => {
        return shallow(nodeWithIntlProp(node), { context: { intl } });
    }

如果这没有帮助,那么您可以在帮助文件中定义以下函数。

    const messages = require('./Lang/en.json') // en.json 
    const defaultLocale = 'en'

    const locale = defaultLocale

    export const intl = (component) => {
         return (
             <IntlProvider
                 locale={locale}
                 messages={messages}
             >
                 {React.cloneElement(component)}
             </IntlProvider>
         );
    }

并在您的测试文件中使用它,如下所示

    const wrapper = mount(intl(<MobileRechargeComponent />));

推荐阅读