В тестировании React-компонентов с использованием Enzyme часто
встречается ситуация, когда компоненты обёрнуты в Higher-Order
Components (HOC). HOC добавляют функциональность к базовым
компонентам, оборачивая их в дополнительные слои. При этом стандартный
рендеринг через shallow возвращает внешний HOC, а не сам
компонент, который нужно тестировать. Для таких случаев предназначен
метод .dive().
Метод .dive() позволяет спуститься на один
уровень внутрь обёрнутого компонента, effectively
“прокинувшись” через HOC. Это особенно полезно для тестирования
поведения самого компонента, а не его обёртки.
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
import withExtraProps from './withExtraProps';
const WrappedComponent = withExtraProps(MyComponent);
const wrapper = shallow( );
console.log(wrapper.debug()); // Отображает HOC
const innerWrapper = wrapper.dive();
console.log(innerWrapper.debug()); // Отображает MyComponent
Ключевой момент: .dive() работает
только с компонентами, обёрнутыми в HOC, которые возвращают
классический или функциональный компонент, а не простые
HTML-элементы.
Если компонент обёрнут в несколько HOC, можно вызывать
.dive() последовательно:
const wrapper = shallow( );
const firstDive = wrapper.dive(); // спускаемся через withRouter
const secondDive = firstDive.dive(); // спускаемся через withTheme
Для ускорения процесса часто используют цепочку вызовов:
const innerWrapper = shallow( )
.dive()
.dive();
shallow( ) рендерит только один
уровень компонента..dive() позволяет войти внутрь этого
уровня, не переходя к полному DOM-рендерингу через
mount.Таким образом, .dive() обеспечивает контроль над
отдельными слоями компонента без необходимости рендерить всю дерево.
Функциональные компоненты, использующие React hooks,
после .dive() ведут себя так же, как классовые компоненты.
Основное ограничение — .dive() не работает с
компонентами, которые возвращают null или фрагменты без
оболочки, потому что Enzyme не видит “уровня для спуска”.
Проверка рендеринга элементов внутреннего компонента:
const wrapper = shallow( );
const inner = wrapper.dive();
expect(inner.find('button').length).toBe(1);
expect(inner.text()).toContain('Submit');
Проверка передачи props через HOC:
const wrapper = shallow( );
const inner = wrapper.dive();
expect(inner.props().extraProp).toBe(true);
Вызов методов компонента:
const wrapper = shallow( );
const inner = wrapper.dive();
inner.instance().handleClick();
expect(inner.state('clicked')).toBe(true);
.dive() на
DOM-элементе:const wrapper = shallow();
wrapper.dive(); // Ошибка: dive can only be called on a single non-DOM component
enzyme-adapter-react-16..dive()
не будет работать с HOC.<>...>,
.dive() не имеет “уровня” для спуска.div или span)..dive(), чтобы точно попасть в нужный
компонент.shallowUntilTarget (вспомогательная
функция) для автоматизации спуска до целевого компонента.wrapper.debug() после
.dive(), чтобы убедиться, что вы тестируете именно нужный
компонент.