React-native-i18n: Jest Error Message - TypeError: Cannot read property 'languages' of undefined

Created on 20 Jun 2017  ·  34Comments  ·  Source: AlexanderZaytsev/react-native-i18n

 FAIL  __tests__\index.android.js
  ● Test suite failed to run

    TypeError: Cannot read property 'languages' of undefined

      at Object.<anonymous> (node_modules/react-native-i18n/index.js:7:31)
      at Object.<anonymous> (src/tools.js:8:34)
      at Object.<anonymous> (src/App.js:5:12)

__tests__\index.android.js

import 'react-native';
import React from 'react';
import App from '../src/App';
import renderer from 'react-test-renderer';
it('renders correctly', () => {
    const tree = renderer.create(
        <App />
    );
});

src/tools.js

import I18n from 'react-native-i18n';
import en from '../res/locales/en';
import es from '../res/locales/es';
import zh from '../res/locales/zh';
I18n.fallbacks = true;
I18n.defaultLocale = 'en';
I18n.translations = { en, es, zh };
export function trans(key) {
    return I18n.t(key);
}

Used in code in this format:

import { trans } from './tools.js';
console.log(trans('key.from.json.lang.files'));

Most helpful comment

I just to do like this, it worked. I'm using version v2.0.2:

jest.mock('react-native-i18n', () => {
  return {};
});

All 34 comments

@elliotleelewis What version of this lib are you using?
It just seems that the module is not correctly mocked.

@zoontek v2.0.1

@elliotleelewis Try following this: https://facebook.github.io/jest/docs/tutorial-react-native.html#mock-native-modules-using-jestmock

@zoontek How would I do that? I tried to add this to my test file.

jest.mock('react-native-i18n', () => 'RNI18n');

and now I get this error...

 FAIL  __tests__\index.android.js
  ● Test suite failed to run

    TypeError: _reactNativeI18n2.default.t is not a function

      at trans (src/tools.js:17:34)
      at Object.<anonymous> (src/pages/Search.js:70:88)
      at Object.<anonymous> (src/App.js:6:13)
      at Object.<anonymous> (__tests__/index.android.js:6:171)

I'm experiencing the same issue. My tests started failing after I switched to v2. They worked before, now they fail with

TypeError: Cannot read property 'languages' of undefined

I can't mock i18n since I need real localization in components, and all the snapshots already contain localized data.

I have the same problem with v2.0.2. It worked fine before v2, and I get the same error as @elliotleelewis if I mock the lib with jest.mock().

I just to do like this, it worked. I'm using version v2.0.2:

jest.mock('react-native-i18n', () => {
  return {};
});

any news on this? i have the same problem :(

@jaycee425 Did you tried the @linhnh123 solution?

On 1.x, it worked without mocking the NativeModule because a test was done and a fallback was made with an empty string. It's really not a good solution, because it's harder to detect a non-correctly linked lib :/ ( https://github.com/AlexanderZaytsev/react-native-i18n/blob/c6691e049a4005aea6d082e65692d60fa1aa22ef/index.js )

i just solved...it was my error... it seems that it didnt link properly with react-native link so i just had to link it manually, my bad

@jaycee425 Glad to hear you solved it :)

I also have nonworking react-native link for this package and I linked it manually. It's awful.

@SoundBlaster you need to react-native unlink before updating to 2 and then react-native link. I guess react-native scripts can't figure out changes in native module name.

@SoundBlaster If you upgrade from 1.x to 2.x, you need to unlink before the update and link it again after (folder architecture changes)

Experiencing the same under "react-native": "0.46.2" and react-native unlink react-native-i18n & react-native link react-native-i18n does not work for me. I have tried rm -rf node_modules/react-native-i18n and have wiped library/Developer/Xcode/DerivedData too with no success.

I can confirm the unlink _before_ the bump and the link afterwards doesn't work for me :/

@jaimeagudo react-native unlink/react-native link doesn't work for me either (w/ [email protected])

I use this solution for now :

jest.mock('react-native-i18n', () => {
  const i18njs = require('i18n-js');
  const en = require('../app/i18n/locales/en');
  i18njs.translations = {en}; // Optional ('en' is the default)

  return {
     t: jest.fn((k, o) => i18njs.t(k, o)),
  };
});

Having the same issue - if I find a solution I'll post back. At the moment finding it impossible to mock this out properly.

I did something similar to @yspychala, but with a different library (react-native-doc-viewer). Here's a breakdown of what happened for me to get tests to pass.

Problem

  • I just detached my expo app (wish me luck). Upon running my Jest tests for my components, I was receiving an error stating the following
    TypeError: Cannot read property 'openDoc' of undefined

Solution

  • I mocked the react-native-doc-viewer package in my testing env file which is pulled in as a setup file when run my tests.
  • My package.json contains this block of code:
"jest": {
    "preset": "jest-expo",
    "setupFiles": [
      "./test/env.js"
    ]
  }, 
  • In my env.js file I mock the package like so to expose the package globally during tests :
const OpenFileMock = jest.mock('react-native-doc-viewer', () => {
  return {
    openFile: jest.fn(() => {})
  }
})

global.OpenFile = OpenFileMock

Notes

All my tests are now passing. Hope this helps with anyone's issues. Please tag me if you have any questions.

Cool thanks @wontwon - saved me loads of time this morning. Finally got it working I'll outline here what I did for react-i18n (although its basically the exact same as @wontwon's answer)

Problem

TypeError: Cannot read property 'languages' of undefined inside all of my react jest snapshot.

