DEV Community

Cover image for How to create custom commands with Cypress
Walmyr
Walmyr

Posted on • Edited on

How to create custom commands with Cypress

Today in “Pinches of Cypress”, learn how to create reusable code

A lot of people have been asking me to talk about "Page Objects or App Actions?"

To those who want to understand better about the subject, I recommend the official source (Cypress.io's blog), to not mention more of the same.

In this post, I won't talk about Page Objects versus App Actions. The focus here will be CUSTOM COMMANDS, where some of them can be considered App Actions.

To make things clear, I'll use the wlsf82/gitlab-cypress project as an example.

In this project, I decided to separate the custom commands between commands that occur at the API level (which can be considered App Actions) and those that occur via GUI (which are just GUI custom commands.)

Inside the cypress/support/ directory, I have the following files' structure.

cypress/support/
  api_commands.js
  gui_commands.js
  e2e.js
Enter fullscreen mode Exit fullscreen mode

YES, YOU CAN HAVE AS MANY CUSTOM COMMAND FILES AS YOU WANT!

And from the cypress/support/e2e.js file, I import both api_commands.js and gui_commands.js files.

import './api_commands'
import './gui_commands'
Enter fullscreen mode Exit fullscreen mode

Everything okay so far?

Now I want to add a test that validates a project's creation (via API).

Let's look at the test implementation.

const faker = require('faker')

describe('Create project', () => {
  before(() => cy.api_deleteProjects()) // I'll talk about the before function in another post

  it('successfully', () => {
    const project = {
      name: faker.random.word() // I will talk about the use of faker in another post as well, explaining its use.
    }

    cy.api_createProject(project).then(response => {
      expect(response.status).to.equal(201)
      expect(response.body.name).to.equal(project.name)
    })
  })
})
Enter fullscreen mode Exit fullscreen mode

And the app action's implementation (or the custom command that creates such a resource via an API call.)

const accessToken = Cypress.env('gitlab_access_token')

Cypress.Commands.add('api_createProject', project => cy.request({
  method: 'POST',
  url: `/api/v4/projects/?private_token=${accessToken}`,
  body: { name: project.name }
})
Enter fullscreen mode Exit fullscreen mode

To create a custom command, use the .add function, from Cypress.Commands module, where the first argument is the custom command name, e.g., api_createProject; and the second argument is the callback function that implements the logic for doing what the custom command is supposed to do.

In the case of the api_createProject custom command, it receives a project object as an argument, and runs a cy.request command to create such resource via an API call, using the project's name attribute.

Also, it uses the accessToken variable defined outside of the custom command, so it has the right to make the API call.

Okay, the API testing part is covered.

Now, let's look at an example of a GUI test, also for project creation.

const faker = require('faker')

describe('Create project', () => {
  beforeEach(() => {
    cy.api_deleteProjects()
    cy.sessionLogin()
  })

  it('successfull', () => {
    const project = {
      name: faker.random.uuid(),
      description: faker.random.words(5)
    }

    cy.gui_createProject(project)

    cy.url().should(
      'be.equal',
      `Cypress.config('baseUrl')${Cypress.env('user_name')}/${project.name}`
    )
    cy.contains(project.name).should('be.visible')
    cy.contains(project.description).should('be.visible')
  })
})
Enter fullscreen mode Exit fullscreen mode

And the implementation of the gui_createProject custom command.

Cypress.Commands.add('gui_createProject', project => {
  cy.visit('projects/new')

  cy.get('#project_name').type(project.name)
  cy.get('#project_description').type(project.description)
  cy.get('.qa-initialize-with-readme-checkbox').check()
  cy.contains('Create project').click()
})
Enter fullscreen mode Exit fullscreen mode

Similarly to the api_createProject custom command, the gui_createProject custom command is also defined by the .add function of the Cypress.Commands module; it also receives a project object as argument, but its implementation uses Cypress commands that interact with the app as users would, such as cy.visit(), cy.get(...).type(...), cy.contains(...).click(), etc.

Notice that it uses the project's name and descriptions attributes for typing into text input fields.

Done! We now have the project creation functionality covered at both the API and GUI levels!

For details about the api_deleteProjects and sessionLogin custom commands, read the official project's code.


Any thoughts about the series?

I'm looking forward to hearing your feedback!


This post was originally published in Portuguese on the Talking About Testing blog.


Would you like to learn about test automation with Cypress? Get to know my online courses on Udemy.

Top comments (0)