Creating Custom Cypress Commands: Boost Efficiency and Maintainability in Your Test Suites

Written on 2023-06-12 by Adam Drake - 4 min read

Image of Creating Custom Cypress Commands: Boost Efficiency and Maintainability in Your Test Suites

While developing Cypress tests, you'll quickly realize that some actions tend to recur frequently across various test scenarios. This is where Cypress Commands can be a game-changer for you. These powerful, customizable APIs enable developers to create bespoke commands that can be seamlessly integrated into your test cases, significantly streamlining the entire testing process and enhancing productivity.

Cypress Custom Commands

As an example I will show you how to create a Cypress custom command and how to use it. In this example we have an app with an email and password login. Very secure I know! Many of the tests require access to protected routes so the test will need to login first to the application and then navigate to which ever route needs to be tested and then that part of the application tested. So the login functionality is continually needed for all tests on protected routes.

Below is the lines needed in Cypress to login to this example application:

cy.visit('/login');
cy.get('input[name="username"]')
  .type(adminUser.username)
  .should('have.value', user.username);
cy.get('input[name="password"]')
  .type(adminUser.password)
  .should('have.value', user.password);
cy.getBySel('login-button').click();

Pretty simple stuff. Cypress navigates to the `login` route. There is an `user` object with a `username` and `password` which is used for the login. Then the `Login` button is pressed and the user is logged in.

This is where Cypress Commands can come in handy. Cypress commands allow us to take the above code and put it in a custom, reusable command.

We could use this code snippet in all our tests where we need to login first. However, what if our login functionality changes somehow? It's no longer `username` but `email` or its no longer username and password but some SSO? If we have many tests (which we likely will over time) then we would have to change this snippet in many places. Not good!

This is where Cypress Commands can come in handy. Cypress commands allow us to take the above code and put it in a custom, reusable command.

There are two API available for adding custom commands:

Cypress also recommends that you put your custom commands in the cypress/support/commands.js file, since it is loaded before any test files are evaluated via an import statement in the supportFile.

Creating a Custom Command

If we take our login snippet we can create a Cypress command from that:

Cypress.Commands.add('login', () => {
  cy.visit('/login');
  cy.get('input[name="username"]')
    .type(adminUser.username)
    .should('have.value', user.username);
  cy.get('input[name="password"]')
    .type(adminUser.password)
    .should('have.value', user.password);
  cy.getBySel('login-button').click();
});

I have used the `Cypress.Commands.add()` api to create a custom command called `login`. I also use typescript in my projects so I have to declare type in the `global.d.ts` file I have in the `cypress` folder:

declare namespace Cypress {
  interface Chainable {
    login(): Chainable<JQuery<HTMLElement>>;
  }
}
By investing time into building reusable commands, you can streamline your code, increase readability, and reduce maintenance efforts, improving the overall efficiency of your testing framework.

Now the command is set up and ready to use! To use it in your tests it's actually very simple. Let's take an example where we want to test the dashboard page is rendering the right information. We can now use this command at the beginning of our test:

it('should allow a logged in user to access the dashboard page', () => {
  cy.login();
  cy.url().should('include', '/dashboard');
});

As you can see as we have declared this `login` command in the `Chainable` interface if is now available on the `cy` object. When this test runs and Cypress reaches this line it will know that it needs to run the code in the `login` command. Great!

Conclusion

Creating custom Cypress commands is a powerful way to optimise and enhance your end-to-end testing process. By investing time into building reusable commands, you can streamline your code, increase readability, and reduce maintenance efforts, improving the overall efficiency of your testing framework. Furthermore, the flexibility afforded by Cypress in crafting these commands ensures that you can easily tailor them to your application's specific requirements. By embracing this powerful feature, you can unlock the full potential of end-to-end testing, making your application more reliable, high-performing and, ultimately, more successful (assuming it's a good app in the first place!).

Subscribe to My Weekly Updates on Medium!

Enjoyed This Post?

If you found this blog post helpful, why not stay updated with my latest content? Subscribe to receive email notifications every time I publish.

If you're feeling really generous you can buy me a coffee. (Btw, I really like coffee…)

What You'll Get

  • Exciting Discoveries: Be the first to know about the latest tools and libraries.
  • How-To Guides: Step-by-step articles to enhance your development skills.
  • Opinion Pieces: Thought-provoking insights into the world of frontend development.

Join Our Community

I live in the vibrant city of Prague, Czech Republic, with my family. My blog is more than just articles; it's a community of like-minded developers who share a love for innovation and learning.

About me

I'm a passionate Frontend Developer specialising in React and TypeScript. My professional journey revolves around exploring and mastering new tools and libraries within the JavaScript ecosystem.

Check out my LinkedIn and Github if you are interested.

Adam Drake AI Selfie

Written by Adam Drake

Adam Drake is a Frontend React Developer who is very passionate about the quality of the web. He lives with his wife and three children in Prague in the Czech Republic.

Adam Drakes Site © 2025