Найти в Дзене

React-testing-library, jsdom -хакаем transitionEvent

Оглавление

Привет, дзен! Недавно на работе споткнулся о тестирование компонента, в котором используется подписка на событие onTransitionEnd. Долго не мог придумать, решение. Потом вспомнил, что это javascript и придумал костыль. Из этого родилась маленькая статья, приятного чтения!

Компонент для тестирования

-2

Есть обработчик события onTransitionEnd. Так как под transition попадает несколько свойств, а нам нужно только свойство высоты - простая проверка (вот о нее я и споткнулся) и вызов колбека - все очень просто.

Тест 1. Наивный

-3

Тест тоже довольно простой, рендерим компонент, проверяем, что колбек не был вызван, файрим ивент, проверяем, что колбек был вызван один раз. Как думаете, пройдет тест?

Первый запуск

Тест не прошел с сообщением

-4

Но интереснее посмотреть на консоль лог

-5

Как я и думал, мы не задаем свойство propertyName, как результат оно не определено. Но почему конструктор Event? Должен же быть TransitionEvent? 🤨

Тест испорчен, вечер в шоке.

Тест 2. Переопределяем свойства.

Судя по тайпингам и документации функция вторым параметром можно передать либо ивент, либо настройки ивента, давайте попробуем.

-6

Тест снова не проходит, смотрим лог

-7

cancelable изменился, а propertyName нет? Чего? 🤨

Тест 3. Кастомный ивент

Ну, думаю, ладно, можно же создать кастомный ивент и стриггерить его, попробуем.

-8

Делаем ставки, господа, что пойдет не так на этот раз?

-9

Вот это поворот :)
Лезем в исходники и подглядываем.
В файлике `@testing-library/dom/dist/events.js` находим волшебные строки

-10

Ну теперь хотя бы становится понятно, почему при вызове fireEvent.transitionEnd название конструктора Event а не TransitionEvent.

Дело в том, что testing library работает поверх jsdom. Не знаю как в свежих версиях, но в моей версии jsdom не существует TransitionEvent. Существует только Event.

Я, конечно, попробовал создать Event c параметрами {cancelable: false, bubbles: true, propertyName: 'height'}, но конструктор Event игнорирует propertyName. Я пробовал создать CustomEvent, но мои попытки не увенчались успехом

Проблема

Мне нужно создать ивент, который бы содержал propertyName = "height".
Все, доступные в
jsdom, конструкторы событий игнорируют propertyName.

Что же делать? Есть идеи?

Костыль. Отличная идея

По хорошему, я бы поискал полифил TransitionEvent для jsdom, однако я нашел отличный (по моему мнению) костыль. Это же javascript :)

Мы можем создать Event, однако у него нет свойства propertyName.
Как бы нам так положить туда
propertyName, да еще так, чтобы typescript не орал на меня?

Что мы делаем, когда
property is undefined? Правильно, используем defineProperty :)

-11

Ну сейчас-то тест пройдет?
Посмотрим на логи

-12
-13

Ура! Долгожданный тест пройден 🥳

Заключение

Это я сейчас в статье поставил консоль логи, обратил внимание на имя конструктора и тому подобное, но еще вчера на два часа моей жизни стало меньше из-за этой прекрасной особенности :)

Пишите тесты, определяйте свойства
(это лютый костыль, не стоит так делать), подписывайтесь на события, на меня на ютубе, на меня в телеграмм канале.

🕊️