I am making unit tests with jest and react-testing-library for my frontend application which is done with React. My unit tests worked nicely before I added the internationalization with react-i18next -library. Now when I run the tests, it seems that it doesn't find/use the translation files and all places where there should read something, are left empty. I'm using the newest react version with hooks and instead of React.Component I am using this kind of "const-components":
const ComponentName = ({t}) => {
return(
<p>{t('example')}</p>
)}
export default ComponentName;
The internationalization works perfectly in the actual page but just that the unit tests fail due to not using the translation-file so I think the problem is with correctly mocking the translation files. I am only finding some suggestion solutions for the older react using this.variableName -type of solutions, which however doesn't help me much.
I have tried to mock it with jest.fn(), but I am not sure which function is the one, which I should mock and how to utilize the useTranslation() -function correctly from the tests.
import React from 'react';
import { useTranslation, Trans } from 'react-i18next';
import { render } from '@testing-library/react';
import ComponentName from './ComponentName';
import '../locales/i18n';
test('renders all documents in the list', () => {
const mockUseTranslation = jest.fn();
const { t, i18n } = mockUseTranslation();
// const t = jest.fn();
const c = render(<ComponentName t={t} />);
expect(c.getByText('Translation File Title')).toBeDefined();
expect(
c.getAllByText(
'Lorem ipsum'
).length
).toBe(3);
});
Error message: Unable to find an element with the text: Translation File Title. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
So in short: the place, which should contain certain text is now totally empty.
Internationalization or i18n is the design and development of a product, application, or document content that enables easy localization for target audiences that vary in culture, region, or language. Thus, React i18n is concerned with localizing React applications for different locales.
How to translate your React app with react-i18next 1 Setup your first React app. We're setting up a small React application to learn how localization works. ... 2 Add internationalization. ... 3 Translation IDs vs Translation strings. ... 4 Translate your application. ... 5 Changing languages. ... 6 Maintain translation files. ...
The react-i18next module is a widely used module available for multilingual setup on react js and also for react-native. So let us get started on how to use that module in our project. Create a react project. 2. Now install react-i18next and i18next packages in your project.
Internationalization or i18n is the design and development of a product, application, or document content that enables easy localization for target audiences that vary in culture, region, or language. Thus, React i18n is concerned with localizing React applications for different locales.
You can refer to react-intl documentation here. In this tutorial, we will be using the react-intl library to apply internationalization as it is the best and most popular library for React i18n to date. The react-intl-universal internationalization package, which is built by Alibaba Group, is based on the react-intl library.
You should not mock the translation, instead render the component with translation library as Higher Order Component, for example;
import React from 'react';
import i18n from '../../../i18n' // your i18n config file
import { render } from '@testing-library/react';
import ComponentName from './ComponentName';
import { I18nextProvider } from 'react-i18next'
test('renders all documents in the list', () => {
const c = render(
<I18nextProvider i18n={i18n}> // actually give translation to your component
<ComponentName />
</I18nextProvider>
);
// example if you have a key called example
expect(c.getByText(i18n.getDataByLanguage('en').translation.example)).toBeDefined();
});
Instead of calling your translation texts with i18n.getDataByLanguage('en') , you can give the default translation of your project, if it is French call it by i18n.getDataByLanguage('fr').
Also change your component like this, instead of taking useTranslation hook from props, take it inside the component with hooks
ComponentName.jsx
import { useTranslation } from 'react-i18next'
const ComponentName = () => {
const { t } = useTranslation()
return(
<p>{t('example')}</p>
)}
export default ComponentName;
Eventually I got the mock working like this (in App.js):
jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: key => key,
i18n: { changeLanguage: jest.fn() }
})
}));
In case somebody needs this.
Additionally inside components I was just using t={key=>key}
, which enabled queries like this: expect(c.getByText('json.field.in.translation')).toBeDefined();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With