DEV Community

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

Posted on • Updated 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 in custom commands, where some of them can be considered App Actions. The comparison between Page Objects and App Actions will be left for another publication.

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 custom commands.)

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

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

And from the cypress/support/index.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', () => {
  after(() => cy.api_deleteProjects()) // I'll talk about the after 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

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.gui_login())

  after(() => cy.api_deleteProjects())

  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

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


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.

Discussion (0)