Каждый рабочий день я пишу множество тестов с помощью Enzyme. Несмотря на то, что библиотека хорошо спроектирована, есть несколько хитрых моментов, когда легко ошибиться и потратить много драгоценного времени, пытаясь выяснить, почему один тест не проходит… 😤
Обновление состояния onEvent
Рассмотрим простой сценарий:
- монтируем компонент и получаем обертку
prop.value
изtab
имеет исходное значениеbefore
- смоделировано
click
событие prop.value
должно иметь значениеafter
const tab = wrapper.find('.tab');
expect(tab.props().value).toEqual('before');
tab.find('button').simulate('click');
expect(tab.props().value).toEqual('after');
Выглядит неплохо, не правда ли? К сожалению, это может не сработать 🥴
Далее проблема описана в официальном трекере проблем Enzyme.
TL; DR: оболочка не обновляет свои значения сама по себе - нам нужно запускать обновление вручную. Более того, уже найденные обертки не обновляются. Это означает, что нужно добавить две строки кода, чтобы тест стал зеленым:
...tab.find('button').simulate('click');
wrapper.update(); tab = wrapper.find('tab');expect(tab.props().value).toEqual('after');
Пример из реальной жизни
Есть две кнопки, изначально активна первая. После нажатия на другую, вторая кнопка становится активной.
function findButtons(wrapper: ReactWrapper) { const buttons = wrapper.find(buttonClass); return { first: buttons.first(), last: buttons.last() }; } it('should select active button when clicked', () => { const panel = mount({ buttons, activeIndex: 0 }); expect(findButtons(panel).first.find(Styles.active)).exists()) .toBeTruthy(); expect(findButtons(panel).last.find(Styles.active)).exists()) .toBeFalsy(); findButtons(panel).last.simulate(EVENT_CLICK); panel.update(); expect(findButtons(panel).first.find(Styles.active)).exists()) .toBeFalsy(); expect(findButtons(panel).last.find(Styles.active)).exists()) .toBeTruthy(); });
Моделирование различных типов событий
Выше было описано событие клика. Однако есть много других событий, например:
change
blur
focus
Может случиться так, что в нашем приложении есть textarea
. Для нашего варианта использования представьте, что длина текста, который может писать пользователь, ограничена. Нам нужен тест, который проверяет, правильно ли работает наша логика и textarea
получает красную рамку, когда набирается слишком много букв.
Как мы можем установить текст в textarea
?
wrapper.find('textarea').simulate('click');
Очевидно, ничего не выйдет - чтобы изменить текст, нам нужно событие change
, а не просто click
🤭 Так что, возможно:
wrapper.find('textarea').simulate('change');
Неа. Мы должны передать текстовое значение для отображения 💡 Должно быть указано событие!
const event = { target: { value: 'comment '} }; wrapper.find('textarea').simulate('change', event);
Вывод: simulate
принимает два параметра - произвольное название события и его значение.
Резюме
Реагировать + Фермент = 🌩️❤️🌩️
Спасибо за чтение и оставайтесь на связи! 👏👏👏