Cypress Part IV: Custom Commands

Custom commands allow us to reuse common code we use for tests. Let's look at how we can make one and add its type definition for TypeScript.

20th Jan. 2020

As you write more tests, you will soon find that you are repeating yourself. Custom Commands are a good way of encapsulating repeated test code in one place.

Show me the code!

Cypress will load commands added in support/commands.js or support/commands.ts file. It could be as simple as calling an endpoint to setup state or a complex collection of steps that you keep writing.

The example below shows how we could check if the user’s logged in and if not, log them in. The snippet uses Cypress’s built-in request helper.

Cypress.Commands.add(‘login’, (username: string, password: string) => {
  return cy
    .request(‘/api/authentication/refresh’)
    .its(‘body’)
    .then((response) => {
      // let’s inspect the body and see if the are authenticated
      if (response.authenticated) {
        return
      }

      // if not, we should log in via the endpoint
      cy.request({
        method: ‘POST’,
        url: ‘/api/authentication/login’,
        body: {
          username,
          password,
        },
      })
    })
})

For those using JavaScript, removing the types for username and password will be the only modification you will need to do.

So, how do we add type definitions to this so it will be available in the IntelliSense?

declare namespace Cypress {
  interface Chainable {
    login: (username: string, password: string) => Chainable
  }
}

// rest of your Cypress.Commands code

That’s it, the next time you need to login, you can just invoke something like cy.login('tony.stark', 'pa$$w0rd') in your tests.

In Closing

Hopefully this short post will help you write your own custom commands. As always, if you have any questions, just leave a comment below and I’ll get back to you.