Skip to content

17. Testowanie komponentów

This content is not available in your language yet.

Testowanie komponentów React

React Testing Library (RTL) to biblioteka do testowania komponentów React z perspektywy użytkownika — tak jak użytkownik widzi i interaguje z UI. Zasada: testuj zachowanie, nie implementację. Nie testuj jak komponent jest zbudowany — testuj co użytkownik widzi i może zrobić.

  1. Dlaczego testujemy? — Pewność że zmiany nie psują istniejącej funkcjonalności (regression)
  2. Co to jest RTL? — Biblioteka renderująca komponenty React w testach bez przeglądarki
  3. Queries — co to? — Metody wyszukiwania elementów: getByRole, getByText, getByLabelText
  4. Testuj zachowanie, nie implementację? — Testy nie powinny wiedzieć jak komponent jest zbudowany wewnątrz
  1. Po co testy? — Regression prevention, confidence, dokumentacja
  2. Setup — Vitest + RTL + @testing-library/user-event
  3. render i screen — renderowanie komponentu, wyszukiwanie elementów
  4. Queries — getByRole (preferowany), getByText, getByLabelText
  5. userEvent — symulacja kliknięć, wpisywania tekstu

Schemat

Piramida testów: Unit (dużo, szybkie) → Integration (kilka) → E2E (mało, wolne). Zaznaczcie gdzie jest RTL (unit/integration komponentów).

Przykład kodu JSX

Test komponentu licznika: render → kliknięcie przycisku → asercja nowej wartości.

  • Po co testy, piramida testów
  • Podstawowy test z render i getByText
  • Kliknięcie przycisku z fireEvent

Forma: 10 slajdów, 10 minut

Ocena: 3.0
Counter.test.jsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Counter } from './Counter';
describe('Counter', () => {
it('should display initial value of 0', () => {
render(<Counter />);
expect(screen.getByText('Licznik: 0')).toBeInTheDocument();
});
it('should increment when + button is clicked', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: '+' }));
expect(screen.getByText('Licznik: 1')).toBeInTheDocument();
});
it('should reset to 0 when Reset is clicked', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: '+' }));
await user.click(screen.getByRole('button', { name: '+' }));
await user.click(screen.getByRole('button', { name: 'Reset' }));
expect(screen.getByText('Licznik: 0')).toBeInTheDocument();
});
});
it('should show error when email is invalid', async () => {
const user = userEvent.setup();
render(<LoginForm />);
await user.type(screen.getByLabelText('Email'), 'niepoprawny-email');
await user.click(screen.getByRole('button', { name: 'Zaloguj' }));
expect(screen.getByText('Podaj poprawny email')).toBeInTheDocument();
});

Uruchomcie testy na żywo

Nic nie robi takiego wrażenia jak npm test w terminalu i zobaczenie zielonego “PASS” (lub czerwonego “FAIL” gdy zepsujecie komponent). Live demo!

Zasada getByRole

Podkreślcie: getByRole jest preferowanym query bo sprawdza ACCESSIBILITY — jeśli test z getByRole przechodzi, element jest dostępny dla czytników ekranu.

Testy to ubezpieczenie kodu!

Każda firma produkująca poważne aplikacje wymaga testów. Ten temat wyróżni Was na rynku pracy!