При тестировании React-компонентов с использованием библиотеки React
Testing Library (RTL), часто возникает необходимость работать с данными,
которые сохраняются в localStorage или
sessionStorage. Это хранилища предоставляют веб-приложению
возможность хранить данные на стороне клиента, и понимание их работы
критически важно для написания корректных тестов, проверяющих
функциональность компонентов, использующих эти API.
localStorage и sessionStorage — это два
веб-API для хранения данных в браузере. Они отличаются по времени жизни
данных:
Оба API предоставляют методы для хранения, извлечения и удаления данных:
setItem(key, value) — сохраняет данные по ключу.getItem(key) — извлекает данные по ключу.removeItem(key) — удаляет данные по ключу.clear() — удаляет все данные.Эти хранилища особенно полезны при сохранении настроек пользователя, токенов аутентификации, состояния приложений и других данных, которые должны сохраняться между сессиями или вкладками.
При тестировании компонентов, которые взаимодействуют с
localStorage или sessionStorage, важно
учитывать, что в тестах необходимо управлять этим хранилищем. По
умолчанию хранилища в тестах браузера могут быть пустыми или уже
содержать данные. React Testing Library предоставляет методы, которые
позволяют манипулировать этими хранилищами в тестах.
Прежде чем тестировать компоненты, использующие
localStorage или sessionStorage, нужно
очистить их содержимое или подготовить начальные данные.
beforeEach(() => {
localStorage.clear();
sessionStorage.clear();
});
Этот код гарантирует, что хранилища будут очищены перед каждым тестом. Это важно для изоляции тестов и предотвращения “переноса” данных из одного теста в другой.
Для того чтобы протестировать работу компонентов с
localStorage или sessionStorage, можно
использовать методы setItem и getItem.
Например, если компонент зависит от определённых данных, которые
хранятся в хранилище, можно установить эти данные перед рендерингом
компонента.
it('сохраняет токен в localStorage и отображает данные пользователя', () => {
const token = 'abc123';
localStorage.setItem('authToken', token);
render(<Profile />);
expect(screen.getByText('Добро пожаловать, пользователь!')).toBeInTheDocument();
});
В этом примере мы заранее сохраняем токен в localStorage
и проверяем, что компонент Profile правильно отображает
данные после рендера.
Для sessionStorage процедура аналогична:
it('сохраняет данные сессии в sessionStorage и отображает их', () => {
const sessionData = { userId: '123', sessionToken: 'xyz' };
sessionStorage.setItem('sessionData', JSON.stringify(sessionData));
render(<SessionInfo />);
expect(screen.getByText('Session ID: 123')).toBeInTheDocument();
});
В случае, если необходимо более гибко контролировать поведение
localStorage или sessionStorage, можно
использовать моки. Например, при работе с Jest можно замокать эти
API:
global.localStorage = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
Такой подход позволяет протестировать вызовы методов хранилища, не полагаясь на реальное хранилище браузера. Это также помогает предотвратить нежелательные побочные эффекты, такие как сохранение данных между тестами.
it('вызывается localStorage.setItem при сохранении данных', () => {
const token = 'abc123';
render(<Login />);
fireEvent.click(screen.getByText('Войти'));
expect(localStorage.setItem).toHaveBeenCalledWith('authToken', token);
});
После завершения тестов необходимо очистить все данные из хранилища,
чтобы не возникли конфликты с последующими тестами. Это особенно важно
при работе с глобальными хранилищами, такими как
localStorage или sessionStorage, которые могут
сохранять данные между тестами.
afterEach(() => {
localStorage.clear();
sessionStorage.clear();
});
Эта операция помогает поддерживать чистоту тестового окружения и предотвращает ошибки, вызванные сохранением лишних данных.
Если компонент асинхронно взаимодействует с localStorage
или sessionStorage, например, через API или асинхронные
операции, тестирование требует особого подхода. В таких случаях важно
дождаться завершения всех асинхронных операций перед проверкой состояния
компонента.
it('обрабатывает данные из localStorage после загрузки', async () => {
const userData = { name: 'Иван', age: 30 };
localStorage.setItem('user', JSON.stringify(userData));
render(<UserProfile />);
await waitFor(() => {
expect(screen.getByText('Имя: Иван')).toBeInTheDocument();
expect(screen.getByText('Возраст: 30')).toBeInTheDocument();
});
});
Здесь мы сначала устанавливаем данные в localStorage,
затем рендерим компонент и используем waitFor для того,
чтобы дождаться, пока асинхронная операция завершится и данные появятся
в интерфейсе.
Работа с localStorage и sessionStorage в
тестах React-компонентов с использованием React Testing Library требует
внимательности к управлению состоянием хранилищ. Правильное очищение
хранилищ перед и после тестов, использование моков для замены реальных
вызовов методов хранилища и асинхронные ожидания — важные аспекты для
стабильности тестов. С учётом этих факторов можно эффективно тестировать
компоненты, взаимодействующие с веб-хранилищами.