Rking14
Rking14

Reputation: 345

Mocking useTranslation for i18n in JEST not working

My react component uses translations from i18next and I'm trying to create tests for it using JEST. However, nothing is getting translated and I have tried mocking the useTranslation function below:

const useMock : any = [(k: any) => k, {}];
useMock.t = (k: any) => k;
useMock.i18n = {};

jest.mock('react-i18next', () => ({
  // this mock makes sure any components using the translate HoC receive the t function as a prop
  /* tslint:disable-next-line:variable-name */
  useTranslation: () => useMock,
}));

What am I doing wrong?

Upvotes: 6

Views: 23671

Answers (4)

Ovidiu Muntean
Ovidiu Muntean

Reputation: 11

Try like this:

jest.mock('react-i18next', () => ({
  useTranslation: () => ({ t: () => ['key'] }),
  Trans: () => jest.fn(),
  t: () => jest.fn(),
}));

Upvotes: 1

ricnef2121
ricnef2121

Reputation: 64

i share my config i hope that it can help you

my folder are this : enter image description here

my mocks is this :

react-i18next.js
const React = require('react');
const reactI18next = require('react-i18next');
let root = __dirname;
var fs = require('fs');

//console.log(root.replace("src\\__mocks__","public\\assets\\i18n\\{{ns}}.json"))
const hasChildren = (node) => node && (node.children || (node.props && node.props.children));

const getChildren = (node) =>
    node && node.children ? node.children : node.props && node.props.children;

const renderNodes = (reactNodes) => {
    if (typeof reactNodes === 'string') {
        return reactNodes;
    }

    return Object.keys(reactNodes).map((key, i) => {
        const child = reactNodes[key];
        const isElement = React.isValidElement(child);

        if (typeof child === 'string') {
            return child;
        }
        if (hasChildren(child)) {
            const inner = renderNodes(getChildren(child));
            return React.cloneElement(child, { ...child.props, key: i }, inner);
        }
        if (typeof child === 'object' && !isElement) {
            return Object.keys(child).reduce((str, childKey) => `${str}${child[childKey]}`, '');
        }

        return child;
    });
};

let language = "en"
const useMock = [(k) => k, {}];
let traduccions = root.replace("src\\__mocks__", `public\\assets\\i18n\\commons\\${language}.json`)

let changeLanguage = (lng = "en") => {
    useMock.language = lng;
}

useMock.i18n = { 
    ns: ['commons'],
    defaultNS: 'commons',
    changeLanguage,
    language,
};
useMock.t = (k) => { 
    const result =()=> fs.readFileSync(traduccions,"utf8", function (err, data) {
        if (err) {
           return console.error(err);
        }
       return data.toString()
     });  
    let termsToSearch = k.replace(`${useMock.i18n.defaultNS}:`,'').split(".")
    let res =JSON.parse(result());
    termsToSearch.forEach(element => {
         res=res[element];
    });
    return res;
};



/**
 * commons:language.language
 */



module.exports = {
    // this mock makes sure any components using the translate HoC receive the t function as a prop
    withTranslation: () => (Component) => (props) => <Component t={(k) => k} {...props} />,
    Trans: ({ children }) =>
        Array.isArray(children) ? renderNodes(children) : renderNodes([children]),
    Translation: ({ children }) => children((k) => k, { i18n: {} }),
    useTranslation: () => useMock,

    // mock if needed
    I18nextProvider: reactI18next.I18nextProvider,
    initReactI18next: reactI18next.initReactI18next,
    setDefaults: reactI18next.setDefaults,
    getDefaults: reactI18next.getDefaults,
    setI18n: reactI18next.setI18n,
    getI18n: reactI18next.getI18n,
};

The major parte is of the documentation of i18n i only add the way to show the right traduction

https://react.i18next.com/misc/testing https://github.com/i18next/react-i18next/blob/master/example/test-jest/src/__mocks__/react-i18next.js

Upvotes: 0

Michael Schmid
Michael Schmid

Reputation: 5005

Create a file __mocks__/react-i18next.js (the folder __mocks__ being next to node_modules, in the same parent folder), containing:

module.exports = {
  useTranslation: () => ({
    t: key => key,
  }),
}

In your test script, import useTranslation normally, but define the mock to be used.

import {useTranslation} from 'react-i18next'
/* Other imports and code */

jest.mock('react-i18next')
/* Your test code using useTranslation */

Upvotes: 4

Iuri Pereira
Iuri Pereira

Reputation: 98

Create a mock file: __mocks__/react-i18next.useTranslation.js with this content:

module.exports = () => {
  return () => ({
    t: key => key
  })
}

Upvotes: 3

Related Questions