Transcripted Summary

In this test below, we have already intercepted our board list request.


it('Stubbing response', () => {

  cy
    .intercept({
      method: 'GET',
      url: '/api/boards'
    }).as('boardList')

  cy
    .visit('/')

});

We have done so by giving our intercept command a parameter, which happens to be an object. This object is responsible for matching our request.

But intercept can take another object, which we can use for stubbing a response from our server.

For example, we can specify a response body.

In our application, when we look into the detail of our GET /api/boards request, we see that the Response is an array of objects.



Each object represents 1 board.

When we look into the Response, you can see that our app is going to render two boards. And it is going to use the data that our server has provided.

So, if we decided that instead of the current list of our boards, we want to render an empty list, we can just put an empty array over here. That way, whatever was supposed to return from our server is going to be substituted by what we have defined here.

And we have defined that the response body should be an empty array.


  cy
    .intercept({
      method: 'GET',
      url: '/api/boards',
      body: []
    }).as('boardList')

Now, when I save my test, you can see that our board list is empty.

If I look into the detail of my request, you'll see that we have an empty array.



When I go back and remove my object (deleting the body code that we just added) and save my test again, you'll see that our boards are back.

What we have just done is that we told our app that instead of a real response from the server, a different one came in, and that was our empty array.

Not only we can specify an exact response in our test, but we can also actually use a file that will become a Response body. These files are usually stored in the fixtures folder.

So, I have a fixture that is called, “threeBoards.json”.


[
  {
    "created": "2021-03-17",
    "id": 6783578613,
    "name": "board from fixture #1",
    "starred": false,
    "user": 0
  },
  {
    "created": "2021-03-17",
    "id": 6583782612,
    "name": "board from fixture #2",
    "starred": false,
    "user": 0
  },
  {
    "created": "2021-03-17",
    "id": 456456889,
    "name": "board from fixture #3",
    "starred": false,
    "user": 0
  }
]

Inside there's an array of objects that I'm going to use as a response body.

To do that, instead of body attribute, I'm going to use fixture. And the value of that attribute is going to be the name of our JSON file.


  cy
    .intercept({
      method: 'GET',
      url: '/api/boards'
      fixture: 'threeBoards.json'
    }).as('boardList')

When I now save my test, you can see that instead of the real server response, I have a list of boards loaded from my fixture file.



Let's now try something else.

Let's say, for example, that I want to test an error message that appears when there's some network issue. I'm going to match a different request for that.

Instead of our GET, I'm going to match the POST request, which is the request that we do when we are creating boards.

Instead of fixture, I'm going to give an attribute that is called, forceNetworkError. I'll set that to “true”.


  cy
    .intercept({
      method: 'GET',
      url: '/api/boards',
      forceNetworkError: true
    }).as('createBoard')

And when I save my test now, and go ahead and create a new board, I will see an error.



Now we can create a test that will check if our application behaves correctly when there's a network error.

Let's quickly write a test.

I will select the “create-board” item, click on it. Then I'll select the input element, type in the name of the board, which will be, “new board”, and type in “enter” key.


  cy
    .get('[data-cy=create-board]')
    .click()

  cy
    .get('[data-cy=new-board-input]')
    .type('new board{enter}')

I will save my test to see if I'm doing everything correctly. It seems that I do.

Now I can hover to the moment when my error happens and use elements selector to find my error message.

It has an ID of, #errorMessage.

I can simply select it and write an assertion that it should be visible.


  cy
    .get('#errorMessage')
    .should('be.visible')

When I close this now and save my test, you can see that we have successfully made a test to make sure that the error message is visible.



Let's back up a little and intercept our get boards request once again.

As I mentioned, the second argument is an object. There are multiple options we can pass and change the response of our HTTP call.

The really powerful thing about intercept, however, is that the second parameter can be a function.

So, let's pass a function. And for now, let's just log it out to our console.

I'll save my test, open the console, and you can see that we have an object over here.



There are different functions we can use.

Let's use that reply function and see what it gives us.

I'm going to call reply, req.reply. And again, pass a function and see what's inside.

But instead of request, we are looking at a response.


it('Stubbing response', () => {

  cy
    .intercept({
      method: 'GET',
      url: '/api/boards'
    }, (req) => {

      req.reply( (res) => {
        console.log(res) 
      })
    }).as('boardList')

  cy
    .visit('/')

});

Let me save this now and look inside the console.

I can see that there's a couple of pieces of information that I can work with now. Inside this reply function, I can actually change this data and return it back as a reply.

For example, inside this body object, I have my 2 boards. Both have the “starred” attribute set to “false”.

With my function, I can change that and say that the response body item number 0 and the attributes “starred” should be set to “true”.

I will then now return the whole response and then save my test.


it('Stubbing response', () => {

  cy
    .intercept({
      method: 'GET',
      url: '/api/boards'
    }, (req) => {

      req.reply( (res) => {
        res.body[0].starred = true

        return res
      })
    }).as('boardList')

  cy
    .visit('/')

});

And you can now see that my first board appears in the Starred section.

Keep in mind that I didn't actually change the data in the database. In fact, we can look inside and see that the groceries board has still the “starred” attribute set to “false”.



What we did over here is that we not only matched our request, but we have also modified the response that it gave us. And we did that only within the context of our test.

This is especially useful if you want to test different edge cases, that would be hard to get to with test data. With the intercept command, we can change the data however we want.

Let's quickly recap what we have done here.

First, we passed a second argument to our intercept command. With that, we were able to change the response body or use a fixture from a file. This enabled us to change the response to our liking.

Second, by passing the forceNetworkError option, we were able to look into the behavior of our application under the circumstance that it gets an error from the network.

And finally, we were able to combine real data and change just a part of it, so that we were able to test any state of data that we want.



Resources



© 2024 Applitools. All rights reserved. Terms and Conditions Privacy Policy GDPR