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 оновився".

👉 Далі: Тестування Thunks та API

Copyright © 2026