App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Home Guide Cypress API Testing: A Comprehensive Guide

Cypress API Testing: A Comprehensive Guide

By Siddharth Murugan, Community Contributor -

Cypress is a highly preferred E2E testing framework and it provides us with a way to do API testing. For performing API testing, we don’t need any third-party dependency to perform this testing. We can just set up Cypress and perform API testing with it.

What is an API? (Purpose of API testing)

API – Application Program Interface is a way in which two different software components communicate. 

  • For example, we interact with remote devices in BrowserStack from the BrowserStack website with the help of API. It acts as a medium for communication between two different software components. 
  • When a product is being developed, we won’t have a UI to validate the front-end part. 
  • But with API testing, we can validate the response we will get in the front end when the product is being developed.

Setting up the Environment

To get started with Cypress, follow the below steps:

  1. Create a folder where you would like to store and execute the scripts.
  2. Open the terminal and set up the node project with the command, npm init -y, which will create package.json file with default values.
  3. Execute the command, npx cypress install from the same folder in the terminal.
  4. Now the installation will be complete, and then the Cypress application will appear on the screen.

For executing Cypress API testing, we don’t need to install any additional packages as Cypress itself has the capacity of handling API requests and responses.

Writing your first Cypress API test

  • To make an API request, Cypress automation provides an inbuilt command called cy.request(). 
  • With this command, Cypress will make an HTTP request on behalf of the web application and get the response from the API server. 
  • When the API request is successful, we will get the response status as 2xx.

Syntax

cy.request(method,URL,body)

In the above command, method, and body are optional but the URL is mandatory.

ArgumentDefinition
methodThis is the type of HTTP method we would like to implement. By default, Cypress makes this request as GET.
URLURL to which we need to send the request
bodyBody to send along with the request

cy.request(options)

In the above command, the argument options should be in the form of object

OptionDefault valueDescription
logtrueWhether it should display the command in command log
urlnullThis is the URL to which we need to make request
methodGETType of HTTP request which we need to request
authnullAuthorization header which needs to send along with the request
bodynullBody of the request
failOnStatusCodetrueWhether to make the script fail for response code other than 2xx and 3xx
followRedirecttrueWhether to follow redirects automatically
formfalseWhether to convert the body values to URL encoded content and set the URL encoded header
encodingutf8This is the type of encoding to be used when serializing the response body. Below are the supported encodings:

ascii, base64, binary, hex, latin1, utf8, utf-8, ucs2, ucs-2, utf16le, utf-16le.

gziptrueWhether to accept the gzip encoding
headersnullAdditional header which needs to be sent.
qsnullQuery paraments to append to the URL of the request.
retryOnStatusCodeFailurefalseThis set the retry ability to Cypress request command. If it is set to true, Cypress will give a retry up to 4 times.
retryOnNetworkFailuretrueRetry ability on network error. This will give a retry up to 4 times.
timeoutresponseTimeoutTime up to which it has to wait for the completion of the command. By default, it will wait up to the time which is mentioned in the config file responseTimeout

Making HTTP Request with Cypress

Let’s make a simple GET request with cy.request() command. We will make a GET request to the following URL – https://www.bstackdemo.com/ with the below piece of code,

describe('template spec', () => {
it('passes', () => {
//Getting response from BrowserStack demo website
cy.request('GET','https://www.bstackdemo.com/')
})
})

You can view the request’s response from the console log of the Cypress runner by inspecting it.

console log of the Cypress runner

Assertions in Cypress API testing

Now, let’s go ahead and try to assert the API response. When we hit the API server with the URL, if we get a response status of 200, we can say that the request we passed succeeded. 

Let’s try to assert the response status code with the below piece of code:

 describe('template spec', () => {
it('passes', () => {
//Getting response from browserstack demo website 
cy.request('GET','https://www.bstackdemo.com/').then((response) =>{
//Expecting the response status code to be 200
expect(response.status).to.eq(200)
})
})
})

With this, we will be able to assert whether the response code which we got back is 200 or not.

response code in console log of the Cypress runner

Advanced Cypress API testing

Here is the list of various methods supported by Cypress

GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE, COPY, LOCK, MKCOL, MOVE, PURGE, PROPFIND, PROPPATCH, UNLOCK, REPORT, MKACTIVITY, CHECKOUT, MERGE, M-SEARCH, NOTIFY, SUBSCRIBE, UNSUBSCRIBE, SEARCH, CONNECT.

But mostly, GET, POST, PUT, DELETE, and PATCH methods will be used. Let’s look at their purpose. 

MethodPurpose
GETThis method is for getting the list of data / specific data, available from the API server
POSTPOST request is used to create data in the server
PUTPUT is for updating the existing data
PATCHThis method is for updating the data partially
DELETEAs the name implies, it is for deleting the data in target server

Let’s try to execute them one by one, with a help of an external dummy API website – https://dummy.restapiexample.com/

With the below piece of code, you can execute POST, PUT, PATCH and DELETE request and understand it more clearly

