Livewire to potężne narzędzie w ekosystemie Laravel, które pozwala na tworzenie dynamicznych i interaktywnych komponentów bez konieczności pisania dużej ilości JavaScriptu. Wraz z rosnącą złożonością aplikacji pojawia się potrzeba testowania komponentów, aby mieć pewność, że działają one zgodnie z oczekiwaniami i zachowują się poprawnie w różnych scenariuszach.
W tym artykule omówimy, jak testować komponenty Livewire – zarówno jednostkowo, jak i integracyjnie, wykorzystując wbudowane narzędzia Laravel i Livewire. Przedstawimy praktyczne przykłady kodu oraz zaproponujemy ćwiczenia, które pomogą Ci utrwalić zdobytą wiedzę.
Artykuł jest kontynuacją poprzednich wpisów dotyczących Livewire:
- Livewire w Laravel – wprowadzenie
- Tworzenie i zarządzanie stanem komponentów w Livewire
- Obsługa formularzy i walidacja w Livewire
- Zaawansowana praca z danymi (CRUD w Livewire)
- Eventy i komunikacja między komponentami w Livewire
- Usprawnienia i optymalizacja w Livewire
- Przekazywanie parametrów, Sloty i re-używalne komponenty w Livewire
- Praca z plikami i uploady w Livewire
Podstawy testowania w Laravelu (w kontekście Livewire)
Laravel domyślnie dostarcza strukturę do testów w folderze tests, dzieląc je na:
Unit– testy jednostkowe (testujące głównie logikę, pojedyncze metody czy helpery).Feature(lubIntegration) – testy integracyjne, które mogą dotyczyć całego przepływu w aplikacji (w tym bazy danych, widoków, czy komponentów Livewire).
Dla Livewire warto wykorzystywać w szczególności testy typu Feature, aby sprawdzić zachowanie całego komponentu (czy reaguje na akcje, waliduje dane, renderuje odpowiednie fragmenty HTML).
W pliku composer.json znajduje się standardowa komenda do uruchamiania testów:
composer test
lub bezpośrednio:
php artisan test
lub:
./vendor/bin/phpunit
Metoda Livewire::test()
Testowanie komponentów Livewire opiera się na statycznej metodzie Livewire::test('NazwaKomponentu'). Pozwala ona utworzyć instancję testową komponentu, na której można wywoływać metody, ustawiać właściwości (->set()) oraz sprawdzać wyniki (->assertSee(), ->assertEmitted(), ->assertOk(), itp.).
Prosty przykład testu może wyglądać tak (zakładając, że mamy komponent Counter):
call('increment')
->assertSet('count', 1);
}
}
Wyjaśnienie:
Livewire::test('counter')– tworzy instancję testową komponentu o nazwiecounter.->call('increment')– wywołuje publiczną metodęincrement()w komponencie.->assertSet('count', 1)– sprawdza, czy właściwość$countw komponencie ma wartość1po wywołaniu metody.
Testowanie akcji komponentów
W Livewire testujemy nie tylko końcowy stan komponentu, ale również poszczególne metody i przepływy. Załóżmy, że w naszym komponencie mamy metodę submit() dokonującą jakichś operacji (np. zapis w bazie, walidacja).
Przykład testu z walidacją
Zakładamy, że w komponencie RegisterForm mamy publiczną właściwość $email, $password oraz metodę submit(), która waliduje dane.
public function submit()
{
$this->validate([
'email' => 'required|email',
'password' => 'required|min:8'
]);
// Zapis do bazy
// ...
}
Test, który sprawdzi błąd walidacji oraz poprawne przejście:
set('email', 'not-an-email')
->set('password', '12345678')
->call('submit')
->assertHasErrors(['email' => 'email']);
}
/** @test */
public function it_registers_user_with_valid_data()
{
Livewire::test('register-form')
->set('email', 'test@example.com')
->set('password', 'secretPass123')
->call('submit')
->assertHasNoErrors()
->assertRedirect('/dashboard');
// Zakładamy, że po poprawnej rejestracji przekierowujemy na /dashboard
}
}
->assertHasErrors(['email' => 'email'])– sprawdzamy, czy wystąpił błąd walidacji na poluemail(konkretnie regułaemail).->assertHasNoErrors()– oczekujemy, że brak błędów przy poprawnych danych.->assertRedirect('/dashboard')– jeśli w metodziesubmit()następuje przekierowanie w razie sukcesu, test to sprawdzi.
Sprawdzanie tekstu/HTML renderowanego przez komponent
Możemy też sprawdzić, czy Livewire wyrenderował odpowiednie fragmenty HTML w widoku, np. czy pojawia się tekst Witaj, użytkowniku!:
Livewire::test('welcome-panel')
->assertSee('Witaj, użytkowniku!')
->assertSeeHtml('');
->assertSee()– sprawdza, czy w wyrenderowanym HTML występuje podany ciąg tekstu (bez względu na otaczające tagi).->assertSeeHtml()– ściśle sprawdza, czy podany fragment HTML jest obecny w wyrenderowanym kodzie.
Możemy także sprawdzać, czy jakiś tekst nie występuje:
->assertDontSee('Błąd logowania');
Organizacja testów
W standardowym podejściu Laravel:
Testy jednostkowe (Unit) trafiają do folderu
tests/Unit.- Testujemy tu raczej logikę niezależną od bazy danych czy widoku (np. metody formatujące dane, transformery).
- Rzadziej spotkamy tam testy Livewire, bo komponent zwykle ma jednak interakcję z widokiem czy sesją.
Testy funkcjonalne (Feature) trafiają do folderu
tests/Feature.- Tutaj testujemy całe komponenty Livewire: ich metody, walidację, renderowanie widoków, komunikację z bazą itd.
Przykładowo:
tests
├── Feature
│ ├── Livewire
│ │ └── CounterTest.php
│ │ └── RegisterFormTest.php
│ └── ...
└── Unit
└── SomeUtilityTest.php
Dla testów Livewire można wydzielić osobny folder tests/Feature/Livewire, by zachować porządek.
Ćwiczenia
Ćwiczenie A: Napisać test jednostkowy (Feature) dla komponentu licznika
Załóżmy, że mamy komponent Counter, który ma prostą logikę – publiczne pole $count, metodę increment(), która zwiększa liczbę o 1, oraz metodę decrement(), która zmniejsza liczbę o 1.
1. Kod komponentu (przykładowy)
count++;
}
public function decrement()
{
$this->count--;
}
public function render()
{
return view('livewire.counter');
}
}
2. Test: CounterTest.php
assertSet('count', 0);
}
/** @test */
public function it_increments_the_counter_by_one()
{
Livewire::test('counter')
->call('increment')
->assertSet('count', 1);
}
/** @test */
public function it_decrements_the_counter_by_one()
{
Livewire::test('counter')
->call('decrement')
->assertSet('count', -1);
}
}
W powyższym teście sprawdzamy:
- Czy początkowo
$countwynosi0? - Czy wywołanie metody
increment()zmienia tę wartość na1? - Czy
decrement()zmienia ją na-1?
Aby uruchomić test:
php artisan test --filter=CounterTest
Ćwiczenie B: Testy walidacji w formularzu rejestracji
Załóżmy, że mamy komponent RegisterForm, który posiada pola: $name, $email, $password, a także metodę submit(), która waliduje dane i w razie sukcesu tworzy użytkownika w bazie.
1. Kod komponentu (przykładowy)
'required|min:3',
'email' => 'required|email',
'password' => 'required|min:8',
];
public function submit()
{
$this->validate();
// Tworzymy użytkownika w bazie
User::create([
'name' => $this->name,
'email' => $this->email,
'password' => bcrypt($this->password),
]);
// Przykład przekierowania
return redirect('/dashboard');
}
public function render()
{
return view('livewire.register-form');
}
}
2. Test: RegisterFormTest.php
set('name', '')
->set('email', 'test@example.com')
->set('password', 'secretPass123')
->call('submit')
->assertHasErrors(['name' => 'required']);
}
/** @test */
public function email_must_be_valid()
{
Livewire::test('register-form')
->set('name', 'Jan Kowalski')
->set('email', 'not-a-valid-email')
->set('password', 'secretPass123')
->call('submit')
->assertHasErrors(['email' => 'email']);
}
/** @test */
public function password_must_be_at_least_8_characters()
{
Livewire::test('register-form')
->set('name', 'Jan Kowalski')
->set('email', 'test@example.com')
->set('password', 'short')
->call('submit')
->assertHasErrors(['password' => 'min']);
}
/** @test */
public function it_registers_user_with_correct_data()
{
Livewire::test('register-form')
->set('name', 'Jan Kowalski')
->set('email', 'test@example.com')
->set('password', 'secretPass123')
->call('submit')
->assertHasNoErrors()
->assertRedirect('/dashboard');
// Sprawdzamy, czy użytkownik faktycznie został stworzony w bazie
$this->assertDatabaseHas('users', [
'name' => 'Jan Kowalski',
'email' => 'test@example.com'
]);
}
}
Wyjaśnienia:
->assertHasErrors(['name' => 'required'])– sprawdzamy, czy błąd walidacji występuje dla polanamei dotyczy regułyrequired.->assertHasNoErrors()– brak błędów walidacji.->assertDatabaseHas('users', [...])– weryfikujemy, czy w tabeliuserspojawił się właściwy wpis.
Podsumowanie
Testowanie komponentów Livewire jest proste dzięki metodzie Livewire::test(). Można w ten sposób:
- Ustawiać wartości właściwości (
->set('name', 'Jan')). - Wywoływać metody komponentu (
->call('submit')). - Sprawdzać komunikaty o błędach walidacyjnych (
->assertHasErrors()). - Weryfikować renderowany tekst/HTML (
->assertSee()i->assertDontSee()). - Kontrolować, czy wystąpiło przekierowanie (
->assertRedirect()).
Dzięki temu testy stają się źródłem bezpieczeństwa i pewności, że nasze komponenty Livewire – w tym logika walidacji, CRUD, czy mechanizmy uploadu – będą działały zgodnie z oczekiwaniami.
Proponowane rozwiązania ćwiczeń
- Test jednostkowy dla komponentu licznika:
- W sekcji Ćwiczenie A znajdziesz gotowy plik testowy
CounterTest.php, który testuje metodyincrement()idecrement().
- W sekcji Ćwiczenie A znajdziesz gotowy plik testowy
- Testy dla formularza rejestracji:
- W sekcji Ćwiczenie B pokazaliśmy, jak sprawdzić, czy formularz reaguje poprawnie na niepoprawne dane (błędy walidacji) oraz czy tworzy rekord w bazie przy danych poprawnych.
To dopiero początek – w praktyce możesz także testować emisję eventów (->assertEmitted('nazwaZdarzenia')), reakcje w wielu komponentach czy nawet interakcje z bazą i plikami (w połączeniu z mockowaniem dysku). Dzięki takiemu podejściu Twoje aplikacje Livewire będą nie tylko bogate w funkcjonalności, ale i niezawodne w codziennym użytkowaniu.