2

I'm try to do a testing for a component where I use i18n in React Native with Expo but, I'm getting an error that say 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";

For the i18n, I use Expo Localization with i18n-js, and for that reason I use i18n-js.

this is my implementation:

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 };

And it works in all my components, but failt the test of the components where I import this module, ex:

import i18n from '../../../i18n'; and later using the i18n

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


I try to mock the i18n-js module using:

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;

and other solutions, but later I always get the error from the initialise I18n Class (const i18n = new I18n(translations)) with the error:

● 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)

How Can I solve it?

Fabian Montoya
  • 407
  • 4
  • 19

1 Answers1

2

For solve it I do this:

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;

Under my src folder I created a __mocks__ folder and under it, I created a file call jest.setup.ts.

Later I created the files i18n-js.ts and react-i18next.ts with this implementations:

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(() => {})
  }
});

And in the end, import that files into the jest.setup.ts file:

import './i18n-js';
import './react-i18next';
Fabian Montoya
  • 407
  • 4
  • 19