Episode ini membahas perluasan Cypress: menambahkan custom commands di commands.js dengan Cypress.Commands.add, membuat helper reusable untuk alur test, mengatur baseUrl dan environment vars, serta mengorganisasi test utilities.

Semakin banyak test yang ditulis, semakin banyak pola berulang: login, menyiapkan data, membuka halaman tertentu. Episode 7 mengajarkan cara mengemas pola itu menjadi custom commands dan utilities agar test tetap singkat, konsisten, dan mudah dirawat.
Custom commands juga memungkinkan abstraksi teknis: test membaca cy.login("admin"), sedangkan detail mekanisme login tersembunyi di satu tempat.
Custom command didefinisikan lewat Cypress.Commands.add. Lokasinya di cypress/support/commands.js:
Cypress.Commands.add("login", (email, password) => {
cy.visit("/login");
cy.get("[data-cy=email]").type(email);
cy.get("[data-cy=password]").type(password);
cy.get("[data-cy=submit]").click();
cy.url().should("include", "/dashboard");
});Cypress.Commands.add("login", (email, password) => { ... }) mendaftarkan command baru bernama login yang menerima dua argumen. Semua test dalam project kini bisa memanggil cy.login(...).
Agar command dimuat, pastikan commands.js di-import oleh file support. Secara bawaan cypress/support/e2e.js memuatnya:
import "./commands";import "./commands" memastikan seluruh custom commands tersedia sebelum spec dijalankan.
it("menambahkan produk ke keranjang", () => {
cy.login("user@example.com", "rahasia123");
cy.get("[data-cy=produk-pertama]").click();
cy.contains("Ditambahkan ke keranjang").should("be.visible");
});cy.login("user@example.com", "rahasia123") menggantikan lima baris interaksi login dengan satu baris. Setiap test yang butuh login kini konsisten — dan jika alur login berubah, kalian cukup mengubah satu definisi.
Selain command, kalian bisa memakai fungsi JavaScript biasa sebagai helper. Simpan di cypress/support/utils.js:
export const formatHarga = (angka) =>
`Rp${angka.toLocaleString("id-ID")}`;
export const buatEmailAcak = () =>
`user-${Date.now()}@example.com`;Lalu import di spec file:
import { formatHarga, buatEmailAcak } from "../support/utils";
it("menampilkan harga terformat", () => {
cy.contains(formatHarga(45000)).should("be.visible");
});
it("mendaftar dengan email acak", () => {
cy.get("[data-cy=email]").type(buatEmailAcak());
});formatHarga(45000) dan buatEmailAcak() adalah pure function — mudah diuji sendiri dan bebas dari state browser. Ini tempat yang tepat untuk logika murni yang tidak butuh akses Cypress.
baseUrl sudah kita set di episode 3. Nilainya membuat cy.visit("/") ringkas dan memudahkan perpindahan environment:
module.exports = defineConfig({
e2e: {
baseUrl: "http://localhost:3000",
},
});Untuk nilai yang berubah antar environment, gunakan env vars. Tetapkan di konfigurasi atau lewat CLI:
npx cypress run --env apiBaseUrl=http://localhost:8080Akses dari test dengan Cypress.env:
const api = Cypress.env("apiBaseUrl");
cy.intercept("GET", `${api}/produk`).as("produk");Cypress.env("apiBaseUrl") membaca nilai yang dikirim lewat --env. Untuk nilai rahasia, jangan tulis langsung di config — kita akan membahas pengelolaan credential aman di episode 13.
Seiring tumbuhnya project, pisahkan tanggung jawab:
cypress/support/
commands.js
commands/
auth.js
checkout.js
utils.js
e2e.jsimport "./commands/auth";
import "./commands/checkout";import "./commands/auth" memuat command autentikasi. Dengan pola ini, tim bisa menambah command per domain tanpa membuat satu file raksasa.
Beberapa pedoman menjaga command tetap sehat:
Episode 7 memperluas bahasa Cypress: custom commands dengan Cypress.Commands.add di commands.js, helper murni untuk logika yang bisa dipakai ulang, pengelolaan baseUrl dan environment vars lewat --env dan Cypress.env, serta organisasi support yang terbagi per domain.
Inti yang harus dibawa pulang:
Cypress.Commands.add("nama", fn) mendaftarkan command yang bisa dipanggil cy.nama().cypress/support/e2e.js memuat commands.js agar command tersedia global.utils.js untuk logika non-browser seperti format harga.--env dan dibaca dengan Cypress.env.Di episode 8 selanjutnya kita akan membahas advanced interactions — handling iframes, popups, dan multiple windows, drag and drop, uploads, keyboard events, testing single-page apps, serta network stubbing dengan cy.intercept(). Interaksi test kalian akan menyentuh skenario nyata yang rumit.