Episode ini membedah automatic waiting Cypress: cara menunggu elemen tanpa sleep manual, retry-ability pada commands dan assertions, mengatasi timing issues, serta best practices untuk test yang andal dan tidak flaky.

Salah satu alasan utama orang pindah dari Selenium ke Cypress adalah: tidak perlu lagi menulis sleep acak di mana-mana. Episode 5 menjelaskan mengapa. Kalian akan memahami automatic waiting, retry-ability pada commands dan assertions, serta cara menghindari pola yang justru membuat test lambat dan flaky.
Pemahaman di episode ini adalah pembeda antara test yang hidup di tim selamanya dan test yang dihapus karena terlalu sering gagal.
Cypress tidak menjalankan perintah secara membuta. Saat sebuah perintah tidak bisa langsung berhasil — misalnya elemen belum muncul karena fetch masih berjalan — Cypress menunggu dan mencoba lagi sampai berhasil atau waktu habis.
cy.visit("/dashboard");
cy.get("[data-cy=grafik]").should("be.visible");
cy.get("[data-cy=loading-spinner]").should("not.exist");cy.get("[data-cy=grafik]") akan menunggu sampai elemen muncul di DOM, sementara .should("not.exist") menunggu sampai spinner benar-benar hilang. Tidak ada cy.wait(3000) — Cypress tahu kapan keadaan sudah terpenuhi.
Automatic waiting tidak berjalan tanpa batas. Batasnya diatur defaultCommandTimeout, secara bawaan 4000 milidetik. Kalian bisa menyesuaikan per perintah:
cy.get("[data-cy=hasil-analisis]", { timeout: 15000 }).should("be.visible");{ timeout: 15000 } memperpanjang tunggu untuk perintah ini saja menjadi 15 detik — berguna untuk proses yang memang lambat seperti komputasi atau loading besar.
Pola klasik yang menimbulkan flakiness adalah menebak waktu:
cy.wait(5000);
cy.get("[data-cy=hasil]").should("be.visible");cy.wait(5000) menunggu angka tebakan. Di mesin cepat cukup, di mesin lambat tidak. Ganti pola tersebut dengan assertion yang menunggu sampai kondisi terpenuhi:
cy.get("[data-cy=hasil]").should("be.visible");Untuk loading asinkron yang jelas sumbernya, tunggu event jaringan yang sudah ditangkap cy.intercept() — bukan menebak waktu. Kita akan membahas ini mendalam di episode 12.
Hati-hati dengan elemen yang muncul lalu hilang dengan cepat. Menunggu sampai ada lalu berharap masih ada di aksi berikutnya bisa rawan. Lebih aman menunggu kondisi akhir, misalnya konten hasil sudah terlihat, daripada elemen perantara.
Tidak semua perintah di-retry. Yang bisa: cy.get, cy.contains, cy.find, cy.should, dan assertion. Yang tidak di-retry: cy.visit, cy.request, cy.then, dan action seperti cy.click — action hanya dijalankan sekali terhadap elemen yang sudah ditemukan.
cy.get("[data-cy=judul]").should("have.text", "Selamat datang");
cy.wrap([1, 2, 3]).should("have.length", 3);.should("have.text", "Selamat datang") di-retry: Cypress membaca ulang teks elemen sampai cocok atau timeout. Begitu pula cy.wrap(...).should(...) — assertion di dalam should dijalankan ulang secara otomatis.
Untuk logika yang lebih kompleks, pakai callback. Penting: callback harus memakai expect, bukan assert, agar retry bekerja:
cy.get("[data-cy=daftar-produk]").should(($items) => {
expect($items).to.have.length(8);
});expect($items).to.have.length(8) di dalam callback memungkinkan Cypress me-retry seluruh callback sampai assertion lulus. Inilah cara yang benar untuk memvalidasi beberapa elemen sekaligus tanpa menebak waktu render.
Semakin sedikit asumsi timing, semakin stabil test. Prioritaskan:
cy.intercept() dan cy.wait("@alias") untuk alur jaringan.defaultCommandTimeout sesuai kebutuhan aplikasi, bukan memaksakan timeout pendek.cy.wait(ms) dengan angka tebakan.it("menampilkan hasil pencarian", () => {
cy.intercept("GET", "/api/search*").as("search");
cy.get("[data-cy=query]").type("buku");
cy.get("[data-cy=cari]").click();
cy.wait("@search");
cy.get("[data-cy=hasil]").should("have.length.gt", 0);
});Di sini cy.wait("@search") menunggu respons API selesai, lalu assertion memastikan hasil benar-benar dirender. Tidak ada satupun sleep acak — setiap langkah menunggu sampai kondisinya nyata.
Episode 5 mengubah cara kalian berpikir tentang timing: Cypress menunggu kondisi, bukan menebak waktu. Automatic waiting bekerja lewat retry-ability — perintah pencarian elemen dan assertion di-retry sampai berhasil atau timeout. Timing issues diatasi dengan menunggu kondisi akhir, bukan cy.wait(ms) acak.
Inti yang harus dibawa pulang:
defaultCommandTimeout (bawaan 4000 ms) membatasi tunggu; bisa di-override per perintah.cy.visit.cy.wait(ms) dengan angka tebakan adalah sumber flakiness — hindari.cy.intercept() untuk alur asinkron.Di episode 6 selanjutnya kita akan membahas fixtures dan test data — mengelola data test dengan fixtures, memuat JSON lewat cy.fixture(), data-driven testing dengan dataset eksternal, serta mocking data dan request stubs. Test kalian akan mulai memisahkan data dari logika.