Mengapa testing Inertia.js di Laravel perlu pendekatan yang spesifik
Pada aplikasi Laravel yang menggunakan Inertia.js, respons dari server bukan sekadar HTML biasa dan bukan pula API JSON murni seperti pada arsitektur SPA tradisional. Laravel mengembalikan respons Inertia yang berisi nama komponen halaman, props, serta metadata lain yang akan dipakai oleh frontend untuk merender halaman. Karena itu, strategi pengujian backend sebaiknya tidak berhenti pada pemeriksaan status code atau redirect saja, tetapi juga memverifikasi kontrak antara Laravel dan halaman Inertia.
Kontrak ini penting karena perubahan kecil pada controller, policy, resource, atau validasi dapat membuat halaman frontend gagal bekerja tanpa terlihat jelas dari test yang terlalu dangkal. Misalnya, endpoint masih mengembalikan HTTP 200, tetapi nama komponen berubah, properti penting hilang, struktur props tidak sesuai, atau redirect setelah submit tidak menuju halaman yang benar. Semua ini bisa ditangkap dengan HTTP test yang tepat.
Dalam artikel ini, kita akan membahas cara menguji aplikasi Inertia.js Laravel dengan Pest dan fitur HTTP test Laravel. Fokus utama ada pada backend test yang memastikan:
- komponen Inertia yang dirender sesuai,
- props yang dikirim sesuai struktur dan isi yang diharapkan,
- redirect dan flash message berjalan benar,
- validasi request bekerja,
- alur autentikasi dan endpoint CRUD tetap konsisten.
Pendekatan ini sangat berguna untuk menjaga stabilitas aplikasi saat tim backend dan frontend bekerja paralel.
Dasar strategi: uji kontrak, bukan implementasi frontend
Salah satu kesalahan umum saat menguji aplikasi berbasis Inertia adalah mencoba menjadikan backend test sebagai pengganti test frontend. Padahal tujuan utama HTTP test di Laravel adalah memverifikasi bahwa server mengirim respons Inertia yang benar, bukan memastikan Vue, React, atau Svelte benar-benar merender DOM sesuai harapan. Pengujian DOM frontend tetap relevan di layer lain, misalnya melalui component test atau end-to-end test.
Untuk backend, fokuskan test pada hal-hal berikut:
- Route dan otorisasi: endpoint dapat diakses oleh user yang benar dan ditolak untuk user yang tidak berhak.
- Komponen Inertia: controller merender halaman yang tepat.
- Props: data yang dikirim memiliki field yang diharapkan dan nilainya benar.
- Redirect pasca aksi: create, update, delete, login, logout, dan operasi lain mengarah ke halaman yang tepat.
- Validasi: input invalid menghasilkan session error dan tidak mengubah data.
Pendekatan ini membuat test cukup kuat untuk mendeteksi regresi penting, namun tetap cepat dan mudah dirawat.
Menyiapkan Pest dan fondasi HTTP test
Jika proyek Laravel Anda belum memakai Pest, instalasi dasarnya biasanya sederhana. Pada banyak proyek, Pest dipakai sebagai lapisan sintaks yang lebih ringkas di atas PHPUnit.
composer require pestphp/pest --dev
php artisan pest:installUntuk aplikasi Laravel, Anda juga biasanya membutuhkan pengaturan database test, misalnya menggunakan SQLite in-memory atau database khusus testing. Gunakan trait seperti RefreshDatabase agar setiap test berjalan dalam kondisi bersih.
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);Pada aplikasi Inertia, pastikan Anda mengetahui bagaimana route dan controller mengembalikan halaman. Contoh controller index sederhana:
use Inertia\Inertia;
use App\Models\Post;
public function index()
{
return Inertia::render('Posts/Index', [
'posts' => Post::query()
->latest()
->get(['id', 'title', 'status']),
]);
}Dari sini kita tahu kontrak endpoint GET /posts: harus merender komponen Posts/Index dan mengirim prop posts dengan struktur tertentu. Itulah yang akan kita uji.
Menguji respons Inertia: komponen dan props
Memastikan halaman Inertia yang dirender benar
Pada level paling dasar, test harus memastikan route mengembalikan respons sukses dan komponen Inertia yang sesuai. Dengan Pest, sintaksnya bisa dibuat ringkas dan mudah dibaca.
use App\Models\Post;
use App\Models\User;
use Inertia\Testing\AssertableInertia as Assert;
it('menampilkan halaman daftar post', function () {
$user = User::factory()->create();
Post::factory()->count(3)->create();
$this->actingAs($user)
->get(route('posts.index'))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('Posts/Index')
->has('posts', 3)
);
});Test di atas memverifikasi dua hal penting: halaman yang dirender benar dan jumlah data pada prop posts sesuai. Ini jauh lebih berguna daripada hanya memeriksa assertOk().
Memeriksa struktur dan nilai props
Sering kali Anda perlu memverifikasi bukan hanya jumlah item, tetapi juga struktur data yang dikirim. Ini penting jika frontend mengandalkan field tertentu seperti id, title, atau can.edit.
it('mengirim props post dengan struktur yang dibutuhkan halaman', function () {
$user = User::factory()->create();
$post = Post::factory()->create([
'title' => 'Belajar Inertia Testing',
'status' => 'published',
]);
$this->actingAs($user)
->get(route('posts.index'))
->assertInertia(fn (Assert $page) => $page
->component('Posts/Index')
->has('posts', 1)
->has('posts.0', fn (Assert $page) => $page
->where('id', $post->id)
->where('title', 'Belajar Inertia Testing')
->where('status', 'published')
->etc()
)
);
});Kenapa penting memakai pemeriksaan selektif? Karena terlalu banyak mengunci seluruh payload dapat membuat test rapuh. Jika Anda menguji semua field, perubahan kecil yang tidak relevan dapat membuat test gagal. Sebaliknya, jika terlalu longgar, bug penting bisa lolos. Praktik yang sehat adalah memeriksa field yang menjadi kontrak utama halaman, lalu gunakan etc() bila memang struktur bisa berkembang.
Menguji halaman detail atau edit
Untuk endpoint seperti show atau edit, pastikan data yang ditampilkan memang data milik resource yang diminta.
it('menampilkan halaman edit post yang benar', function () {
$user = User::factory()->create();
$post = Post::factory()->create();
$this->actingAs($user)
->get(route('posts.edit', $post))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('Posts/Edit')
->where('post.id', $post->id)
->where('post.title', $post->title)
);
});Ini berguna untuk menangkap kesalahan route model binding, transformasi resource, atau pembatasan field yang tidak sengaja berubah.
Menguji create, update, delete: redirect, validasi, dan efek ke database
Uji create dengan redirect yang benar
Pada aplikasi Inertia, operasi tulis biasanya akan mengembalikan redirect ke halaman tertentu, sering disertai flash message. Untuk itu, pengujian sebaiknya memeriksa tiga hal sekaligus: request berhasil, data tersimpan, dan redirect sesuai.
it('membuat post baru lalu redirect ke halaman index', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)->post(route('posts.store'), [
'title' => 'Post Baru',
'content' => 'Isi artikel',
'status' => 'draft',
]);
$response->assertRedirect(route('posts.index'));
$this->assertDatabaseHas('posts', [
'title' => 'Post Baru',
'status' => 'draft',
]);
});Jika controller menambahkan flash message ke session, Anda juga bisa memverifikasinya:
$response->assertSessionHas('success', 'Post berhasil dibuat.');Pemeriksaan ini memastikan pola interaksi khas Inertia tetap utuh setelah refactor controller atau service layer.
Uji validasi request
Validasi adalah area yang sangat penting karena error validasi akan dikonsumsi halaman Inertia melalui session error bag. Test perlu memastikan input tidak valid menghasilkan error yang benar dan tidak menyimpan data yang rusak.
it('menolak pembuatan post jika title kosong', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)->from(route('posts.create'))
->post(route('posts.store'), [
'title' => '',
'content' => 'Isi artikel',
'status' => 'draft',
]);
$response->assertSessionHasErrors(['title']);
$response->assertRedirect(route('posts.create'));
$this->assertDatabaseCount('posts', 0);
});Kesalahan umum di sini adalah hanya memeriksa assertSessionHasErrors tanpa memverifikasi bahwa database tetap tidak berubah. Padahal bug pada service atau repository bisa saja tetap menyimpan data sebelum exception atau validasi tertentu terjadi.
Uji update dan delete
Operasi update dan delete juga perlu memeriksa redirect dan perubahan database.
it('mengubah post lalu redirect', function () {
$user = User::factory()->create();
$post = Post::factory()->create(['title' => 'Judul Lama']);
$response = $this->actingAs($user)
->put(route('posts.update', $post), [
'title' => 'Judul Baru',
'content' => $post->content,
'status' => 'published',
]);
$response->assertRedirect(route('posts.index'));
$this->assertDatabaseHas('posts', [
'id' => $post->id,
'title' => 'Judul Baru',
'status' => 'published',
]);
});it('menghapus post lalu redirect', function () {
$user = User::factory()->create();
$post = Post::factory()->create();
$response = $this->actingAs($user)
->delete(route('posts.destroy', $post));
$response->assertRedirect(route('posts.index'));
$this->assertDatabaseMissing('posts', ['id' => $post->id]);
});Jika ada policy atau ownership, tambahkan test penolakan akses agar kontrak keamanan tetap terjaga.
Menguji auth flow dan proteksi route pada aplikasi Inertia
Pada banyak aplikasi Inertia, alur autentikasi seperti login, logout, halaman dashboard, dan proteksi route adalah area yang rawan regresi. HTTP test dapat memverifikasi apakah user tamu diarahkan ke login, user valid bisa masuk, dan user yang tidak berhak tidak dapat mengakses halaman tertentu.
Guest diarahkan ke login
it('mengalihkan guest ke halaman login saat mengakses posts', function () {
$this->get(route('posts.index'))
->assertRedirect(route('login'));
});Login berhasil dan redirect sesuai
it('mengizinkan user login dan redirect ke dashboard', function () {
$user = User::factory()->create([
'password' => bcrypt('password'),
]);
$response = $this->post(route('login.store'), [
'email' => $user->email,
'password' => 'password',
]);
$response->assertRedirect(route('dashboard'));
$this->assertAuthenticatedAs($user);
});Halaman dashboard merender komponen yang tepat
it('menampilkan dashboard inertia untuk user terautentikasi', function () {
$user = User::factory()->create();
$this->actingAs($user)
->get(route('dashboard'))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('Dashboard')
);
});Dengan pola seperti ini, Anda memastikan alur auth tidak hanya lolos dari sisi middleware, tetapi juga tetap merender halaman Inertia yang diharapkan oleh frontend.
Praktik terbaik saat menulis test Inertia dengan Pest
1. Uji kontrak minimum yang penting
Jangan memverifikasi semua field bila tidak perlu. Pilih field yang memang dibutuhkan halaman. Ini menjaga test tetap kuat namun tidak rapuh terhadap perubahan kecil yang sah.
2. Pakai factory yang realistis
Gunakan model factory untuk menyiapkan data yang mendekati kondisi produksi. Hindari setup yang terlalu sederhana bila aplikasi Anda memiliki relationship, status, ownership, atau policy yang kompleks.
3. Gabungkan assert respons, database, dan session
Untuk endpoint mutasi, satu test yang baik biasanya memeriksa lebih dari satu sisi: status/redirect, perubahan database, dan session error atau flash message. Ini memberi keyakinan lebih tinggi dibanding test yang hanya memeriksa salah satunya.
4. Pisahkan test halaman baca dan aksi tulis
Test index, show, edit berfokus pada komponen dan props. Test store, update, destroy berfokus pada validasi, efek ke database, dan redirect. Pemisahan ini membuat intent test lebih jelas.
5. Tambahkan skenario otorisasi
Jika aplikasi memiliki policy, periksa bahwa user yang tidak berhak menerima respons yang sesuai, misalnya 403. Ini bagian penting dari kontrak backend, terutama bila frontend hanya menyembunyikan tombol tanpa perlindungan server yang nyata.
it('melarang user mengedit post milik user lain', function () {
$owner = User::factory()->create();
$otherUser = User::factory()->create();
$post = Post::factory()->for($owner)->create();
$this->actingAs($otherUser)
->get(route('posts.edit', $post))
->assertForbidden();
});Debugging: saat test Inertia gagal
Ketika assertion Inertia gagal, penyebabnya sering berada di salah satu area berikut:
- Nama komponen berubah, misalnya dari
Posts/IndexmenjadiPost/Index. - Props dibungkus resource sehingga struktur JSON berubah.
- Middleware share data menambah atau mengubah props global.
- Redirect berbeda karena perubahan flow setelah create/update.
- Auth atau policy memblokir request sehingga respons bukan halaman Inertia yang diharapkan.
Beberapa tips debugging yang praktis:
- Gunakan dump pada payload respons jika perlu untuk melihat struktur props aktual.
- Periksa route name dan policy yang aktif.
- Pastikan factory membuat data yang memenuhi syarat scope query, misalnya status
publishedbila controller memfilter data. - Jika memakai form request atau resource, periksa apakah transformasi field berubah.
Prinsip pentingnya: ketika test Inertia gagal, jangan hanya memperbaiki assertion. Pastikan Anda memahami apakah kontrak memang berubah secara sengaja atau ada regresi yang harus diperbaiki.
Penutup
Testing aplikasi Laravel yang menggunakan Inertia.js paling efektif bila difokuskan pada kontrak antara backend dan halaman Inertia. Dengan HTTP test dan Pest, Anda bisa memverifikasi bahwa route mengembalikan komponen yang tepat, props memiliki struktur yang benar, validasi bekerja, redirect sesuai, dan alur autentikasi tetap aman.
Pendekatan ini bukan pengganti test frontend, tetapi lapisan penting yang menjaga integrasi Laravel dan Inertia tetap stabil. Untuk aplikasi CRUD dan auth flow, kombinasi assertInertia, assertRedirect, assertSessionHasErrors, dan assertDatabaseHas biasanya sudah cukup kuat untuk menangkap regresi yang paling sering terjadi.
Jika Anda merawat aplikasi Inertia dalam jangka panjang, test semacam ini akan sangat membantu saat refactor controller, mengganti resource transformer, menambah policy, atau mengubah struktur props. Backend tetap bisa bergerak cepat tanpa memutus kontrak yang diandalkan frontend.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!