Kurs vibe coding z AI · Moduł 11: Spotify Clone

Testing - Jest & React Testing Library

1 min czytania
W tej lekcji2

Pisanie testów dla komponentów React.

Setup

npm install --save-dev @testing-library/react @testing-library/jest-dom jest

Component Tests

// Button.tsx
export function Button({ onClick, children }: {
  onClick: () => void;
  children: React.ReactNode
}) {
  return (
    <button onClick={onClick} className="btn">
      {children}
    </button>
  );
}

// Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('renders children', () => {
    render(<Button onClick={() => {}}>Click me</Button>);
    expect(screen.getByText('Click me')).toBeInTheDocument();
  });

  it('calls onClick when clicked', () => {
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click</Button>);

    fireEvent.click(screen.getByText('Click'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });
});

Do zobaczenia!

Kod do tej lekcji: App.tsx
'use client';

import { useState } from 'react';

export default function CreatePlaylistModal() {
  const [isOpen, setIsOpen] = useState(true);
  const [name, setName] = useState('');
  const [description, setDescription] = useState('');
  const [isPublic, setIsPublic] = useState(true);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (name.trim()) {
      alert(`Utworzono playlistę: ${name}`);
      setIsOpen(false);
    }
  };

  if (!isOpen) {
    return (
      <div className="min-h-screen bg-black text-white flex items-center justify-center">
        <button
          onClick={() => setIsOpen(true)}
          className="px-6 py-3 bg-green-500 text-black font-semibold rounded-full hover:bg-green-400"
        >
          Utwórz playlistę
        </button>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-black/75 flex items-center justify-center p-4">
      <div className="bg-gray-900 rounded-lg max-w-md w-full p-6 text-white">
        <h2 className="text-2xl font-bold mb-6">Utwórz playlistę</h2>

        <form onSubmit={handleSubmit}>
          <div className="mb-4">
            <label className="block text-sm font-semibold mb-2">
              Nazwa
            </label>
            <input
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="Moja playlista"
              className="w-full bg-gray-800 text-white px-4 py-3 rounded outline-none focus:ring-2 focus:ring-green-500"
              autoFocus
            />
          </div>

          <div className="mb-4">
            <label className="block text-sm font-semibold mb-2">
              Opis (opcjonalnie)
            </label>
            <textarea
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              placeholder="Dodaj opis..."
              className="w-full bg-gray-800 text-white px-4 py-3 rounded outline-none resize-none focus:ring-2 focus:ring-green-500"
              rows={3}
            />
          </div>

          <div className="mb-6">
            <label className="flex items-center gap-3 cursor-pointer">
              <input
                type="checkbox"
                checked={isPublic}
                onChange={(e) => setIsPublic(e.target.checked)}
                className="w-5 h-5"
              />
              <span>Ustaw playlistę jako publiczną</span>
            </label>
          </div>

          <div className="flex gap-3">
            <button
              type="button"
              onClick={() => setIsOpen(false)}
              className="flex-1 py-3 border border-gray-700 rounded-full font-semibold hover:border-white"
            >
              Anuluj
            </button>
            <button
              type="submit"
              disabled={!name.trim()}
              className="flex-1 py-3 bg-green-500 rounded-full text-black font-semibold hover:bg-green-400 disabled:bg-gray-700 disabled:text-gray-500"
            >
              Utwórz
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jakie biblioteki instalujemy do testowania komponentów React?

  2. 2. Do czego służy fireEvent.click() w teście?

Zadania praktyczne w grze

  • Klikanie w kolejności

    Kliknij elementy, aby zbudować import narzędzi testowych:

  • Układanie w pionie

    Uporządkuj kroki testu sprawdzającego kliknięcie przycisku:

Przydatne artykuły