Условный рендеринг является важной частью разработки веб-приложений с использованием React. Он позволяет отображать или скрывать элементы на основе определённых условий, таких как состояние компонента, параметры или ответы от серверов. Правильное тестирование этого процесса имеет решающее значение для обеспечения надёжности приложения. Jest, в связке с React Testing Library, предоставляет мощные инструменты для тестирования таких сценариев.
Условный рендеринг часто используется в следующих случаях:
В контексте тестирования важно не только проверить рендеринг этих элементов, но и убедиться, что компоненты корректно обновляются, когда изменяются условия.
Рассмотрим компонент, который отображает список элементов только если
состояние isLoaded истинно, а если нет, — выводит сообщение
о том, что данные ещё загружаются:
import React, { useState, useEffect } from 'react';
const ItemList = ({ items }) => {
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
if (items.length > 0) {
setIsLoaded(true);
}
}, [items]);
if (!isLoaded) {
return <div>Loading...</div>;
}
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
};
В этом примере компонент сначала отображает индикатор загрузки, а затем список, если данные загружены. Тестирование такого компонента включает проверку того, что компоненты рендерятся в зависимости от состояния загрузки.
Для тестирования условного рендеринга в Jest важно убедиться, что компонент ведёт себя корректно при разных значениях состояния.
Для проверки того, что индикатор загрузки отображается, когда данные ещё не загружены, можно использовать следующий тест:
import { render, screen } from '@testing-library/react';
import ItemList from './ItemList';
test('показывает индикатор загрузки при пустом списке', () => {
render(<ItemList items={[]} />);
const loadingMessage = screen.getByText(/loading/i);
expect(loadingMessage).toBeInTheDocument();
});
В этом тесте компонент рендерится с пустым массивом в качестве пропса. Ожидаем, что на экране появится текст “Loading…”, что подтверждает рендеринг индикатора загрузки.
Когда данные загружены (в данном случае, когда массив
items содержит элементы), компонент должен отобразить
список. Следующий тест проверяет это:
test('показывает список элементов после загрузки', () => {
const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
];
render(<ItemList items={items} />);
const listItem1 = screen.getByText(/Item 1/i);
const listItem2 = screen.getByText(/Item 2/i);
expect(listItem1).toBeInTheDocument();
expect(listItem2).toBeInTheDocument();
});
Здесь мы передаём в компонент массив с двумя элементами. Ожидаем, что оба элемента будут отображены в списке.
Если состояние компонента изменяется после рендера, важно проверить,
что компонент обновляется корректно. В этом примере условный рендеринг
зависит от состояния, которое обновляется через хук
useEffect. Тест на обновление состояния можно написать
следующим образом:
test('переключается между состояниями загрузки и списка', () => {
const { rerender } = render(<ItemList items={[]} />);
const loadingMessage = screen.getByText(/loading/i);
expect(loadingMessage).toBeInTheDocument();
rerender(<ItemList items={[{ id: 1, name: 'Item 1' }]} />);
const listItem = screen.getByText(/Item 1/i);
expect(listItem).toBeInTheDocument();
expect(loadingMessage).not.toBeInTheDocument();
});
Здесь используется метод rerender для того, чтобы
принудительно обновить компонент с новыми пропсами. Сначала компонент
рендерится с пустым списком, отображая “Loading…”. После изменения
пропсов на список с элементом проверяется, что “Loading…” больше не
отображается, а элемент списка появляется.
В реальных приложениях данные часто загружаются асинхронно. Для таких
случаев можно использовать моки, чтобы симулировать поведение сервера
или API. Например, можно использовать jest.mock для
создания фиктивного модуля для асинхронной загрузки данных:
jest.mock('./api', () => ({
fetchItems: jest.fn(() => Promise.resolve([{ id: 1, name: 'Mocked Item' }])),
}));
import { fetchItems } from './api';
test('отображает элементы после асинхронной загрузки', async () => {
render(<ItemList items={[]} />);
const loadingMessage = screen.getByText(/loading/i);
expect(loadingMessage).toBeInTheDocument();
await screen.findByText(/Mocked Item/i);
expect(loadingMessage).not.toBeInTheDocument();
});
В этом примере мы мокаем функцию fetchItems, которая
возвращает промис с загруженными элементами. После того как данные
загружены, компонент должен отобразить эти элементы.
Тестирование условного рендеринга является важной частью обеспечения корректной работы интерфейсов, особенно в React-приложениях, где поведение компонента может изменяться в зависимости от состояния и пропсов. Использование Jest и React Testing Library позволяет удобно проверять такие сценарии, включая рендеринг элементов в зависимости от состояния компонента и правильное обновление интерфейса при изменении данных. Тесты, проверяющие отображение сообщений, списков и обновления компонентов, дают уверенность в том, что приложение будет работать должным образом в различных условиях.