Umi: plugin-locale imports not working in tests

Created on 2 Apr 2020  ·  4Comments  ·  Source: umijs/umi

What happens?

Imports from plugin-locale are not available when running unit tests. In my case, I'm importing getIntl from umi in a utils.ts file (not a react component).
The import works when I run or build the app, but fails when running tests. It shows the following error.

TypeError: (0 , _umi.getIntl) is not a function

Mini Showcase Repository (REQUIRED)

https://github.com/khalibloo/umi-intl-bug

How To Reproduce

Steps to reproduce the behavior:

  1. Import getIntl and use it in a simple function
  2. Write a test for the function and run the test

Expected behavior

  1. The import should work in the test environment

Example

// utils.ts
import { getIntl } from "umi";

export const formatPrice = (currency: string, amount: number) => {
  const intl = getIntl();
  return intl.formatNumber(amount, {
    style: "currency",
    currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
};
// utils.test.ts
import { formatPrice } from "./utils";

describe("formatPrice tests", () => {
  test("(USD, 30) should return $30.00", () => {
    expect(formatPrice("USD", 30)).toEqual("$30.00");
  });
});

Context

  • Umi Version: 3.0.16
  • Node Version: 12.13.0
  • Platform: Windows 10 x64
type(enhancement)

Most helpful comment

可以通过手动初始化国际化语言包,在测试的Reac组件外包裹 _LocaleContainer 组件,从而在 umi 实现组件级单元测试:

以下实例基于 [email protected] 版本测试验证:

jest.config.js

module.exports = {
  // ...
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@@/(.*)$': '<rootDir>/src/.umi/$1',
  },
};

src/pages/404.tsx

import React from 'react';
import { history, useIntl } from 'umi';
import { Button, Result } from 'antd';

const NoFoundPage = props => {
  const { formatMessage } = useIntl();
  return (
    <Result
      status="404"
      title="404"
      subTitle={formatMessage({ id: 'component.404.text' })}
      extra={
        <Button type="primary" onClick={() => history.push('/')}>
          {formatMessage({ id: 'component.404.button' })}
        </Button>
      }
    />
  );
};

export default NoFoundPage;

src/pages/404.test.tsx

import React from 'react';
import TestRenderer from 'react-test-renderer';
import { setIntl } from '@@/plugin-locale/localeExports';
import { _LocaleContainer as LocaleContainer } from '@@/plugin-locale/locale';
import NoFoundPage from './404';

describe('NoFoundPage Component Test', () => {
  beforeAll(() => {
    setIntl('zh-CN');
  });

  it('NoFoundPage render ok', () => {
    const testRenderer = TestRenderer.create(
      <LocaleContainer>
        <NoFoundPage />
      </LocaleContainer>,
    );
    expect(testRenderer.toJSON()).toMatchSnapshot();
  });
});

测试结果如下:

$ npm run test -- src/pages/404.test.tsx

> [email protected] test pcmgr-client
> umi test "src/pages/404.test.tsx"

 PASS  src/pages/404.test.tsx (8.675s)
  NoFoundPage Component Test
    √ NoFoundPage render ok (29ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        10.127s, estimated 65s
Ran all test suites matching /src\\pages\\404.test.tsx/i.

All 4 comments

Same problem. Any ideas?

后面找到解决方法,umi 依赖于浏览器运行时和其他状态,所以单元测试里不能生效。

Since umi getIntl library rely on browser runtime and other state, using it with unit testing would possibly cause problem and crash.

可以通过手动初始化国际化语言包,在测试的Reac组件外包裹 _LocaleContainer 组件,从而在 umi 实现组件级单元测试:

以下实例基于 [email protected] 版本测试验证:

jest.config.js

module.exports = {
  // ...
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@@/(.*)$': '<rootDir>/src/.umi/$1',
  },
};

src/pages/404.tsx

import React from 'react';
import { history, useIntl } from 'umi';
import { Button, Result } from 'antd';

const NoFoundPage = props => {
  const { formatMessage } = useIntl();
  return (
    <Result
      status="404"
      title="404"
      subTitle={formatMessage({ id: 'component.404.text' })}
      extra={
        <Button type="primary" onClick={() => history.push('/')}>
          {formatMessage({ id: 'component.404.button' })}
        </Button>
      }
    />
  );
};

export default NoFoundPage;

src/pages/404.test.tsx

import React from 'react';
import TestRenderer from 'react-test-renderer';
import { setIntl } from '@@/plugin-locale/localeExports';
import { _LocaleContainer as LocaleContainer } from '@@/plugin-locale/locale';
import NoFoundPage from './404';

describe('NoFoundPage Component Test', () => {
  beforeAll(() => {
    setIntl('zh-CN');
  });

  it('NoFoundPage render ok', () => {
    const testRenderer = TestRenderer.create(
      <LocaleContainer>
        <NoFoundPage />
      </LocaleContainer>,
    );
    expect(testRenderer.toJSON()).toMatchSnapshot();
  });
});

测试结果如下:

$ npm run test -- src/pages/404.test.tsx

> [email protected] test pcmgr-client
> umi test "src/pages/404.test.tsx"

 PASS  src/pages/404.test.tsx (8.675s)
  NoFoundPage Component Test
    √ NoFoundPage render ok (29ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        10.127s, estimated 65s
Ran all test suites matching /src\\pages\\404.test.tsx/i.

后面找到解决方法,umi 依赖于浏览器运行时和其他状态,所以单元测试里不能生效。

Since umi getIntl library rely on browser runtime and other state, using it with unit testing would possibly cause problem and crash.

請問解決方法是什麼呢?

Was this page helpful?
0 / 5 - 0 ratings