Aller au contenu principal

Module 11 – Tests Livewire

Niveau 5.1 – Laravel Livewire


Livewire::test(), set(), call(), assertions (assertSet, assertSee, assertRedirect, assertHasErrors). En fin de module : tests avec BDD (RefreshDatabase), mocking, couverture des policies.


Objectif

À la fin de ce module, vous saurez :

  • Tester les composants Livewire avec PHPUnit (ou Pest) en utilisant Livewire::test(Composant::class) pour instancier le composant en isolation (sans navigateur).
  • Simuler les actions utilisateur : set('property', $value) pour modifier une propriété, call('methodName', ...args) pour appeler une méthode, et assertSet('property', $value) pour vérifier l’état après l’action.
  • Vérifier le rendu avec assertSee(), assertDontSee(), et assertViewIs() ; vérifier les redirections avec assertRedirect() et les messages flash avec assertSessionHas().
  • Tester des formulaires (remplir les champs, soumettre, vérifier la BDD ou les messages) et des listes (pagination, filtres) pour valider le comportement côté serveur.

Pourquoi tester les composants Livewire ?

Les composants Livewire mélangent logique PHP (état, méthodes, validation, Eloquent) et rendu Blade. Les tests Livewire::test() exécutent cette logique côté serveur sans lancer de navigateur : vous appelez les méthodes, vous modifiez les propriétés, vous vérifiez l’état et le HTML rendu. Cela permet de détecter les régressions (ex. une validation qui ne bloque plus, une action qui ne redirige plus) et de documenter le comportement attendu.


Livewire::test() et chaînage

Livewire::test(Composant::class) retourne une instance de Testable sur laquelle vous enchaînez des appels et des assertions. Vous pouvez passer des paramètres au composant (pour mount()) en second argument :

use Livewire\Livewire;

Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1);
  • assertSet('count', 0) : vérifie que la propriété count vaut 0 (état initial).
  • call('increment') : simule l’appel à la méthode increment() du composant.
  • assertSet('count', 1) : après l’appel, count doit valoir 1.

Vous pouvez aussi set des propriétés avant d’appeler une méthode (ex. remplir un formulaire) :

Livewire::test(RegisterUser::class)
->set('name', 'Jean')
->set('email', 'jean@example.com')
->call('register')
->assertSessionHas('message');

Exemple : test du compteur

<?php

namespace Tests\Feature;

use App\Livewire\Counter;
use Livewire\Livewire;
use Tests\TestCase;

class CounterTest extends TestCase
{
public function test_counter_starts_at_zero(): void
{
Livewire::test(Counter::class)
->assertSet('count', 0);
}

public function test_counter_increments(): void
{
Livewire::test(Counter::class)
->call('increment')
->assertSet('count', 1)
->call('increment')
->assertSet('count', 2);
}
}

Pas besoin de base de données ni de requête HTTP : le composant est exécuté en mémoire.


Exemple : test d’un formulaire avec validation

Composant RegisterUser : propriétés name, email, méthode register() qui appelle validate() et enregistre l’utilisateur (ou flash un message). On teste que la validation rejette un email invalide et que, avec des données valides, register() enregistre et met un message en session.

public function test_register_validates_email(): void
{
Livewire::test(RegisterUser::class)
->set('name', 'Jean')
->set('email', 'invalid-email')
->call('register')
->assertHasErrors(['email']);
}

public function test_register_creates_user_and_flashes_message(): void
{
Livewire::test(RegisterUser::class)
->set('name', 'Jean')
->set('email', 'jean@example.com')
->set('password', 'password123')
->set('password_confirmation', 'password123')
->call('register')
->assertHasNoErrors()
->assertSessionHas('message');
$this->assertDatabaseHas('users', ['email' => 'jean@example.com']);
}
  • assertHasErrors(['email']) : vérifie que la validation a échoué pour le champ email.
  • assertHasNoErrors() : après register(), aucune erreur de validation.
  • assertSessionHas('message') : le message flash est bien présent.
  • assertDatabaseHas : l’utilisateur a été créé en BDD (nécessite une BDD de test, ex. RefreshDatabase).

Assertions utiles

AssertionRôle
assertSet('property', $value)La propriété a la valeur attendue.
assertSee('texte') / assertDontSee('texte')Le HTML rendu contient (ou ne contient pas) le texte.
assertViewIs('livewire.vue-name')La vue rendue est la bonne.
assertRedirect($uri)Le composant a redirigé vers l’URL donnée.
assertSessionHas('key')La session contient la clé (ex. message flash).
assertHasErrors(['field'])La validation a des erreurs sur le(s) champ(s).
assertHasNoErrors()Aucune erreur de validation.

Vous pouvez combiner set(), call() et ces assertions pour couvrir les scénarios : chargement initial, action avec données valides, action avec données invalides, redirection après succès, etc.


À retenir

  • Livewire::test(Composant::class) pour instancier le composant en test. Enchaîner set(), call() et *assert()**.
  • set('property', $value) pour simuler une mise à jour de propriété ; call('methodName', ...args) pour simuler une action (clic, submit).
  • assertSet() pour l’état ; assertSee() / assertDontSee() pour le rendu ; assertRedirect(), assertSessionHas(), assertHasErrors() pour les effets de bord.
  • Tester au moins les chemins critiques : validation, actions qui modifient les données, autorisation (ex. authorize() qui doit bloquer un utilisateur non autorisé).

Approfondissement

  • Tests avec base de données : utilisez RefreshDatabase dans votre TestCase pour que chaque test parte d’une BDD vide. Créez les données nécessaires (User::factory(), Post::factory()) puis Livewire::test(Composant::class). Pour tester authorize(), connectez un utilisateur sans le droit ($this->actingAs($user)) et vérifiez que call('delete', $id) lève une exception ou que assertStatus(403) est vérifié (selon comment Livewire expose l’échec d’autorisation).
  • Mocking : si votre composant dépend d’un service (ex. envoi d’email), mockez-le dans le test pour ne pas envoyer de vrais emails : Mail::fake(); puis Mail::assertSent(...) après l’action.
  • Couverture : visez au moins les actions publiques (méthodes appelées par wire:click / wire:submit) et les chemins (succès vs validation échouée, autorisé vs non autorisé). Les tests Livewire sont rapides ; en avoir une dizaine par composant critique est raisonnable.

Dans le prochain module, nous faisons un aperçu de l’écosystème : Livewire 3 (attributs, événements), Volt (composants single-file), et Alpine.js (interactivité côté client).