Cypress API Testing: A Comprehensive Guide

August 2024 · 8 minute read

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.

Table of Contents

What is an API? (Purpose of API testing)

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

Setting up the Environment

To get started with Cypress, follow the below steps:

  • Create a folder where you would like to store and execute the scripts.
  • Open the terminal and set up the node project with the command, npm init -y, which will create package.json file with default values.
  • Execute the command, npx cypress install from the same folder in the terminal.
  • 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

    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,

    env: { myURL: "https://reqres.in/" }
    //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}`) })
    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

    ncG1vNJzZmivp6x7o77OsKqeqqOprqS3jZympmeXqralsY6csKmqlajAbq3PomStnaOptq%2Bz