Skip to content

E2E Modul Admin: Menguji Guard Role dan Bidang Lewat UI

Adityo Guni Waluyo

Tiga spec Playwright buat area admin: login via UI beneran, CRUD sampai hapus permanen dengan verifikasi API, dan guard role/bidang yang diuji di level server.

Ringkasan

Gue kira redirect frontend buat blokir editor dari menu Pengguna, ternyata gampang dibobol kalau backend gak ikut ngejaga. Jadi tes e2e nya ngecek dua lapis, menu yang ngilang di UI dan server yang wajib ngasih 403 kalau dipaksa bikin user. Ada trik login pakai exact biar gak salah klik, isi Tiptap lewat ProseMirror, sama cek hapus data langsung via API.

Skenario yang bikin saya mau nulis spec guard itu sederhana: halaman admin kelihatan sehat, nggak ada error, tapi saya nggak punya bukti otomatis bahwa menu "Pengguna" beneran tersembunyi buat role editor. Nggak ada error merah justru yang bikin gelisah — kepercayaan tanpa test itu cuma asumsi yang belum ketemu bantahannya.

Awalnya saya kira cukup ngecek routing di level frontend. Logikanya sederhana, kalo role-nya editor, redirect aja ke dashboard. Ternyata itu salah besar. User bisa aja memanipulasi URL atau token, dan backend harus tetap solid menahan akses itu. Saya sadar, menulis tes end-to-end di sini bukan soal mengejar happy path. Saya butuh e2e admin modul guard yang spesifik menguji pagar pembatas ini, bukan sekadar memastikan tombol bisa diklik.

Awalnya saya kira cukup ngecek redirect di level frontend: kalau role-nya editor, ya lempar ke dashboard. Ternyata itu jebakan. User bisa memanipulasi URL atau langsung menembak endpoint, dan yang menahan harusnya server. Karena itu spec-nya ngecek dua lapis: menu yang disembunyikan di UI, dan respons 403 dari backend pas user ber-bidang mencoba POST user baru.

Langkah pertama adalah memastikan proses login diuji lewat antarmuka yang nyata, bukan bypass via API. Di file helpers.ts, saya menulis skrip yang mengisi page.getByLabel("Email") dan getByLabel("Kata sandi", { exact: true }).

Kenapa harus exact: true? Karena ada tombol "Tampilkan kata sandi" yang kebetulan memiliki label serupa. Tanpa flag ini, Playwright akan bingung dan tes jadi flaky. Untungnya, fitur auto-waiting Playwright secara otomatis memastikan elemen sudah terlihat, stabil, dan siap menerima event sebelum melakukan klik, sehingga kita tidak perlu menambahkan sleep manual yang rapuh [5].

Di login.spec.ts, saya tidak hanya menguji skenario sukses. Saya juga menambahkan tes untuk failed login, successful login diikuti reload dan logout, serta negative-control helper untuk memastikan state awal benar-benar bersih. Setelah login berhasil, skrip langsung membaca token dari localStorage dengan kunci mude_admin_token. Token ini kemudian disimpan untuk dipakai di step selanjutnya, memastikan state autentikasi tetap konsisten di seluruh rangkaian tes.

CRUD informasi sampai hapus permanen

Di informasi-crud.spec.ts, tantangan muncul saat mengisi form editor. Tiptap rich text bukan input native biasa. Solusinya cukup praktis: klik dulu node .ProseMirror, baru ketik teksnya.

Alur yang saya uji mencakup pembuatan data, ekspektasi redirect ke /admincms/informasi/{id}, hingga judul muncul di daftar. Saya juga menambahkan kasus validasi empty-title untuk memastikan sistem menolak data kosong dengan pesan error yang jelas.

Namun, bagian paling menentukan ada di flow penghapusan. Saat user mengklik hapus permanen, antarmuka hanya menampilkan notifikasi sukses. UI tidak bisa membuktikan ketiadaan data secara absolut. Di sinilah saya memakai pendekatan campuran. Setelah aksi hapus di UI, saya melakukan panggilan API langsung untuk memverifikasi bahwa record tersebut benar-benar hilang dari database [6]. Semua data uji selalu saya beri prefix "E2E" supaya mudah dibersihkan setelah tes selesai dijalankan lewat run_page.sh admin.

Guard yang diuji di level server

File users-guard.spec.ts adalah inti dari pertahanan sistem. Di sini saya memastikan menu Pengguna benar-benar tersembunyi untuk role editor. Jika seseorang memaksa masuk lewat URL, route guard harus langsung melakukan redirect.

Saya juga menambahkan validasi format bidang chip agar selalu Title Case, serta skenario pembuatan user yang terikat pada bidang tertentu. Poin paling penting: ketika user dengan akses bidang mencoba melakukan POST untuk membuat user baru, server wajib membalas dengan respons 403 Forbidden. Ini adalah bukti konkret bahwa pagar pembatas bekerja di level backend, bukan hanya kosmetik di frontend.

Playwright best practices sangat menekankan untuk menguji perilaku yang terlihat oleh user, bukan detail implementasi seperti nama fungsi atau class CSS tertentu [4]. Pendekatan ini membuat tes lebih tahan terhadap perubahan kode di masa depan. Folder frontend/e2e/admin/ kini berisi tiga spec file dan helper yang solid, dan baris INDEX.md untuk admin sudah saya tutup rapat.

Menulis tes itu bukan soal mengejar persentase coverage yang tinggi di laporan CI/CD. Ini soal memastikan pagar pembatas itu benar-benar ada dan kokoh saat seseorang mencoba memanjatnya. Saya lebih memilih punya lima tes yang menguji skenario gagal secara mendalam, daripada lima puluh tes yang hanya mengulang happy path tanpa makna.

Sources

[1] https://playwright.dev/docs/best-practices

[2] https://playwright.dev/docs/actionability

[3] https://playwright.dev/docs/api-testing

Artikel terkait