Use cy.server() and cy.route() to control API response in a cypress test

Tomasz Łakomy
InstructorTomasz Łakomy
Share this video with your friends

Social Share Links

Send Tweet

Our tests should not be brittle and break just before the data returned from the API changed slightly. As an example - imagine testing Twitter with their ever-changing feed.

When writing e2e tests it's important to have a known state of the app at the beginning of each test so that potential failures depend specifically on the thing we're trying to test.

In this lesson we're going to learn how to use cy.server() and cy.route() to control API response in a cypress test.

Tomasz Łakomy: [00:00] We would like to write a test in order to make sure that this Emoji Search app properly renders the data returned from the API.

[00:06] Right now, our test is very simple. It's just going to visit the home page. When we do visit the home page, we send a network request in order to get those emojis. For now, let us assume that if this Joy emoji over here has been rendered, then our app works as intended.

[00:19] I'm going to do cy.get(), select an element from the list using the emoji-row data-cy property, so it's one of those. I would like one of those to contain Joy. If I save that, now our test is passing, which is excellent, but there's a slight issue though.

[00:35] The issue is that, what happens if this Joy emoji is no longer present in the database? Our test is going to fail, indicating that the app is broken, which is not entirely true because we just deleted something from the database. The functionality of rendering those emojis is not affected at all.

[00:49] To illustrate what may happen, I've just removed this Joy emoji from the database. Right now, if I restart the test, it's going to fail even though, as we can see, there's plenty of emojis displayed. In order to avoid issues like this, Cypress allows us to control the API responses. In order to do that, we have to use the cy.server() command. Afterwards, we're going to use the route() command.

[01:09] Whenever there's a GET request to our ENDPOINT, which we are importing over here, we would like to render an EMOJI_RESPONSE. An EMOJI_RESPONSE is something I've prepared before. It's going to contain an array of three emojis. There's going to be this Joy emoji, as well as Smiley and Smile, which are apparently different.

[01:28] If I'm going to restart the test, it is going to pass, but also, we can see in the UI that we only have those three emojis displayed. Let me finish this test. I would like those emojis to contain Smiley and Smile as well. Just to be extra sure, I'm going to ensure that there are only three items displayed. It should have length of three.

[01:51] Now, if I save that, we have a passing test, which is great because, one, we do have a passing test and, two, this test is less brittle because we are not depending on random changes in the back-end API. Nevertheless, you should always strive for a combination between tests that are hitting your actual back end and also tests where you get to control the back-end response.