When I first started building this Cypress framework, I was barely exploring what things cypress has to offer out of the box and few missing things which can be obtained with the help of external NPM packages. Once I was confident enough with the framework I started experiencing other challenges while trying to reuse my generated data; so the need for State Management arose.
Test State Management is essentially how to manage the data which is generated by the the framework which is to be used in subsequent test steps
The Challenge
So I had a framework which was running and consuming and generating test data. In order to consume data which was generated from a step in subsequent step, I was lost for how to do so with Cypress. Cypress does provide something called Variables & Aliases or Environment Variables out of the box, but using which to derive the expected state/resource could be a cumbersome process.
For instance, you created a user and wanted to use its generated user_id in subsequent API test step:
This may seem simpler from the example, but as the steps increase and you need to keep track of all the aliases which were created to get data and reference them each and every time. We will look how this can be tackled by creating a simple JSON store.
The Solution:
In order to start you can clone the repo here, as I will be using this as a base for building our Test State Management. We'll start by adding an empty store.json file under cypress/fixtures/state folder.
Now in order to get and store values inside this json file we will add 2 custom commands inside support/command.js file
The saveState() requires a key-value pair tosave inside the store.json
Usage:
cy.saveState("page_id", response.body.page.id); //stores as JSON page_id key value
cy.saveState("user>user_id", response.body.payload.id); //stores user_id inside user JSON object
Result:
Here ">" is the special character which is used for signifying the hierarchy
Now similarly we'll add another command getState() to retrieve a stored value by using a stored key
Usage:
//retrieve page_id from the store
cy.getState("page_id").then(value => {
let pageId = value;
console.log(pageID); // it will print asd67asdfsa
// now we can use pageId where ever its needed
});
//retrieve user_id from user json object
cy.saveState("user>user_id").then(value => {
let userId = value;
console.log(userID); // it will print Ka6ds
});
Once above changes are made into the framework we will start by adding a new feature file.
in apiSteps.js add following code for stepDefinition for 2 new steps
That's it. When you run this feature file from the cypress runner that it first fetches the data from GET /pikachu/{name} endpoint and stores the pokemon_id from the response into our store.json and then in subsequent step uses this stored value to fetch data from GET /pikachu/{id} endpoint
Final Notes:
We could additionally add a clearState() command which could be run at the beginning or end of a test run.
Caution: using cy.clearState() will remove everything from store.json