Test elegantly against different API responses in React using Cypress.io
Create dynamic fixtures to mock API responses using JavaScript Objects or Functions
1. Introduction
As an application grows even small changes can cause unforeseeable consequences. As a developer it is hard to remember every conditional and every effect that a change can have. That is why automated testing is a great way to ensure that your application is working properly.
Cypress is a fantastic testing tool for javascript based web applications, and in this article I am going to share a learning, that might help you increase your efficiency.
If you are working against an API you could not make every call when you are testing. Sometimes you have to use mocks, which allows you to mimic responses coming from an API and test certain scenarios without actually making a call. Cypress has built in solution to do that: you can store these fixtures in the fixtures folder, or add responses directly to cy.route() function, usually as JSON.
Keeping your fixtures updated can be painful at times, and sometimes you have to check something dynamically.
2. Using JavaScript objects as dynamic mocks
An example could be that you are restricting something based on date. In that case you cannot use a static mock, you have to create something dynamically. Luckily cypress lets you do that, using javascript objects as responses. An example could look like that:
The sessionpage variable we declare at line 5 ending it at line 85 is a javascript object which we will add to the cy.route() function at line 90 as a response. In there we are creating 2 sessions, the first with a dynamic start/end (line 12 - line 13) date using today (line 4) as a reference to test against some conditionals in our codebase, and the second with a fixed date where it does not matter. This works but clutters our test greatly.
Since we are in JavaScript we could easily extract this object and import it in our test, as we would do it with a helper method in our React components:
Instead of using the local variable sessionpage we import it from the new file we created (at line 3) where export the same object as default, and use it in our cy.route() function (at line 10).
This clears up our tests (37 lines instead of 117), makes it easily readable, and opens up even more possibilities in our mock object.
3. Using JavaScript functions as dynamic mocks
I had cases when I had to create 2 different mock files just because 1 or 2 attributes were different. To avoid this you can create javascript functions as a dynamic mock. You can replace static attributes with dynamic references, add default state, and pass down values you want to change. The structure I choose is similar to redux reducers/actions.
In this last example I made the mock even more responsive, so if you need different statuses in different it blocks you can pass down different payloads in the response if you convert your dynamic mock into a function.
In the sessionpage.js file I add defaults object as default and use it as a reference in the the sessionpage() function on line 22 and line 61. If I do not pass down anything the default object will be used. However if I pass down an argument in the function that will replace the defaults I added. That is what I do in line 10 in users_can_access_videocall_spec.js.
Since you have a function now as a mock you can do so much more. You can add the number of objects you want to return in the payload, you perform calculations, and add random effects. The possibilities are endless!