In Cypress, cy.session is a command that caches and restores certain session data (like cookies, localStorage, and sessionStorage) between tests. This helps you maintain a consistent context between tests, ensuring that your tests are faster and more reliable by avoiding the need for redundant login steps or setup procedures.

How does it work?

When you log in during a test, Cypress caches the session data like authentication tokens and session cookies. During the next tests, Cypress can restore this session to make the tests run faster and more smoothly, without having to log in again. It just takes the cookies and applies it again to the browser.

One of the challenges when using cypress session is ensuring that your session remains valid. In our applications, the authentication token has an expiration time. Once that expires, you need to log in again.

Validation

According the Cypress documentation, there is a validate function that you can implement after a session:

The validate function is used to ensure the session has been correctly established. This is especially helpful when a cached session is being restored, because if the session is not valid, cy.session() will recreate the session by re-running setup.

In my case, I have the following validate function:

function validate() {
  cy.log("Validate the session");
  // Check if the bearer token is expired
  if (storedTokenIsExpired()) {
      throw new Error("Session has expired");
  }
}

I check if the stored bearer token, that I stored in a sessionStorage variable. If the token is expired, then an exception it thrown, so that cypress can re-authenticate.

How to check if the Bearer Token is Expired

To check if the bearer token is expired, I use the jwt-decode library to decode the JWT and extract the exp (expiration) claim. I compare the expiration time afterwards with the current time to determine if the token has expired.

The bearer token is stored in a sessionStorage Item. The code how I stored it, can be found in the previous post.

window.sessionStorage.setItem('bearer', tokenresponse.body.access_token);

Then the next of the expiration check is easy:

function storedTokenIsExpired(): boolean {
  const token = jwtDecode(window.sessionStorage.getItem('bearer'));
  const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
  cy.log(`Token expires at: ${token.exp} - current time is ${currentTime}`);
  // If the token has expired, return true
  if (token.exp < currentTime) {
    return true;
  }
  return false;
}

In this function I get the current time in seconds using Date.now(), divided by 1000 to convert to Unix time. That should be because the expiration time in a bearer token is also Unix time.

This approach simplifies session management, as you don’t need to check if the token will expire soon or handle complex timing logic. Instead, I only check if the token is already expired, and if so, force a re-login.

Resources