This lesson catalogs practical, battle-tested custom command patterns you can adapt directly into a real project, covering login, form filling, and data selection.
Building a Command Library
A well-designed set of custom commands acts like a small, project-specific API layer on top of raw Cypress commands, expressing test intent ("log in as an admin", "fill out the shipping form") instead of low-level DOM interaction steps repeated everywhere.
Cypress.Commands.add('getByCy', (selector) => {
return cy.get(`[data-cy="${selector}"]`);
});
// usage, shorter and more consistent than repeating the attribute syntax
cy.getByCy('submit').click();
A tiny helper like this enforces the data-cy selector convention across the entire suite with almost no extra code.
getByCy() standardizes selector usage across an entire suite.
loginByApi() performs authentication via a direct API call, faster than the UI.
fillForm() accepts an object and fills multiple related fields in one call.
seedCart() sets up backend state directly, skipping repetitive UI setup steps.
Reusable Command Patterns Cheat Sheet
Common command shapes worth adding to almost any real Cypress project.
Command
Purpose
cy.getByCy(name)
Consistent, short data-cy selector helper
cy.loginByApi(email, pw)
Fast, UI-independent authentication for setup
cy.fillForm(fields)
Fill multiple form fields from one object
cy.dragAndDrop(from, to)
Reusable drag-and-drop interaction
cy.assertToast(message)
Reusable toast/notification assertion
A Generic fillForm Command
A generic form-filling command accepts an object mapping data-cy names to values, letting each test express only the specific fields it cares about, in a single, readable call.
Toast or notification components are asserted on constantly across a real suite, wrapping the check in a single command avoids duplicating the same selector and assertion chain in dozens of spec files.
Building overly generic commands that try to handle too many unrelated cases with complex option flags.
Duplicating the same multi-step interaction across many spec files instead of extracting a command once identified.
Not giving reusable commands clear, intention-revealing names that read naturally at call sites.
Skipping API-based setup commands and relying on slow, repetitive UI steps for every test's preconditions.
Key Takeaways
A small library of well-named custom commands acts as a project-specific testing API.
Selector helpers, form fillers, and notification assertions are widely reusable across most projects.
API-based setup commands like loginByApi() meaningfully speed up test suites.
Extract a command as soon as the same multi-step interaction appears in more than one or two places.
Pro Tip
Start a project's custom command library with just three commands: a selector helper, a login/setup helper, and a common assertion helper (like a toast checker), these three alone eliminate the majority of repeated boilerplate in most real-world Cypress suites.
You now have practical reusable command patterns. Next, learn how to safely modify built-in behavior with Overwrite Commands.