我尝试对一个组件进行测试,在该组件中我在 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.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';
关于react-native - 模拟 i18n-js 中的 I18n 类,以便在 React Native 中使用 Expo 进行 Jest 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73721630/