如何在使用 react-testing-library 和 jest 完成的单元测试中启用 react-i18n 翻译文件?
How can I enable react-i18n translation file to be used in the unit tests done with react-testing-library and jest?
我正在用 jest 和 react-testing-library 为我的前端应用程序进行单元测试,这是用 React 完成的。在我使用 react-i18next -library 添加国际化之前,我的单元测试运行良好。现在,当我 运行 测试时,似乎 find/use 翻译文件和所有应该阅读内容的地方都留空了。我正在使用带钩子的最新反应版本,而不是 React.Component 我正在使用这种 "const-components":
const ComponentName = ({t}) => {
return(
<p>{t('example')}</p>
)}
export default ComponentName;
国际化在实际页面中完美运行,但单元测试由于未使用 translation-file 而失败,所以我认为问题在于正确模拟翻译文件。我只是使用 this.variableName 类型的解决方案为较旧的反应找到一些建议解决方案,但这对我帮助不大。
我尝试用 jest.fn() 模拟它,但我不确定应该模拟哪个函数,以及如何在测试中正确使用 useTranslation() 函数。
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);
});
错误消息:找不到包含以下文本的元素:翻译文件标题。这可能是因为文本被多个元素打断了。在这种情况下,您可以为您的文本匹配器提供一个函数,使您的匹配器更加灵活。
简而言之:应该包含某些文本的地方现在完全是空的。
您不应该模拟翻译,而是将带有翻译库的组件呈现为高阶组件,例如;
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();
});
而不是用 i18n.getDataByLanguage('en') 调用你的翻译文本,你可以给你的项目的默认翻译,如果它是法语调用它 i18n.getDataByLanguage('fr').
也像这样更改您的组件,而不是从 props 中获取 useTranslation 钩子,而是将其带入带有钩子的组件中
ComponentName.jsx
import { useTranslation } from 'react-i18next'
const ComponentName = () => {
const { t } = useTranslation()
return(
<p>{t('example')}</p>
)}
export default ComponentName;
最终我得到了这样的模拟(在 App.js 中):
jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: key => key,
i18n: { changeLanguage: jest.fn() }
})
}));
万一有人需要这个。
另外在我刚刚使用的组件内部 t={key=>key}
,它启用了这样的查询:expect(c.getByText('json.field.in.translation')).toBeDefined();
我是这样做的:
在单独的文件中为 i18n
创建配置:
const DEFAULT_LANGUAGE = "en";
const DEFAULT_NAMESPACE = "translations";
const enTranslationJson={ //bring that json from your real translation file!
"nav": {
"home": "Home",
"example": "Example"
},
"page-title": "{{pageName}} Page",
};
i18n.use(initReactI18next).init({
lng: DEFAULT_LANGUAGE,
fallbackLng: DEFAULT_LANGUAGE,
ns: [DEFAULT_NAMESPACE],
defaultNS: DEFAULT_NAMESPACE,
debug: false,
interpolation: {
escapeValue: false,
},
resources: { [DEFAULT_LANGUAGE]: { [DEFAULT_NAMESPACE]:
enTranslationJson } },
});
export default i18n;
使用I18nextProvider
覆盖渲染方法:
import { render as rtlRender } from "@testing-library/react";
import { I18nextProvider } from "react-i18next";
const render = (ui: React.ReactElement) => {
return rtlRender(<I18nextProvider i18n={i18n}>{ui}</I18nextProvider>);
}
在测试中,我使用 render
函数并寻找 真实 翻译值:
test("home component render correctly", async () => {
render(<Home />);
const item = screen.getByText("Template Page");
expect(item).toBeInTheDocument();
});
我正在用 jest 和 react-testing-library 为我的前端应用程序进行单元测试,这是用 React 完成的。在我使用 react-i18next -library 添加国际化之前,我的单元测试运行良好。现在,当我 运行 测试时,似乎 find/use 翻译文件和所有应该阅读内容的地方都留空了。我正在使用带钩子的最新反应版本,而不是 React.Component 我正在使用这种 "const-components":
const ComponentName = ({t}) => {
return(
<p>{t('example')}</p>
)}
export default ComponentName;
国际化在实际页面中完美运行,但单元测试由于未使用 translation-file 而失败,所以我认为问题在于正确模拟翻译文件。我只是使用 this.variableName 类型的解决方案为较旧的反应找到一些建议解决方案,但这对我帮助不大。
我尝试用 jest.fn() 模拟它,但我不确定应该模拟哪个函数,以及如何在测试中正确使用 useTranslation() 函数。
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);
});
错误消息:找不到包含以下文本的元素:翻译文件标题。这可能是因为文本被多个元素打断了。在这种情况下,您可以为您的文本匹配器提供一个函数,使您的匹配器更加灵活。
简而言之:应该包含某些文本的地方现在完全是空的。
您不应该模拟翻译,而是将带有翻译库的组件呈现为高阶组件,例如;
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();
});
而不是用 i18n.getDataByLanguage('en') 调用你的翻译文本,你可以给你的项目的默认翻译,如果它是法语调用它 i18n.getDataByLanguage('fr').
也像这样更改您的组件,而不是从 props 中获取 useTranslation 钩子,而是将其带入带有钩子的组件中
ComponentName.jsx
import { useTranslation } from 'react-i18next'
const ComponentName = () => {
const { t } = useTranslation()
return(
<p>{t('example')}</p>
)}
export default ComponentName;
最终我得到了这样的模拟(在 App.js 中):
jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: key => key,
i18n: { changeLanguage: jest.fn() }
})
}));
万一有人需要这个。
另外在我刚刚使用的组件内部 t={key=>key}
,它启用了这样的查询:expect(c.getByText('json.field.in.translation')).toBeDefined();
我是这样做的:
在单独的文件中为
i18n
创建配置:const DEFAULT_LANGUAGE = "en"; const DEFAULT_NAMESPACE = "translations"; const enTranslationJson={ //bring that json from your real translation file! "nav": { "home": "Home", "example": "Example" }, "page-title": "{{pageName}} Page", }; i18n.use(initReactI18next).init({ lng: DEFAULT_LANGUAGE, fallbackLng: DEFAULT_LANGUAGE, ns: [DEFAULT_NAMESPACE], defaultNS: DEFAULT_NAMESPACE, debug: false, interpolation: { escapeValue: false, }, resources: { [DEFAULT_LANGUAGE]: { [DEFAULT_NAMESPACE]: enTranslationJson } }, }); export default i18n;
使用
I18nextProvider
覆盖渲染方法:import { render as rtlRender } from "@testing-library/react"; import { I18nextProvider } from "react-i18next"; const render = (ui: React.ReactElement) => { return rtlRender(<I18nextProvider i18n={i18n}>{ui}</I18nextProvider>); }
在测试中,我使用
render
函数并寻找 真实 翻译值:test("home component render correctly", async () => { render(<Home />); const item = screen.getByText("Template Page"); expect(item).toBeInTheDocument(); });