react-native - 模拟 i18n-js 中的 I18n 类,以便在 React Native 中使用 Expo 进行 Jest 测试

标签 react-native expo ts-jest i18n-js

我尝试对一个组件进行测试,在该组件中我在 React Native 和 Expo 中使用 i18n,但是,我收到一条错误消息 Jest encountered an unexpected token .

Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /<app-dir>/node_modules/i18n-js/dist/import/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){export { I18n } from "./I18n";

对于 i18n,我使用 Expo Localization with i18n-js ,因此我使用 i18n-js。

这是我的实现:

import * as Localization from 'expo-localization';
import { I18n } from 'i18n-js';

import translations from './translations';

const i18n = new I18n(translations);
i18n.locale = Localization.locale.split('-')[0];
i18n.defaultLocale = 'en';
i18n.enableFallback = true;

export default i18n;
export { Localization };

它适用于我的所有组件,但未能通过我导入此模块的组件的测试,例如:

import i18n from '../../../i18n'; 然后使用 i18n

<Text>{i18n.t('keyOfTranslation')}</Text>


我尝试 mock i18n-js模块使用:

jest.config.ts

moduleNameMapper: {
    'i18n-jss': '<rootDir>/src/__mocks__/i18n-jsMocked.ts'
  }

i18n-jsMocked.ts

import * as origininalI18n from 'i18n-js';
const mocked = origininalI18n as jest.Mocked<typeof origininalI18n>;
export const I18n = mocked.I18n;

beforeEach(() => {
  I18n.mockClear();
});

const i18nMocked = jest.mock('i18n-js', () => {
  return {
    I18n
  };
});

export default i18nMocked;

和其他解决方案,但后来我总是从初始化 I18n 类( const i18n = new I18n(translations) )中收到错误:

● Test suite failed to run

    TypeError: _i18nJs.I18n is not a constructor

      4 | import translations from './translations';
      5 |
    > 6 | const i18n = new I18n(translations);
        |              ^
      7 | i18n.locale = Localization.locale.split('-')[0];
      8 | i18n.defaultLocale = 'en';
      9 | i18n.enableFallback = true;

      at Object.<anonymous> (src/i18n/index.ts:6:14)
      at Object.<anonymous> (src/components/otherFolder/MyComponent/index.tsx:17:1)

如何解决?

最佳答案

为了解决这个问题,我这样做:

jest.config.ts

import { Config } from '@jest/types';

const config: Config.InitialOptions = {
  preset: 'jest-expo',
  setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
  transformIgnorePatterns: [
    'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)'
  ],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
  setupFiles: ['<rootDir>/src/__mocks__/jest.setup.ts'], <-- add this
};

export default config;

在我的 src 文件夹下,我创建了一个 __mocks__ 文件夹,并在其下创建了一个名为 jest.setup.ts 的文件。

后来我使用此实现创建了文件 i18n-js.tsreact-i18next.ts:

i18n-js.ts

jest.mock('i18n-js', () => ({
  I18n: () => {
    return {
      t: jest.fn((str: string) => str)
    };
  }
}));

react-i18next.ts

import { useTranslation } from 'react-i18next';

jest.mock('react-i18next', () => ({
  useTranslation: jest.fn()
}));

const tSpy = jest.fn((str) => str);
const useTranslationSpy: any = useTranslation;

useTranslationSpy.mockReturnValue({
  t: tSpy,
  i18n: {
    changeLanguage: () => new Promise(() => {})
  }
});

最后,将这些文件导入到 jest.setup.ts 文件中:

import './i18n-js';
import './react-i18next';

关于react-native - 模拟 i18n-js 中的 I18n 类,以便在 React Native 中使用 Expo 进行 Jest 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73721630/

相关文章:

reactjs - 如何使用react-native-camera捕获的图像

javascript - React中子元素的条件渲染

react-native - 平面列表中的文本离开屏幕 react native

android - 使用 websocket 的 Expo v27/v28 Android 应用程序崩溃

typescript - 由于 s3key 哈希值更改,为 AWS CDK 编写的单元测试失败

angular - 如何在 Angular 组件的单元测试中提供 ControlContainer?

webview - react native 清除 webview 历史记录

react-native - 'uri.match' 未定义试图将音频文件插入视频源

ios - 无法打开,因为您没有查看权限 - React Native - Expo?

javascript - 错误: Uncaught [TypeError: Cannot read property 'x' of undefined Jest react testing