Расширение ShallowWrapper

Enzyme предоставляет два основных метода для работы с компонентами React — mount и shallow. Метод shallow позволяет тестировать компоненты без рендеринга их детей, что делает тесты быстрее и удобнее для изолированных проверок. ShallowWrapper — это объект, возвращаемый при использовании метода shallow. Он включает в себя различные утилиты для взаимодействия с компонентами и их элементами. Однако часто возникает необходимость расширить функциональность этого объекта, добавив кастомные методы или улучшив уже существующие.

Основные методы ShallowWrapper

До того как углубляться в расширение ShallowWrapper, стоит отметить основные методы, предоставляемые Enzyme для работы с ним:

  • find(selector) — находит элементы внутри обёрнутого компонента с помощью CSS-селекторов.
  • text() — извлекает текст из компонента или элемента.
  • simulate(event, [data]) — симулирует события (например, click, change и т. п.).
  • props() — возвращает свойства компонента.
  • setProps(nextProps) — позволяет изменить пропсы компонента и перерисовать его.

Эти методы являются основой для работы с обёртками компонентов. Однако в реальных приложениях может возникнуть необходимость в добавлении новых утилит или методик для более сложных тестов.

Расширение функционала ShallowWrapper

Enzyme предоставляет несколько способов для расширения функционала ShallowWrapper. Это можно сделать с помощью создания собственных методов или добавления утилит для более специфичных тестов. Обычно для этого используется концепция прототипного наследования.

Пример 1: Добавление нового метода в ShallowWrapper

Предположим, необходимо добавить метод для поиска первого элемента внутри компонента с определённым классом, но только если он существует, без ошибок в случае отсутствия элемента.

Для этого можно расширить прототип ShallowWrapper, добавив новый метод findFirst. Этот метод будет искать элемент и возвращать его только в том случае, если он существует, иначе возвращать null.

import { shallow } from 'enzyme';

// Расширение прототипа ShallowWrapper
ShallowWrapper.prototype.findFirst = function(className) {
  const element = this.find(className);
  return element.length > 0 ? element : null;
};

// Пример использования
const wrapper = shallow(<MyComponent />);
const result = wrapper.findFirst('.some-class');

В этом примере метод findFirst будет искать первый элемент с классом .some-class. Если такой элемент не найден, метод вернёт null, что предотвращает возможные ошибки при дальнейших манипуляциях с undefined или пустыми обёртками.

Пример 2: Создание метода для проверки наличия свойства в компоненте

Часто бывает полезно проверять, что компонент имеет определённые свойства. Например, можно создать метод hasProp, который будет возвращать true, если у компонента есть указанное свойство с заданным значением, и false в противном случае.

ShallowWrapper.prototype.hasProp = function(propName, propValue) {
  const props = this.props();
  return props && props[propName] === propValue;
};

// Пример использования
const wrapper = shallow(<MyComponent someProp="value" />);
const result = wrapper.hasProp('someProp', 'value'); // true

В этом примере метод hasProp проверяет, существует ли свойство с нужным именем и значением, что может быть полезно для тестирования корректности пропсов.

Пример 3: Удобный метод для симуляции события и ожидания результата

Иногда требуется не только симулировать событие, но и проверять состояние компонента после его срабатывания. Для этого можно создать метод simulateAndAssert, который будет сначала симулировать событие, а затем проверять изменение состояния компонента.

ShallowWrapper.prototype.simulateAndAssert = function(event, eventData, expectedState) {
  this.simulate(event, eventData);
  expect(this.state()).toEqual(expectedState);
};

// Пример использования
const wrapper = shallow(<MyComponent />);
wrapper.simulateAndAssert('click', { target: { value: 'new value' } }, { value: 'new value' });

Этот метод полезен, когда важно не только сымитировать действие, но и проверить его влияние на состояние компонента.

Интеграция с тестовыми фреймворками

Для лучшей интеграции с тестовыми фреймворками, такими как Jest, можно создавать расширения, которые добавляют дополнительные утилиты, например, для проверки различных стилей или атрибутов элементов.

Пример: создание метода для проверки наличия атрибута disabled у кнопки.

ShallowWrapper.prototype.hasDisabledAttribute = function() {
  return this.props().disabled === true;
};

// Пример использования
const wrapper = shallow(<button disabled />);
expect(wrapper.hasDisabledAttribute()).toBe(true);

Этот метод позволит просто и быстро проверять наличие атрибутов у элементов, что упрощает процесс написания тестов.

Расширение через утилиты

Вместо того чтобы изменять прототип ShallowWrapper напрямую, можно создать отдельные утилиты, которые будут работать с объектами ShallowWrapper. Это может быть полезно, если необходимо избежать глобальных изменений в прототипах, что позволяет сохранять совместимость с другими частями проекта.

Пример утилиты для поиска дочерних элементов по классу:

function findChildByClass(wrapper, className) {
  return wrapper.find(`.${className}`).first();
}

// Пример использования
const wrapper = shallow(<MyComponent />);
const child = findChildByClass(wrapper, 'child-class');

Этот подход позволяет создавать методы, которые работают с обёртками, но не требуют изменения самого объекта ShallowWrapper, что повышает гибкость и облегчает тестирование.

Советы по расширению ShallowWrapper

  1. Использование дополнительных библиотек: Иногда удобнее использовать дополнительные библиотеки для работы с Enzyme, такие как enzyme-matchers или jest-enzyme. Эти библиотеки добавляют новые методы для работы с компонентами, делая код тестов более читаемым и лаконичным.

  2. Обратите внимание на совместимость: Прежде чем расширять функциональность ShallowWrapper, убедитесь, что такие изменения не нарушат существующие тесты или другие методы работы с Enzyme. Лучше создавать утилиты, чем модифицировать прототипы непосредственно.

  3. Не добавляйте излишней логики: Важно помнить, что методы, добавляемые в ShallowWrapper, должны быть максимально простыми и фокусироваться на конкретных задачах. Излишняя логика или сложные проверки могут сделать тесты тяжёлыми для понимания.

  4. Использование моков и шпионов: Если ваши тесты зависят от методов или состояний, которые трудно протестировать напрямую, используйте моки или шпионов. Они могут помочь вам отслеживать поведение компонента и симулировать разные сценарии.

Расширение функциональности ShallowWrapper в Enzyme позволяет значительно упростить написание тестов и сделать их более гибкими. Однако важно сохранять баланс между расширяемостью и сложностью, чтобы не сделать код трудным для поддержки и понимания.