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!).

Loading...

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 © 2024