Testing
Тестування Компонентів (Integration)
Коли компонент використовує useSelector або useDispatch, ми не можемо просто відрендерити його в тесті. Він впаде з помилкою could not find react-redux context value.
Тестування Компонентів (Integration)
Коли компонент використовує useSelector або useDispatch, ми не можемо просто відрендерити його в тесті. Він впаде з помилкою could not find react-redux context value.
Нам потрібно обгорнути його в <Provider>.
Утиліта renderWithProviders
Рекомендується створити спеціальну функцію-обгортку над render з React Testing Library.
src/utils/test-utils.jsx
import React from 'react';
import { render } from '@testing-library/react';
import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import userReducer from '../features/user/userSlice';
export function renderWithProviders(
ui,
{
preloadedState = {},
// Автоматично створюємо store, якщо його не передали
store = configureStore({ reducer: { user: userReducer }, preloadedState }),
...renderOptions
} = {}
) {
function Wrapper({ children }) {
return <Provider store={store}>{children}</Provider>;
}
// Повертаємо об'єкт store разом з результатами render
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
}
Тест компонента
Тепер ми можемо писати тести дуже легко.
features/user/UserProfile.test.jsx
import { screen, fireEvent } from '@testing-library/react';
import { renderWithProviders } from '../../utils/test-utils';
import UserProfile from './UserProfile';
test('renders user name from state', () => {
// 1. Рендеримо з початковим станом
renderWithProviders(<UserProfile />, {
preloadedState: {
user: { name: 'Ivan', age: 25 }
}
});
// 2. Перевіряємо, що ім'я на екрані
expect(screen.getByText(/Ivan/i)).toBeInTheDocument();
});
test('updates name on button click', () => {
const { store } = renderWithProviders(<UserProfile />, {
preloadedState: { user: { name: 'Old Name' } }
});
// Клікаємо кнопку
fireEvent.click(screen.getByText(/Change Name/i));
// Перевіряємо, що в сторі змінилися дані
expect(store.getState().user.name).toBe('New Name');
// Або перевіряємо UI, якщо компонент реагує на зміни
expect(screen.getByText(/New Name/i)).toBeInTheDocument();
});
Цей підхід дозволяє тестувати інтеграцію компонента з Redux логікою. Ви перевіряєте реальну поведінку: "Я натиснув кнопку -> Стор оновився -> UI оновився".