In this chapter, we'll take a look into network requests, especially into how we can intercept them. In my file, I have a following test. I want to make sure that my board has no lists. If I run my test again, you might see that we have the same result.
Our test is passing, but this is not a good passing. In fact, we are getting a false positive. We're trying to assert that the board has no lists, but in fact, we have a groceries list appearing in here. Our timeline is going to help us debug the problem. As I hover over different items, I can see that the assertion and my get
command were actually executed while the data was still loading. So the test is not actually testing what it is supposed to be testing.
We can change this by adding cy.wait
and wait for, for example, three seconds. And in this case, our test will fail, but this is not exactly the way we want to go about this.
Adding unnecessary waits is definitely an anti-pattern. And although sometimes it cannot be totally avoided, it's good to look at it as a last resort. If I go back to my test and take a look at what's happening, I'll see that there are three XHR requests. In other words, our application is trying to connect to our database and retrieve some data.
For example, this API cards endpoint will get all of our cards. This API lists endpoint will get all of our lists. And you can see in the request and response how the DOM has changed. During my request or at the point when the application called my database, I can see that the data is loading. As soon as my response will come back, my list will appear. So this would be a good thing to wait for. And in Cypress, we can do exactly that.
We can wait for a certain API call to be made and wait for its response. The way we do that is by using intercept command. In the intercept command, we can define which API call we want to wait for. In our case, it is an API call with a method of get and with a URL of API lists and a query parameter board id equals one.
When I save my test and make it fail, I can see a new item in our timeline. We have a routes table. In here, we get the list of all of the API calls we have defined with the intercept command. We can actually define multiple of these intercept commands to check for multiple API calls.
In this nice table overview, we see the method, we see the route, we see whether the API call was stubbed, the alias we have given to our intercept and the number of API calls that were made during our test run. We can see there's no alias both in this table and in the mapped API call. Let's add one by adding alias command. I'm going to call this get lists. What alias enables me to do is to use it in wait command.
Now, instead of adding a number, I can do at
, which stands for alias, get lists and save my test. Now, my test is still failing, but remember, this is a good thing because what we want to do in our test is to make sure that the board has no lists. The way that we have ensured this is that we waited for a get lists API endpoint to be called, return the answer and only then move on to the next command, which is our get command.
There are multiple ways of how we can match a certain API call and I'll show you this in my second test. I'll filter it out using it.only
and in this test, I'm deleting a list. As you can see, the test goes pretty fast. What I want to check in this test is that after I click on the delete list item, this delete API call is being made. Let's add a intercept, but this time I'm going to use slightly different syntax.
In my first case, I used first parameter as a method, second parameter as the URL. Instead, what I can do is to pass an object and define each parameter as a object attribute. So that will be method, in this case, delete and then URL, which will be API lists slash one.
I'm going to give this a alias and call it delete list. After I click, I'll add a wait command and wait for my alias. This way, I'm going to ensure that this API call actually happened. So let's save my test and now I can see it's nicely passing. But what if I'm in a situation where the list ID isn't so obvious and instead of number one, I'm going to get a randomized number or a UID?
Well, the good news is that we can actually use a regular expression for our URL, but there's even nicer method that I usually prefer and that's using mini match. Basically, at any point, if you have a URL that has a part that's unpredictable, you put an asterisk in there. So this is going to be API lists slash whatever comes afterwards. As I save my test now, you can see that the test is still passing and my URL is being matched. If I click on the wait command and take a look into the console, I can see that the wait command is actually yielding something.
It's an object containing all of the properties of this API call. We can take a look into the request or to the response and even check the status code. The way we can do that is by using then command and make a Chai assertion the same way as we did in the previous chapter. So the then command will accept a callback and then I'll write an expect
list response status code to equal 200. When I close the console, save my test and rerun it, I see that not only I have waited for the API call to be made, but I actually checked an attribute of this API call.
I could add multiple assertions into my then command, but if I want to keep things simple and just check for the status, I can actually write this in a much simpler way and that's using its command. This command will take whatever attribute in the given object. So since cy.wait
is going to return an object with the API calls properties, I can access these properties by typing response status code and then write a should assertion that it should equal 200.
I'll delete the rest and now I have a very simple test that will check for the proper status code. You might have noticed that I have added my intercept command before the visit command. This is because I always want to make sure that I call the intercept command before the API call actually happens. If I were to add my intercept command, for example, here after click, it might be too late because click will actually trigger this API call. So this is not a good place to have my intercept command. So it's simply important to remember that you should put your intercept before the API call actually happens or to be completely safe you can put them in a before or before each hook.