Mastering Advanced Cypress.io Test Automation [Part 2/4]: Network Stubbing

ahsanbilal

Ahsan Bilal

Posted on May 12, 2023

Mastering Advanced Cypress.io Test Automation [Part 2/4]: Network Stubbing

With the examples covered in this part, you’ll gain a strong grasp of network stubbing in your Cypress.io test suite and be one step closer to mastering advanced Cypress.io test automation. So, let’s get started!

Network Stubbing

Another challenge in web application testing is dealing with network requests. In some cases, you may want to simulate network responses in your tests. For example, you might want to test how your application handles errors or slow network connections.

The cy.intercept() command is used to intercept specific network requests and provide custom responses. You can pass in the HTTP method, URL, and response object as arguments to the cy.intercept() command. The response object can include a fixture, which is a static JSON file that serves as a mock response.

Let’s take a look at some code examples to see how network stubbing works in Cypress.

Example 1: Simulating a Slow Network Connection

In this example, we’re intercepting a GET request to the URL https://api.example.com/users and responding with a fixture called “users.json”. We’re also using the cy.wait() command to simulate a slow network connection.

describe('Network Stubbing', () => {
  beforeEach(() => {
    cy.intercept('GET', 'https://api.example.com/users', {
      fixture: 'users.json'
    }).as('getUsers')
  })

  it('Visits a website that uses an external API', () => {
    cy.visit('https://www.example.com')
    cy.wait('@getUsers').then(({ response }) => {
      expect(response.statusCode).to.equal(200)
      expect(response.body).to.have.length(2)
      expect(response.body[0]).to.have.property('name', 'FirstName LastName')
    })
  })
})
Enter fullscreen mode Exit fullscreen mode

Let’s break down the code step by step:

  1. The describe function is used to group related tests together. In this case, we’re grouping tests related to network stubbing.
  2. The beforeEach function is used to set up a mock server and define a route for the server to respond to using cy.intercept(). In this case, we’re intercepting a GET request to the URL https://api.example.com/users and responding with a fixture called “users.json”.
  3. The test, it('Visits a website that uses an external API', ()=>{...}), visits a website and waits for the response from the mocked API route we defined earlier using cy.intercept(). Once the response is received, we use the .then() function to perform assertions on the response. In this case, we’re asserting that the response has a status code of 200, has a length of 2, and that the first user object has a name of ‘FirstName LastName’.

Example 2: Handling Dynamic Responses

In this example, we’re intercepting a dynamic API route and responding with user data. We’re using the .its() function to drill down into the response JSON and check that the data returned for the user with ID 1 matches our expected data.

it('Handles dynamic response', () => {
  // Intercept the dynamic API route and respond with user data
  cy.intercept('GET', '/api/users/*', req => {
    req.reply({
      statusCode: 200,
      body: {
        id: req.path.split('/')[3],
        name: 'FirstName LastName',
        email: 'fullname@example.com',
        age: 30
      }
    })
  }).as('dynamicApiRoute')
  // Visit a website and wait for response from mocked API route
  cy.visit('/')
  cy.wait('@dynamicApiRoute')
  // Assert that the response contains the correct user data
  cy.get('@dynamicApiRoute')
    .its('response.body')
    .should('deep.equal', {
      id: '1',
      name: 'FirstName LastName',
      email: 'fullname@example.com',
      age: 30
    })
})
Enter fullscreen mode Exit fullscreen mode

Here is a step-by-step breakdown of the code example:

  1. We start with the test case description: “Handles dynamic response”.
  2. We then use the cy.intercept() method to intercept a dynamic API route. The route is defined with a wildcard * in the URL path, which means that any URL that matches the pattern /api/users/* will be intercepted.
  3. Inside the intercept method, we use the req.reply() method to respond with user data. The req object contains information about the intercepted request, including the URL path. We extract the user ID from the URL path using the .split() method and add it to the response body.
  4. We then visit a website using the cy.visit() method and wait for the response from the mocked API route using the cy.wait() method. Note that we haven't defined an alias for this route yet.
  5. We define an alias for the intercepted route using the .as() method. We use the name dynamicApiRoute as the alias.
  6. We then assert that the response contains the correct user data. We use the cy.get('@dynamicApiRoute') method to get the response for the intercepted route using the alias. We then use the .its() method to access the response.body property of the response. Finally, we use the .should() method with the deep.equal assertion to compare the response body with the expected user data.

Example 3: Handling Errors

In this example, we’re intercepting an API route that returns a 500 server error using cy.intercept(). Once again, we’re visiting the website and waiting for the response from the mocked API route. We’re then checking that the response contains the expected error message.

it('Handles errors', () => {
  // Intercept an API route that returns a 500 server error
  cy.intercept('GET', '/api/error', {
    statusCode: 500,
    body: 'Internal Server Error'
  }).as('errorRoute')

  // Visit the website and wait for response from mocked API route
  cy.visit('/')
  cy.wait('@errorRoute').then(({ response }) => {
    expect(response.statusCode).to.equal(500)
    expect(response.body).to.equal('Internal Server Error')
  })
})
Enter fullscreen mode Exit fullscreen mode

The test first intercepts the API route that returns a 500 server error using cy.intercept(). The method takes three arguments: the HTTP method, the URL to intercept, and an object containing the response to return. In this case, we're returning a response with a status code of 500 and a body of "Internal Server Error". We also give this intercept a unique name using .as('errorRoute') so that we can reference it later.

Next, we visit the website using cy.visit() and wait for the response from the mocked API route using cy.wait('@errorRoute'). Once the response is returned, we can access it in the callback function using destructuring to get the response object.

Finally, we use expect() to check that the response contains the expected error message. We check the statusCode property of the response to ensure that it is 500, and we check the body property of the response to ensure that it matches the expected "Internal Server Error" message.

By intercepting and mocking API routes in this way, we can simulate different responses from the server and ensure that our frontend code handles them correctly. This makes it easier to test our application and catch errors before they make it to production.

Summary: Overall, these examples demonstrates how to use network stubbing in Cypress.io to mock API responses and control the data returned by the API. By using network stubbing, we can ensure that our tests are predictable and repeatable, even when testing applications that rely on external APIs.


If you liked this, click ❤ so other people will also notice here.

💖 💪 🙅 🚩
ahsanbilal
Ahsan Bilal

Posted on May 12, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related