Шутливые тесты с i18next и сборником рассказов
Я использую i18next в своем репозитории компонентов. Компоненты работают нормально, но у меня проблемы с тестами. Я использую i18next с hoc, когда я экспортирую только компонент, тесты проходят, но когда я экспортирую его, как экспорт по умолчанию translate ('components') (List); тесты не пройдены. Я попытался сделать два экспорта, с hoc и без, но некоторые компоненты используются в другом, и я не могу импортировать это без hoc. Моя архитектура выглядит так: Root-компонент с I18nextProvider, я обернул каждый компонент в истории этим компонентом, это основной компонент в моем основном приложении. Выглядит просто так:
const Root = ({ component, i18 }) => (
<I18nextProvider i18n={i18}>
<div className={bindClasses('wrapper')}>
{component}
</div>
</I18nextProvider>
);
пример компонента:
import React, { Component } from 'react';
import { translate } from 'react-i18next';
import classNameBind from 'classnames/bind';
import styles from './List.css';
import Icon from '../Icon';
import uuid from '../../utils/methods/uuid';
class List extends Component {
constructor(props) {
super(props);
this.state = {
items: props.items,
};
}
renderNoItems() {
const { items, t } = this.props;
return items.length === 0 ?
t('noMatchingFoundLabel') : '';
}
renderItems() {
const { onItemSelected } = this.props;
const { items } = this.state;
return items
.map(element =>
(
<li key={uuid()}>
<a role="button" tabIndex={0} onClick={() => onItemSelected(element)}>
{ element.icon ? <Icon {...element.icon} /> : '' }
{element.name}
</a>
</li>
),
);
}
render() {
const { className } = this.props;
const bindClasses = classNameBind.bind(styles);
return (
<nav
ref={(scrollable) => { this.scrollable = scrollable; }}
className={bindClasses('wrapper', className)}
onScroll={this.handleScroll}
>
<ul>
{this.renderItems()}
</ul>
</nav>
);
}
}
export default translate('components')(List);
у каждого компонента есть файл index.js только с экспортом по умолчанию.
использование в истории:
<Root i18={i18}>
<List />
</Root>
Я не уверен здесь. Должен ли я передать функцию t компоненту List? это работает без этого, но, возможно, я должен. И проверить:
import React from 'react';
import List from '../List';
import { shallow, mount } from 'enzyme';
import Icon from "../../Icon";
import TextField from "../../TextField";
describe("List component", () => {
const defaultPropsWithIcons = {
items: [
{ name: 'Item1', icon: { name: 'upload', color: 'default' }, options: { some: 'options1'} },
{ name: 'Item2', icon: { name: 'upload', color: 'default' }, options: { some: 'options2'} },
],
t: jest.fn(),
};
test("should render List component with passed items with icons", () => {
const wrapper = shallow(<List {...defaultPropsWithIcons} />);
const actionList = wrapper.find('.wrapper');
expect(list.find('ul').children().length).toBe(2);
expect(list.find('ul').children().at(0).find('a').exists());
expect(list.find('ul').children().at(0).find(Icon).exists()).toBe(true);
});
При нормальном экспорте компонента он работает, с переводом не получилось. Я пытался использовать
jest.mock('react-i18next', () => ({
receive the t function as a prop
translate: () => List => props => <List t={() => ''} {...props} />,
}));
или же
const wrapper = shallow(<List {...defaultPropsWithIcons} t={key => key} />);
но это не помогает, все еще получил ошибку при первом ожидании (ожидается, будет 2, получен 0) Кто-нибудь есть идеи, как мне это проверить? или где у меня ошибка в использовании i18next? Та же проблема возникала при каждом тесте, где я использую компонент List в другом компоненте или просто в других компонентах с i18next.
Привет
1 ответ
Вы не должны тестировать компоненты, заключенные в HOC, просто модульное тестирование должно проверять отдельные части вашего кода.
В компьютерном программировании модульное тестирование - это метод тестирования программного обеспечения, с помощью которого отдельные единицы исходного кода. https://en.wikipedia.org/wiki/Unit_testing
Старайтесь избегать использования { mount } от jest, я подозреваю, что у вас возникают проблемы при его использовании, потому что он рендерит дочерние компоненты.
Если вы хотите провести интеграционный тест и визуализировать компонент ne = sted, вы можете использовать макет следующим образом:
import { translate } from 'react-i18next';
jest.mock('react-i18next', () => ({
translate: () => List => props => <List t={() => ''} {...props} />,
}));
ОБНОВИТЬ:
Вы можете протестировать компонент перевода, если вам не нравится, когда импорт помечается как неиспользованный:
import { translate } from 'react-i18next';
jest.mock('react-i18next', () => ({
translate: jest.fn(() => List => props => <List t={() => ''} {...props} />),
}));
test('should test translation', () => {
expect(translate).toHaveBeenCalled();
expect(translate).toHaveBeenCalledWith('components');
});
Надеюсь, это поможет, счастливого кодирования!