Решаем проблему с тестированием элемента, что он виден пользователю или не виден.
Предпосылки
Разработчики react-testing-library рекомендуют нам писать тесты так, как если бы код работал как у пользователя. А это значит что нужно вызывать пользовательские события, проверять что пользователь видит тот компонент, который должен.
Для тестирования компонентов мы используем библиотеку react-testing-library с testing-library/jest-dom, в рамках которого мы проверяем показывается тот или иной компонент на странице или нет.
Варианты решения
-
Проверять с помощью метод toHaveClass то, что у элемента есть тот или иной класс. Не является хорошей практикой, т.к. на скрытие элемента также влияют его родители. Если родительский элемент не виден пользователь, соответственно и его дочерние тоже не будут.
-
Использовать метод toBeVisible, который под капотом использует getComputedStyle, на расчет которого как раз влияют родительские компоненты и примененные классы к ним и к самому элементу. Но мы чаще всего css файлы стабаем (заменяем пустым объектом), чтобы тесты быстрее проходили, т.к. нам в принципе не важно, как выглядят компоненты у пользователя. Но есть проблема, как нам дать знать тестовому окружению, что у нас есть классы которые влияют на скрытие элемента.
Решение
Можно конечно попробовать каким-то спосом загрузить все стили приложения при выполнении тестов, но это негативно может повлиять на скорость загрузки. Поэтому такой вариант нас не устраивает, такой вариант описан здесь.
Самый простое и легкое решение, это загрузить только те классы, которые у нас вызывает сокрытие у пользователя компонента. Если мы говорим про tailwindcss, то это классы hidden и invisible.
Добавим в файл jest.setup.js небольшой код, который решает нашу проблему:
import '@testing-library/jest-dom'; beforeEach(() => { const style = document.createElement('style'); style.innerHTML = ` .hidden { display: none; } .invisible { visibility: hidden; } `; document.head.appendChild(style); });
Пример теста:
... test('Check element is show and hidden', async () => { render(<Dropdown {...someProps} />); const searchInput = screen.getByPlaceholderText(/Найти/i); await userEvent.click(searchInput); const listbox = screen.getByRole('listbox'); expect(listbox).toBeVisible(); await userEvent.click(document.body); // если вы вдруг будете запрашивать элемент когда он скрыт используется getByRole с hidden: true, иначе элемент не найдет, т.к. для пользователя он скрыт, но присутствует в DOM-дереве // const listbox = screen.getByRole('listbox', { hidden: true }); expect(listbox).not.toBeVisible(); }); ...
В данном тесте мы находим элемент у которого placeholder со значением «Найти», после мы имитируем нажатие на этот элемент. Компонент реализован у нас таким образом, что при нажатии на него, у нас показывается список элементов.
Затем с помощью getByRole ищем семантический тег список, проверяем его что он показывает на экране. Затем мы имитируем нажатие на тело документа, в приложении у нас компонент список скрывается на это действие и мы проверяем это с помощью expect(listbox).not.toBeVisible();
Но если бы мы в файле jest.setup.js не добавили описание для этих css стилей, которые скрывают элемент, то у нас тест бы не прошел, т.к. jest-dom думал бы, что элемент показывается, т.к. он не знает «реализацию» класса.
P.S. Также есть метод toBeInTheDocument, он проверяет если ли элемент в DOM-дереве элементов, но он не проверяет что видит пользователь или нет его на экране.
ссылка на оригинал статьи https://habr.com/ru/articles/856522/
Добавить комментарий