Konfirmasi yang Menghilang Sendiri: Pelajaran QA Modul Wisata
Sesi QA modul wisata: tombol hapus lewat skrip membuat dialog konfirmasi native langsung hilang, penghapusan dibatalkan diam-diam.
Ringkasan
Tombol hapus di wisata kelihatannya mati, ternyata dialog confirm otomatis di-dismiss Playwright karena nggak ada handler dialog; lewat MCP pakai browser_handle_dialog aman. Dua temuan QA, validasi telepon dan media orphan, akar masalahnya sama dengan modul announcement, jadi dilipat jadi satu keputusan owner lintas modul. Semua hasil diverifikasi langsung ke database dan file, bukan cuma lihat UI.
Tombol hapus di /admincms/wisata saya-klik lewat skrip, lalu dialog konfirmasi native browser muncul sebentar dan langsung hilang. Tidak ada record yang terhapus, tidak ada error di console. Sesi QA di modul wisata sempat tersangkut di sini: aksi hapus terasa "tidak pernah terjadi", padahal tombolnya jelas sudah diklik.
Dugaan pertama saya: dialognya yang rusak, atau environment QA yang flaky. Coba ulang beberapa kali, hasilnya sama persis. Padahal di sesi lain, yang jalan lewat [3] MCP browser dengan tool browser_handle_dialog, dialog yang sama bisa di-accept dengan normal. Bedanya bukan keberuntungan.
Dokumentasi resmi Playwright menjelaskan kontraknya [1], tanpa handler page.on('dialog'), semua dialog native (alert, confirm, prompt) otomatis di-dismiss. Klik lewat jalur JavaScript .click() tidak melalui lapisan yang mengenali dialog MCP, jadi confirm terjawab sebagai cancel sebelum sempat ditampilkan untuk diputuskan. Modal di web itu blocking; kalau tidak di-auto-dismiss, eksekusi halaman berhenti sampai dialog ditangani. Framework memilih menutup otomatis supaya skrip tidak menggantung selamanya; konsekuensinya, intent "terima" harus dinyatakan eksplisit lewat handler atau jalur MCP.
Dari sana pola kerja sesi ini masuk akal: aksi destruktif lewat MCP dengan browser_handle_dialog, aksi di dalam halaman lewat klik biasa tanpa dialog native. Kesalahan "tombol tidak berfungsi" berubah jadi pemahaman bahwa yang salah adalah jalur kliknya.
21 Skenario, 2 Temuan, Satu Pola Generalisasi
Sesi QA modul wisata ini berjalan 21 skenario dan sebagian besar soal bukti, bukan soal keberuntungan interaksi: form negative-first dikirim kosong sampai aria-invalid muncul tanpa satu pun request menyentuh endpoint, latitude 999 ditolak dengan pesan rentang, status Terjadwal tanpa jadwal publish diblok. Yang lolos justru bagian yang paling gampang diremehkan: telepon bukan-angka diterima form, record terbuat, kolom phone di database persis berisi teks non-digit itu. N-4 temuan R4-7, dan ia kembarannya R4-1 di modul informasi: lapisnya beda, entityadmin vs announcementadmin, akar masalahnya satu: validasi format telepon tidak ada di dua editor.
Sesi lengkapnya mencakup 21 skenario: 19 PASS, 2 temuan. Temuan pertama, R4-7: form wisata menerima telepon bukan-angka tanpa validasi format, FE maupun BE — paralel dengan R4-1 di modul informasi, tapi di lapis berbeda (entityadmin vs announcementadmin). Temuan kedua, perluasan R4-5: hapus permanen entity juga meninggalkan media orphan (row + file), akar masalah yang sama dengan modul announcement.
Laporan sesi juga merekam bagian yang tidak ada hubungannya dengan dialog sama sekali, tapi sejalan dengan logika yang sama: percaya artifact, bukan kesan. Lifecycle CRUD divalidasi kolom demi kolom: kategori, alamat, lat/lng hasil auto-parse Maps URL, JSON jam buka tujuh hari, sampai HEX byte en-dash U+2013 yang dicek langsung di baris database supaya yakin tidak berubah jadi karakter lain di perjalanan JSON [4]. Media orphan dari temuan perluasan R4-5 dibuktikan dengan baris database dan file fisik yang tertinggal setelah entity dihapus permanen, lalu dibersihkan lewat endpoint media (respons 200). Angka-angka ini keluar dari artefak mesin, bukan dari ingatan tester.
Karena lapis dan modulnya berbeda tapi akar masalahnya sama, dua temuan ini tidak jadi tiket terpisah per modul. Keduanya dilipat jadi satu keputusan owner lintas modul — R4-1+R4-7 untuk validasi telepon, R4-5 untuk media orphan. Satu keputusan, dua modul tertutup.
Verifikasi yang Tidak Percaya Tampilan
Sisanya sesi pembuktian bahwa data tersimpan benar-benar benar: verifikasi DB kolom-per-kolom setelah save, edit password diverifikasi dengan bcrypt.checkpw [2] bahwa hash baru cocok dengan sandi baru, dan karakter en-dash dicek sampai level byte (HEX E28093) untuk memastikan tidak berubah jadi karakter lain di perjalanan JSON [4]. Tampilan di UI memang perlu dicek, tapi keputusan PASS ditarik dari database dan network, bukan dari kesan layar.
Pelajaran teknisnya sederhana: saat automation "tidak jalan", cek dulu kontrak tool-nya sebelum menuduh aplikasi. Dialog yang menghilang bukan bug aplikasi — itu kontrak Playwright yang bekerja sebagaimana mestinya. Dan kalau temuan QA sendiri terasa tumpang tindih antar modul, jangan langsung menerbitkan tiket per modul. Lipat dulu: temukan akar yang sama, ajukan satu keputusan ke owner, dan biarkan dua modul tertutup oleh satu jawaban.
Sumber
[1] Playwright docs: Dialogs
[2] pyca/bcrypt README
[3] Playwright MCP
[4] Go spec