Solution

  • Add a testEnvironment file to your package.json. Mine is stored in my root directory alongside package.json.
  "jest": {
    "preset": "react-native",
    "setupFiles": [
      "./config/testEnvironment.js"
    ]
  }
  • Next add the mocked 'react-native-i18n' to the testEnvironment.js
const I18nMock = jest.mock('react-native-i18n', () => {
  return {
    // translation passed in here is the
    // string passed inside your template
    // I18n.t('yourObjectProperty')
    t: jest.fn((translation) => {
      // This function is something custom I use to combine all
      // translations into one large object from multiple sources
      // appTranslations is basically just a large object
      // { en: { yourObjectProperty: 'Your Translation' } }
      const appTranslations = combineTranslations(
        TestFormTranslation,
        TestSecondFormTranslation,
      );
      // I use english as the default to return translations to the template. 
      // This last line returns the value of your translation
      // by passing in the translation property given to us by the template.
      return appTranslations.en[translation];
    }),
  };
});

global.I18n = I18nMock;

Notes

  • For the above method you can just return a string ("MockTranslations", etc), or the translation property. I just went for the real translations so I didn't have to rebake my snapshots.

@herman-rogers' solution looks good, I only had to add another property to the mocked object to get rid of currentLocale is not a function error:

const I18nMock = jest.mock('react-native-i18n', () => {
  return {
    t: jest.fn(translation => translation), // you may have to change this function
    currentLocale: jest.fn(() => 'en'), // I added this line
  };
});

I fix this problem here

I don't understand why people recommend to unlink/link the package when it fails on Jest, did I miss something ?

I published the 2.0.5 release with a test in the /example folder: https://github.com/AlexanderZaytsev/react-native-i18n/tree/master/example/src

Hi @zoontek,
I am using RN version 0.45.1 and react-native-i18n version 2.0.5. and I am still getting:

TypeError: Cannot read property 'getLanguages' of undefined

I tried to un-link and link the package, it did not solve the problem
I want to avoid unnecessary mocking only for JEST test, since it is a source for errors and maintenance headache

I have the same issue of @assafb81 pls, could you provide a working example of a jest setup?

@assafb81 You have to mock RN Native modules, or launch tests with a simulator.

@sir-gon https://github.com/AlexanderZaytsev/react-native-i18n/tree/master/example/src

@zoontek, thanks for your help.
I tried to add the mock file (since I don't want to run with simulator) from the example but I still got the same error.

 TypeError: Cannot read property 'getLanguages' of undefined

   at Object.<anonymous> (node_modules/react-native-i18n/index.js:12:45)
   at Object.<anonymous> (src/nls/i18n.js:1:168)
   at Object.<anonymous> (src/components/searchScreen.js:5:11)

the code in my mock file (located in [project]/__ _mock_ __/react-native-i18n.js:

// instead of:
import I18n from 'i18n-js'; // with this line I get an error - I need to install i18n-js.
// I am using:
import I18n from 'react-native-i18n';

I18n.locale = 'en'; // a locale from your available translations
export const getLanguages = () => Promise.resolve(['en']);
export default I18n;

It seems that the tests does not recognize my react-native-i18n.js mock file, how do I point the tests to the mock file?

Inside my jest setup , I did
jest.mock('react-native-i18n', () => ({ t: jest.fn((translation) => translation), }));

This will replace the actual text with the i18n key , which I suppose is good for snapshot testing.

@bharadwajsampath - can you provide a complete working example??? I am still struggling

Just add the __mocks__ folder to your root directory as well as that file in the example that @zoontek linked.

for now, this is what I did:

  1. add file react-native-i18n.js to __mock__ folder with:
const I18nMock = jest.mock('react-native-i18n', () => ({
    t: jest.fn(translation => translation),
    currentlLocale: jest.fn(() => 'en'),
}));

global.I18n = I18nMock;

in my package.json I added into the jest configuration section:

"jest": {
    ...
    "setupFiles": [
        "<rootDir>/__mock__/react-native-i18n.js",
        ...-other mock packages...
    ],
    ...
}

I tried to follow the example @zoontek added but with no luck.

@herman-rogers, I tried your solution since the solution @zoontek does not work for me.

my mock, looks like that:

import enTranslation from '../src/nls/en';
import frTranslation from '../src/nls/fr';

const I18nMock = jest.mock('react-native-i18n', () => ({
    t: jest.fn((key) => {
        const appTranslation = combineTranslations(
            enTranslation,
            frTranslation,
        );
        return appTranslation.en[key];
    }),
    currentlLocale: jest.fn(() => 'en'),
}));

global.I18n = I18nMock;

I get an ESLINT error - 'combineTranslations' is not defined.
and I still getting TypeError: _i18n2.default.t is not a function

update
I did 2 changes:

  1. changed the translation files to be *.json and not *.js that contain json object.
  2. adding reference in the jest configuration section solve the TypeError: _i18n2.default.t is not a function.
        "setupFiles": [
            ***
            "<rootDir>/__mocks__/react-native-i18n"
        ]

hi
i've tried all above methods + manual linking but i'm still getting
TypeError: Cannot set property 'translations' of undefined
and
TypeError: Cannot set property 'fallbacks' of undefined
errors

My I18n contains

```import I18n from 'react-native-i18n';
import en from './locales/en';
import fa from './locales/fa';

I18n.fallbacks = true;

I18n.translations = {
en,
fa
};

export default I18n;
```

As above, Did someone solve this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mengxiaowei picture Mengxiaowei  ·  4Comments

tregismoreira picture tregismoreira  ·  7Comments

timgcarlson picture timgcarlson  ·  5Comments

ansmonjol picture ansmonjol  ·  6Comments

mekaVR picture mekaVR  ·  5Comments