我试图在React Native with 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本地化与i18njs一起使用,因此我使用i18nJS。
这是我的实现:
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>
我尝试使用模拟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.ts
和react-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';