describe('template spec', () => {
//This block inserts the data which is mentioned in the body of the request
it('POST request', () => {

cy.request({method: 'POST', url: 'https://reqres.in/api/users', body: {
"name": "Bingo",
"job": "Team lead"
}}).then((response) =>{
//Asserting the status code to be 201 for successful execution
expect(response.status).to.eq(201)
//Asserting the name which we have inserted into
expect(response.body.name).to.eq("Bingo")
//Asserting the status text to confirm whether it is created
expect(response.statusText).to.eq("Created")
})
})

//This block will execute PUT request
it('PUT request', () => {

cy.request({method: 'PUT', url: 'https://reqres.in/api/users/2', body: {
"name": "Angel",
"job": "zion resident"
}}).then((response) =>{
//Asserting the status code to be 200 for successful execution
expect(response.status).to.eq(200)
//Asserting the name which we have inserted into
expect(response.body.name).to.eq("Angel")
})
})

//This block will execute the PATCH request and update the record
it('PATCH request', () => {

cy.request({method: 'PATCH', url: 'https://reqres.in/api/users/2', body: {
"name": "Angel",
"job": "zion resident"
}}).then((response) =>{
//Asserting the status code to be 200 for successful execution
expect(response.status).to.eq(200)
//Asserting the name which we have inserted into
expect(response.body.name).to.eq("Angel")
})
})

//This block will delete the user which exist
it('DELETE request', () => {

cy.request({method: 'DELETE', url: 'https://reqres.in/api/users/2'}).then((response) =>{
//Asserting the status code to be 204 for successful execution
expect(response.status).to.eq(204)
})
})
})

Advanced Cypress API testing

Best Practices for Cypress API testing

When you have an API call which needs to be called across many test cases, then you can create your own custom command with Cypress and use it across many spec files. For example,

  • First store the API URL as an environment variable to access it across files with Cypress.env() command.
  • To store this URL as a variable, add the below object inside cypress.config.js file,
env: {
myURL: "https://reqres.in/"
}
  • Create a custom command inside /support/commands.js file like below,
//We are creating a custom command named GETrequest which has URL and userDataLink as argument 
Cypress.Commands.add('GETrequest', (url,userDataLink) =>{
//Usual GET request command
cy.request('GET',`${Cypress.env(url)+userDataLink}`)
})
  • You can use this custom command inside you spec file and get the API response stored in a variable. 
  • The complete working spec file, will look like below,
describe('template spec', () => {
it('passes', () => {
//Get the API request with URL and user details arguments and store response in a variable named details
cy.GETrequest('myURL',"api/users/2").as('details')
//With cy.get() validating the status code of response
cy.get('@details').its('status').should('eq',200)

})
})

Real-World examples of Cypress API testing

Let’s go further on testing API, by making an API GET request call to weather API, get their response, and do assertion with it.

For this step, you may need to sign-up for the weather API website, create your own account and get the API access key.weather API websiteInside cypress.config.js file, paste your access key under an object named env as below,

const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
env: {
access_key: "<your_access_key>"
}
},
});

Then, we can import this access key inside our test script and make an API call with the help of below script,

describe('template spec', () => {
it('passes', () => {
cy.request({method: 'GET', url: 'http://api.weatherstack.com/current', qs: {
//Access key given by the website
access_key: Cypress.env('access_key'),
//Name of the city for which you are viewing temperature
query: "Chennai"
}}).then((response) =>{
//Asserting the status code to be 200 for successful response
expect(response.status).to.eq(200)
//Asserting the location name
expect(response.body.location.name).to.eq('Chennai')
})
})
})

With this above piece of code, you will be able to get the API response, assert the response status code and also assert its location name in the response.

Testing a GraphQL API with Cypress

GraphQL is a query language for API. To test GraphQL API, we will use another external website – star-wars-swapi. By hitting the GraphQL API they provided, we will get the list of Star Wars movies. 

Here is the working code:

describe('template spec', () => {
it(GraphQL request, () => {
//Making a POST request to the given URL
cy.request({method: 'POST', url: 'https://swapi-graphql.netlify.app/.netlify/functions/index',
body: {
//Query parameter which needs to be passed for GraphQL
query: `query Query {
allFilms {
films {
title
director
releaseDate
speciesConnection {
species {
name
classification
homeworld {
name
}
}
}
}
}
}`
}
}).then((response) =>{
//Asserting the status code to be 200 for successful response
expect(response.status).to.eq(200)
cy.log(response)
})
})

You will notice that, the only difference which we have between the usual REST API and GraphQL API is the query part. We need to pass the body request as a query.

Conclusion

With this, we are now at the end of Cypress API testing. With the above explanations, you will be able to understand the different methods of API testing, performing assertions for API testing with Cypress, best practices for Cypress API testing, real-world examples of API testing, and performing API testing for GraphQL API. 

Browserstack provides you with a robust infrastructure to test on multiple devices with Cypress for: 

Start Cypress Testing

Tags
Automation Testing Cypress

Featured Articles

What is API Testing? (with Examples)

Top 10 API Testing Tools in 2023

Curated for all your Testing Needs

Actionable Insights, Tips, & Tutorials delivered in your Inbox
By subscribing , you agree to our Privacy Policy.
thank you illustration

Thank you for Subscribing!

Expect a curated list of guides shortly.