|
| 1 | +/* eslint-disable @typescript-eslint/no-var-requires */ |
| 2 | +/* eslint-disable react/display-name */ |
| 3 | +/* eslint-disable no-confusing-arrow */ |
| 4 | + |
| 5 | +/** |
| 6 | + * Setup i18n in tests |
| 7 | + * |
| 8 | + * Docs |
| 9 | + * @see https://react.i18next.com/misc/testing |
| 10 | + * |
| 11 | + * Inspired by |
| 12 | + * @see https://github.com/i18next/react-i18next/blob/552ed79036c28f282afe7c6ccb525b82b76e71d5/example/test-jest/src/__mocks__/react-i18next.js |
| 13 | + * |
| 14 | + * Alternative examples using `i18n.use()...` |
| 15 | + * @see https://github.com/i18next/react-i18next/blob/552ed79036c28f282afe7c6ccb525b82b76e71d5/example/test-jest/src/setupTests.js#L4-L23 |
| 16 | + * @see https://github.com/i18next/react-i18next/blob/552ed79036c28f282afe7c6ccb525b82b76e71d5/test/i18n.js |
| 17 | + * @see https://github.com/isaachinman/next-i18next/issues/377#issuecomment-700516821 |
| 18 | + */ |
| 19 | + |
| 20 | +const React = require('react') |
| 21 | +const reactI18next = require('react-i18next') |
| 22 | + |
| 23 | +const hasChildren = node => |
| 24 | + node && (node.children || (node.props && node.props.children)) |
| 25 | + |
| 26 | +const getChildren = node => |
| 27 | + node && node.children ? node.children : node.props && node.props.children |
| 28 | + |
| 29 | +const renderNodes = reactNodes => { |
| 30 | + if (typeof reactNodes === 'string') { |
| 31 | + return reactNodes |
| 32 | + } |
| 33 | + |
| 34 | + return Object.keys(reactNodes).map((key, i) => { |
| 35 | + const child = reactNodes[key] |
| 36 | + const isElement = React.isValidElement(child) |
| 37 | + |
| 38 | + if (typeof child === 'string') { |
| 39 | + return child |
| 40 | + } |
| 41 | + if (hasChildren(child)) { |
| 42 | + const inner = renderNodes(getChildren(child)) |
| 43 | + return React.cloneElement(child, { ...child.props, key: i }, inner) |
| 44 | + } |
| 45 | + if (typeof child === 'object' && !isElement) { |
| 46 | + return Object.keys(child).reduce( |
| 47 | + (str, childKey) => `${str}${child[childKey]}`, |
| 48 | + '', |
| 49 | + ) |
| 50 | + } |
| 51 | + |
| 52 | + return child |
| 53 | + }) |
| 54 | +} |
| 55 | + |
| 56 | +/** |
| 57 | + * @type any |
| 58 | + */ |
| 59 | +const useMock = [k => k, {}] |
| 60 | +useMock.t = k => k |
| 61 | +useMock.i18n = {} |
| 62 | + |
| 63 | +module.exports = { |
| 64 | + // this mock makes sure any components using the translate HoC receive the t function as a prop |
| 65 | + withTranslation: () => Component => props => ( |
| 66 | + <Component t={k => k} {...props} /> |
| 67 | + ), |
| 68 | + Trans: ({ children }) => |
| 69 | + Array.isArray(children) ? renderNodes(children) : renderNodes([children]), |
| 70 | + Translation: ({ children }) => children(k => k, { i18n: {} }), |
| 71 | + useTranslation: () => useMock, |
| 72 | + |
| 73 | + // mock if needed |
| 74 | + I18nextProvider: reactI18next.I18nextProvider, |
| 75 | + initReactI18next: reactI18next.initReactI18next, |
| 76 | + setDefaults: reactI18next.setDefaults, |
| 77 | + getDefaults: reactI18next.getDefaults, |
| 78 | + setI18n: reactI18next.setI18n, |
| 79 | + getI18n: reactI18next.getI18n, |
| 80 | +} |
0 commit comments