Aller au contenu principal

Module 13 – Tests et bonnes pratiques

Niveau 5.2 – Laravel Inertia (React & Vue)


Objectif

À la fin de ce module vous saurez :

  • Tester les pages Inertia côté Laravel avec assertInertia() : vérifier le composant rendu et la présence/forme des props sans exécuter de JavaScript.
  • Tester les composants React ou Vue (pages, layouts) avec Vitest (ou Jest) et Testing Library en leur passant des props simulées.
  • Appliquer des bonnes pratiques : structure des dossiers, nommage cohérent, typage TypeScript des props, accessibilité (labels, rôles, focus), et performance (lazy loading, partial reloads).

Nous donnons des exemples de tests PHP et des pistes pour les tests front (React/Vue), puis une checklist de bonnes pratiques.


Tests Laravel – assertInertia

Laravel propose (via le package inertia-laravel ou des helpers de test) une assertion assertInertia qui permet de vérifier que la réponse est bien une réponse Inertia et d’inspecter le composant et les props sans lancer le navigateur ni exécuter React/Vue.

Exemple : test que la route GET /users renvoie la page Users/Index avec une prop users contenant des données paginées.

// tests/Feature/UserControllerTest.php
namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class UserControllerTest extends TestCase
{
use RefreshDatabase;

public function test_users_index_returns_inertia_page(): void
{
User::factory()->count(3)->create();

$response = $this->get(route('users.index'));

$response->assertStatus(200);
$response->assertInertia(fn ($page) => $page
->component('Users/Index')
->has('users')
->has('users.data')
->where('users.current_page', 1)
->where('users.per_page', 10)
);
}
}
  • assertInertia(fn ($page) => ...) : la closure reçoit un objet Assert (ou équivalent selon votre version) sur lequel vous enchaînez component(), has(), where(), etc. component('Users/Index') vérifie que le nom du composant est bien Users/Index. has('users') vérifie la présence de la clé users dans les props. where(...) vérifie une valeur précise.
  • Vous pouvez aussi vérifier une partie des users.data (ex. premier utilisateur a un name non vide) en utilisant where('users.data.0.name', '!=', '') ou des helpers similaires.

Test avec filtres :

public function test_users_index_respects_search_parameter(): void
{
User::factory()->create(['name' => 'Alice']);
User::factory()->create(['name' => 'Bob']);

$response = $this->get(route('users.index', ['search' => 'Alice']));

$response->assertInertia(fn ($page) => $page
->component('Users/Index')
->has('users.data')
->where('users.data.0.name', 'Alice')
);
}

Ces tests ne chargent pas React/Vue ; ils vérifient uniquement que Laravel renvoie la bonne structure (composant + props). C’est rapide et suffisant pour s’assurer que le contrôleur et les données sont corrects.


Tests des composants React / Vue (Vitest + Testing Library)

Pour tester le rendu et le comportement des composants de page (affichage des données, soumission de formulaire, affichage des erreurs), vous pouvez utiliser Vitest (ou Jest) avec @testing-library/react ou @testing-library/vue. Vous montez le composant en lui passant des props (simulant les props Inertia) et vous faites des assertions sur le DOM ou sur les appels à router / useForm (en mockant Inertia).

Exemple React (idée) :

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import Index from '@/Pages/Users/Index';

describe('Users/Index', () => {
it('renders user list', () => {
const users = {
data: [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
],
current_page: 1,
last_page: 1,
links: [],
};
render(<Index users={users} filters={{}} />);
expect(screen.getByText('Alice')).toBeInTheDocument();
expect(screen.getByText('Bob')).toBeInTheDocument();
});
});

Pour que le composant s’affiche, il faut souvent mocker les dépendances Inertia (Link, usePage, router) pour qu’elles ne lèvent pas d’erreur. La doc Inertia et les guides de test (Vitest, Testing Library) donnent des exemples de setup. L’idée ici est de montrer que vous pouvez tester les pages comme des composants classiques en fournissant des props.


Bonnes pratiques – structure et nommage

  • Pages/ : un fichier par page, regroupés par domaine (Users/, Articles/, Settings/). Nommer Index pour la liste, Show pour le détail, Create / Edit pour les formulaires.
  • Layouts/ : AppLayout (zone connectée), GuestLayout (login, register, accueil). Réutiliser le même layout pour toutes les pages d’un même « type ».
  • Composants réutilisables : si vous avez des boutons, cartes, formulaires réutilisables, les placer dans Components/ (ex. Pagination, Button, Input) et les importer dans les pages ou layouts.
  • Nommage des routes : cohérent avec Laravel (users.index, users.show, users.store, etc.) et utilisation de route() (Ziggy) côté front pour éviter les URLs en dur.

Bonnes pratiques – typage (TypeScript)

En TypeScript, définir des interfaces pour les props de chaque page (ou des types globaux partagés) améliore la maintenabilité et évite les erreurs. Exemple :

// types/index.d.ts ou à côté de la page
export interface User {
id: number;
name: string;
email: string;
created_at: string;
}

export interface PaginatedData<T> {
data: T[];
current_page: number;
last_page: number;
links: { url: string; label: string; active: boolean }[];
}

export interface UsersIndexProps {
users: PaginatedData<User>;
filters: { search?: string; sort?: string; order?: string };
}

Puis dans la page : export default function Index({ users, filters }: UsersIndexProps). Vous pouvez aussi générer ou partager ces types avec le backend (doc API, ou export depuis un script) pour garder une seule source de vérité.


Bonnes pratiques – accessibilité et performance

  • Accessibilité : labels sur tous les champs de formulaire (<label for="...">), role="alert" sur les messages flash, boutons et liens explicites. Désactiver les boutons de soumission pendant processing pour éviter les double-clics. Si vous utilisez des modales, gérer le focus (focus trap) et la fermeture à la touche Echap.
  • Performance : lazy loading des pages (déjà géré par import.meta.glob dans resolve de createInertiaApp : chaque page est chargée à la demande). Utiliser les partial reloads (option only) quand une page a beaucoup de props et qu’une action ne modifie qu’une partie. Éviter de passer des collections énormes en props ; privilégier la pagination et les filtres côté serveur.

À retenir

  • assertInertia() en tests Laravel pour vérifier component et props sans exécuter le front.
  • Tests des composants React/Vue avec Vitest + Testing Library en mockant Inertia et en passant des props.
  • Structure : Pages/, Layouts/, Components/ ; nommage cohérent (Index, Show, Create, Edit).
  • TypeScript : typer les props des pages pour éviter les erreurs et documenter le contrat.
  • Accessibilité : labels, rôles, gestion du focus ; performance : lazy loading, partial reloads, pagination.

Dans le prochain module, nous ferons la synthèse (projet final) et le bonus (ressources, SSR, Breeze/Jetstream).