Enzyme — мощная библиотека для тестирования React-компонентов, предоставляющая два основных способа рендеринга: shallow и mount. При работе с более сложными компонентами часто возникает необходимость взаимодействия с несколькими уровнями вложенности. Понимание того, как Enzyme управляет обёртками, позволяет писать более точные и эффективные тесты.
Shallow rendering создаёт поверхностную обёртку компонента, не рендеря дочерние компоненты глубоко. Это полезно для тестирования изолированного поведения компонента.
const wrapper = shallow(<Parent />);
В этом случае дочерний <Child /> будет представлен
как React-элемент, а не как полностью рендеренный компонент.
Mount rendering создаёт полное дерево компонента с рендерингом всех вложенных компонентов и жизненным циклом React.
const wrapper = mount(<Parent />);
Mount используется, когда требуется проверить взаимодействие компонентов или работу методов жизненного цикла.
Dive позволяет “погружаться” в компонент, созданный при shallow рендеринге, чтобы тестировать его внутреннее содержимое.
const childWrapper = wrapper.find(Child).dive();При наличии глубоко вложенных компонентов одной shallow обёртки может быть недостаточно для тестирования внутренних компонентов. Основные техники:
.find() и
.dive()Метод .find() возвращает новую обёртку, включающую все
найденные компоненты. Для глубокого доступа применяется
.dive(). Например, если структура компонента выглядит
так:
<Parent>
<Intermediate>
<Child />
</Intermediate>
</Parent>
Тестирование внутреннего <Child /> через
shallow:
const wrapper = shallow(<Parent />);
const intermediateWrapper = wrapper.find(Intermediate).dive();
const childWrapper = intermediateWrapper.find(Child).dive();
expect(childWrapper.text()).toBe('Контент Child');
Ключевой момент: каждый .dive() создаёт новую shallow
обёртку для конкретного дочернего компонента.
.children() для обхода DOMМетод .children() возвращает дочерние узлы текущей
обёртки. Если известно, что компонент рендерит прямых потомков без
дополнительных вложенных компонентов, можно комбинировать
.children() с .find():
const wrapper = shallow(<Parent />);
const childWrapper = wrapper.children().find(Child);
Такой подход удобен, когда необходимо проверить прямых потомков, не погружаясь в промежуточные компоненты.
mount и .find()Когда структура компонента сложная и shallow не позволяет получить доступ к элементам, используется mount. Mount создаёт полноценное дерево, позволяя искать любой компонент напрямую:
const wrapper = mount(<Parent />);
const childWrapper = wrapper.find(Child);
expect(childWrapper.text()).toContain('Контент Child');
Преимущество mount — возможность работать с реальным DOM и проверять жизненный цикл компонентов, однако тесты становятся тяжелее и медленнее.
Если компонент рендерит несколько однотипных дочерних элементов,
.find() вернёт коллекцию обёрток. Для работы с конкретным
элементом используется .at(index):
const wrapper = shallow(<Parent />);
const firstChild = wrapper.find(Child).at(0).dive();
expect(firstChild.text()).toBe('Первый Child');
Такой подход критически важен для тестирования списков или динамически генерируемых компонентов.
.find(), .dive(), .children(),
.at()На практике тесты с несколькими уровнями обёртки используют комбинацию методов:
.find() для поиска компонента по типу или
селектору..dive() для входа в внутренний компонент при
shallow..children() для обхода DOM-элементов..at(index) для выборки конкретного компонента из
коллекции.Пример комплексного использования:
const wrapper = shallow(<Parent />);
const firstIntermediate = wrapper.find(Intermediate).at(0).dive();
const targetChild = firstIntermediate.children().find(Child).dive();
expect(targetChild.text()).toBe('Ожидаемый текст');
Shallow не вызывает методы жизненного цикла глубоко вложенных
компонентов, поэтому .dive() часто используется совместно с
shallow, чтобы протестировать componentDidMount и
componentDidUpdate внутри дочернего компонента. Если
необходимо тестировать полностью жизненный цикл, предпочтительнее
mount.
.find() и .dive() позволяет
изолировать тесты и избегать создания слишком тяжёлого дерева..at() для точной выборки.Грамотное использование этих техник обеспечивает гибкость тестирования и позволяет покрывать сложные компоненты без дублирования кода и излишней нагрузки на тестовую среду.