Cypress · Browser testing end to end

How do you write custom Cypress commands?

Mediumcustom commandscommandstypescriptUpdated Oct 2026
Quiz this track

Short answer

Use Cypress.Commands.add in the support file to define a reusable command, and augment the Cypress Chainable interface in TypeScript so the command is typed everywhere.

Custom commands remove repeated setup from specs. A login flow, a data seeding step or a repeated assertion belongs in a command when several tests need it. The command lives in cypress/support and is loaded through the support file.

ts
Cypress.Commands.add("login", (email: string, password: string) => {
  cy.session([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.location("pathname").should("eq", "/dashboard");
  });
});
The command wraps a session, so repeated logins in a spec reuse the cached session.

Typing the command

ts
declare global {
  namespace Cypress {
    interface Chainable {
      login(email: string, password: string): Chainable<void>;
    }
  }
}

export {};
Declaration merging gives editors and tests the command signature.
  • Add the command in cypress/support/commands.ts and import it from the support file
  • Return a chain when callers need to continue chaining
  • Use cy.session inside a login command to avoid repeated UI setup
  • Prefer a command for repeated user intent, not for every small click
  • Keep commands deterministic; a command that hides a sleep will spread flakiness
Custom commands do not replace page objects or app actions automatically. Choose one pattern for the team and stay consistent, because mixing three abstractions makes tests harder to read.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Where should a custom command be defined?
  2. 2How do you make a custom command typed in TypeScript?
  3. 3When should a helper be a function instead of a command?
  4. 4How does cy.session change a login command?

Say it in the interview

I define reusable commands with Cypress.Commands.add in the support file. For each command I add a TypeScript declaration so it is typed in specs. I use commands for repeated user intent like login, and I keep them deterministic. If a helper does not need the Cypress chain, I prefer a plain function, and I stay consistent rather than mixing commands, page objects and app actions arbitrarily.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Cypress mock interview and get scored feedback on depth, clarity and confidence.