В процессе написания тестов на React-компоненты с использованием Enzyme часто возникает ситуация, когда одни и те же операции повторяются в нескольких тестах: рендеринг компонентов с разными пропсами, настройка моков, поиск элементов, имитация событий. Для поддержания чистоты кода и повышения читаемости тестов критически важно выделять повторяющиеся части в отдельные функции или утилиты.
Enzyme предоставляет три основных метода рендеринга:
shallow, mount и render. Часто
тесты нуждаются в одних и тех же настройках рендеринга, например,
обёртка компонента в провайдер контекста или установка дефолтных
пропсов.
Пример организации повторного рендеринга через фабрику:
import { shallow, mount } from 'enzyme';
import MyComponent from './MyComponent';
const defaultProps = {
title: 'Тестовый заголовок',
visible: true,
};
export const renderShallow = (props = {}) => {
return shallow(<MyComponent {...defaultProps} {...props} />);
};
export const renderMount = (props = {}) => {
return mount(<MyComponent {...defaultProps} {...props} />);
};
Такой подход позволяет в тестах не дублировать код:
it('должен отображать заголовок', () => {
const wrapper = renderShallow({ title: 'Новый заголовок' });
expect(wrapper.find('h1').text()).toBe('Новый заголовок');
});
Ключевой момент: собственные фабрики рендеринга повышают читаемость и облегчают модификацию дефолтного поведения компонентов во всех тестах сразу.
Поиск элементов с помощью .find() часто повторяется.
Вынесение селекторов в отдельные функции делает тесты более
декларативными и снижает риск ошибок при изменении структуры DOM:
export const findTitle = wrapper => wrapper.find('h1');
export const findButton = wrapper => wrapper.find('button.submit');
Использование:
it('кнопка должна быть кликабельной', () => {
const wrapper = renderShallow();
const button = findButton(wrapper);
expect(button.prop('disabled')).toBe(false);
});
Преимущество: изменение селектора в одном месте сразу отражается во всех тестах, где используется соответствующая функция.
Для имитации событий и проверки их последствий лучше создавать вспомогательные функции.
export const clickButton = wrapper => {
wrapper.find('button.submit').simulate('click');
};
Применение:
it('вызывает обработчик при клике', () => {
const onCl ick = jest.fn();
const wrapper = renderShallow({ onClick });
clickButton(wrapper);
expect(onClick).toHaveBeenCalled();
});
Это снижает дублирование кода и делает тесты более читаемыми, особенно если действие включает несколько шагов (клик → изменение состояния → проверка DOM).
Часто тесты требуют разных комбинаций пропсов. Вынесение их в отдельные функции упрощает генерацию сценариев:
export const createProps = (overrides = {}) => ({
title: 'Дефолтный заголовок',
visible: true,
onClick: jest.fn(),
...overrides,
});
Тест с разными набором пропсов:
it('не отображает компонент, если visible = false', () => {
const wrapper = renderShallow(createProps({ visible: false }));
expect(wrapper.isEmptyRender()).toBe(true);
});
Ключевой момент: фабрики пропсов позволяют легко создавать множество сценариев, избегая дублирования и улучшая поддержку тестов.
Если несколько тестов проверяют одинаковые условия, полезно вынести проверку в функцию:
export const expectTitle = (wrapper, text) => {
expect(wrapper.find('h1').text()).toBe(text);
};
Применение:
it('должен отображать корректный заголовок', () => {
const wrapper = renderShallow({ title: 'Тест' });
expectTitle(wrapper, 'Тест');
});
Такой подход делает тесты краткими и выразительными, а логику проверки можно обновлять централизованно.
Часто повторяющийся код помещают в отдельный каталог, например
tests/utils:
tests/
utils/
renderers.js
selectors.js
actions.js
propsFactory.js
Каждый файл содержит отдельный тип утилит:
Это позволяет быстро находить и использовать общие инструменты, поддерживать единообразие и облегчает масштабирование тестовой базы.
Enzyme тесно интегрируется с Jest, что позволяет комбинировать фабрики, мок-функции и проверки:
it('вызывает функцию с правильными аргументами', () => {
const onSub mit = jest.fn();
const wrapper = renderMount(createProps({ onClick: onSubmit }));
clickButton(wrapper);
expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({ type: 'click' }));
});
Комбинирование фабрик рендеринга, пропсов и действий позволяет строить мощные, читаемые и поддерживаемые тесты, сводя дублирование к минимуму.
Повторное использование кода в тестах повышает стабильность, скорость написания и сопровождения тестовой базы, делая её более масштабируемой и структурированной.