Cypress Commands Cypress JavaScript

Feb 21st, 2020 - written by Kimserey with .

Few weeks ago we looked at Cypress, we looked into how we could install it, the different assertion we could use and how we could debug the tests. In today’s post, we will look at how we can create reusable commands to be used across all integration tests.

Custom Commands

A custom command can be added by using the Cypress.Commands.add() function and registering it in the /support/command.js file. For example here we register a login:

1
2
3
4
5
6
Cypress.Commands.add("login", (username) => {
  cy.fixture('logins.json')
    .then(users => {
      window.localStorage.setItem('access_token', users[username]);
    });
});

Our login function loads a fixture logins.json which contains the following:

1
2
3
4
{
    "user_1": "access_token_1",
    "user_2": "access_token_2"
}

and takes the access token from the fixture for the specific user. We can then use the login command from our integration tests as such:

1
2
3
4
5
6
7
context("When visiting the dashboard", () => {
  it("display the graphs", () => {
    cy.login()
      .get('[data-cy=graphs]')
      .should('be.visible')
  });
});

Due to the nature of Cypress commands being asynchronous, it isn’t allowed to mix async and sync for return value. If we were to return a value from the commad to allow it to be chained outside the usage of our command, we can do so in .then() command and return the whole chain of command leading to the .then(). For example, if we wanted to return the access token from the login, we would do as followed:

1
2
3
4
5
6
7
Cypress.Commands.add("login", (username) => {
  return cy.fixture('logins.json')
    .then(users => {
        window.localStorage.setItem('access_token', users[username]);
        return users[username];
    });
});

Type Declaration

The type reference /// <reference types="cypress" /> won’t help in the case of custom commands as they aren’t known by Cypress. In order to add type help, we can create a Typescript definition file index.d.ts in the /support folder.

This file will extend the declaration of Cypress namespace by adding the new commands:

1
2
3
4
5
6
7
8
9
10
11
/// <reference types="cypress" />

declare namespace Cypress {
    interface Chainable<Subject> {
        /**
         * Login with the username provided.
         * @param username The username to login as.
         */
        login(username: string): Chainable<any>;
    }
}

Then from the spec file, we can reference the support folder:

1
2
/// <reference types="Cypress" />
/// <reference types="../support" />

This will now provide us tooltips with help on our custom commands. And that concludes today’s post!

Conclusion

Today we looked into Cypress custom commands, we started by looking at how we could create commands and then looked at how to provide type help witht signature. Hope you liked this post and I see you on the next one!

External Sources

Designed, built and maintained by Kimserey Lam.