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
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'
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)
})
})
})
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 }
})
To create a custom command, use the
.add
function, fromCypress.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 aproject
object as an argument, and runs acy.request
command to create such resource via an API call, using theproject
'sname
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')
})
})
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()
})
Similarly to the
api_createProject
custom command, thegui_createProject
custom command is also defined by the.add
function of theCypress.Commands
module; it also receives aproject
object as argument, but its implementation uses Cypress commands that interact with the app as users would, such ascy.visit()
,cy.get(...).type(...)
,cy.contains(...).click()
, etc.Notice that it uses the
project
'sname
anddescriptions
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
andsessionLogin
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)