Episode ini membahas penyusunan test scenario end-to-end: alur login, checkout, dan multi-page journeys, pengelolaan state application under test dengan cy.session, serta data setup dan teardown yang deterministik.

Component testing memperkuat fondasi. Sekarang kalian merangkainya: skenario end-to-end lengkap dari UI ke backend. Episode 10 membahas menyusun test scenario E2E, alur login, checkout, dan multi-page journeys, mengelola state application under test, serta data setup dan teardown yang deterministik.
E2E adalah lapis paling tinggi dari test pyramid — paling mendekati pengalaman pengguna nyata. Namun kekuatannya dibayar dengan kecepatan dan stabilitas, jadi menyusun skenario dengan disiplin menjadi penentu keberhasilan.
Prinsip utama: satu test memeriksa satu alur pengguna. Jangan menggabungkan login, pencarian, dan checkout dalam satu it raksasa — sulit dilacak saat gagal dan mahal untuk dijalankan ulang.
describe("Alur pencarian produk", () => {
it("menampilkan hasil yang sesuai kata kunci", () => {
cy.visit("/katalog");
cy.get("[data-cy=cari]").type("kopi");
cy.get("[data-cy=hasil]").should("contain.text", "Kopi Gayo");
});
});cy.visit("/katalog") membuka halaman awal skenario. Test ini punya satu tujuan: memastikan pencarian menampilkan hasil yang tepat. Tidak ada langkah yang tidak dibutuhkan.
Susun langkah mengikuti perjalanan pengguna, bukan urutan implementasi. Mulai dari keadaan nyata, lakukan aksi, lalu verifikasi hasil yang terlihat pengguna. Bahasa test sebaiknya bisa dibaca tim non-teknis:
it("memesan produk dari halaman detail", () => {
cy.visit("/produk/kopi-gayo");
cy.get("[data-cy=jumlah]").type("2");
cy.get("[data-cy=masukkan-keranjang]").click();
cy.get("[data-cy=keranjang]").should("have.text", "2");
});cy.get("[data-cy=jumlah]").type("2") meniru pengguna mengisi jumlah pesanan. Setiap baris menggambarkan satu langkah nyata: buka produk, isi jumlah, masukkan keranjang, lalu pastikan keranjang berubah.
Login adalah fondasi banyak skenario. Gunakan custom command yang sudah dibuat di episode 7 agar tidak mengulang detail:
it("berhasil login dan diarahkan ke dashboard", () => {
cy.visit("/login");
cy.get("[data-cy=email]").type("user@example.com");
cy.get("[data-cy=password]").type("rahasia123");
cy.get("[data-cy=submit]").click();
cy.url().should("include", "/dashboard");
cy.contains("Selamat datang").should("be.visible");
});cy.url().should("include", "/dashboard") memverifikasi pengalihan setelah login. Assertion kedua memastikan konten halaman benar-benar dimuat — bukan sekadar URL yang berubah.
Checkout biasanya melintasi beberapa halaman: keranjang, alamat, pembayaran, konfirmasi. Tulis sebagai satu test terorganisir dengan langkah per halaman:
it("menyelesaikan checkout", () => {
cy.visit("/checkout");
cy.get("[data-cy=alamat]").type("Jl. Merdeka 1");
cy.get("[data-cy=lanjut-pembayaran]").click();
cy.get("[data-cy=kartu]").type("4111 1111 1111 1111");
cy.get("[data-cy=konfirmasi]").click();
cy.contains("Pesanan berhasil dibuat").should("be.visible");
cy.url().should("include", "/pesanan-selesai");
});cy.get("[data-cy=lanjut-pembayaran]").click() memindahkan test ke halaman berikutnya. Pola isi form → lanjut → isi form berikutnya → verifikasi akhir adalah inti pengujian journey multi-halaman.
Test yang baik tidak bergantung pada riwayat pengguna sebelumnya. Setiap test menyiapkan state-nya sendiri. Ada beberapa cara: menyuntikkan data lewat task API, men-stub respons, atau menetapkan token sesi:
cy.visit("/");
cy.window().then((win) => {
win.localStorage.setItem("token", "token-tiruan");
});
cy.reload();win.localStorage.setItem("token", "token-tiruan") menyuntikkan sesi tiruan sebelum reload. Dengan cara ini, alur login tidak perlu dijalankan ulang di setiap test — hemat waktu tanpa mengorbankan realisme.
Sebaliknya, kadang kalian justru ingin meniru pengguna yang tetap login antar halaman. Cypress menyediakan cy.session() untuk menyimpan sesi:
beforeEach(() => {
cy.session("login-user", () => {
cy.visit("/login");
cy.get("[data-cy=email]").type("user@example.com");
cy.get("[data-cy=password]").type("rahasia123");
cy.get("[data-cy=submit]").click();
});
});cy.session("login-user", ...) menjalankan blok login sekali lalu menyimpan state sesi. Test berikutnya memakai sesi tersimpan — mempercepat eksekusi sambil tetap meniru pengguna yang sudah login.
Data yang bocor antar test adalah sumber flakiness. Gunakan hooks untuk setup dan teardown yang deterministik:
beforeEach(() => {
cy.task("seedDatabase");
cy.visit("/");
});
afterEach(() => {
cy.task("clearDatabase");
});cy.task("seedDatabase") memanggil fungsi Node di sisi Cypress untuk menyuntikkan data uji. cy.task("clearDatabase") membersihkan setelah test. Kita akan membedah implementasi task API ini di episode 18.
Jika test gagal di tengah jalan, afterEach tetap berjalan — pastikan teardown tidak bergantung pada asumsi test sukses. Hindari mengirim request pembersihan dari dalam test; taruh semuanya di hook agar selalu dieksekusi apa pun hasil test.
Info
Kombinasikan cy.session() dengan cy.task(): sesi untuk state pengguna, task untuk data backend. Pemisahan ini membuat test tetap cepat dan setiap sumber state memiliki pemilik yang jelas.
Episode 10 merangkai interaksi menjadi alur nyata: satu test satu skenario, login dan checkout multi-halaman, pengelolaan state dengan cy.session() dan localStorage, serta setup dan teardown data melalui task API dan hooks.
Inti yang harus dibawa pulang:
it raksasa.cy.session() menyimpan sesi login agar test berikutnya cepat.localStorage, task API, atau stub.Di episode 11 selanjutnya kita akan membahas dashboard dan reporting — fitur Cypress Dashboard, video recording dan screenshots, reporter Mochawesome untuk CI, serta cara menganalisis test runs dan debugging kegagalan. Hasil test kalian mulai bisa dibaca orang lain.