DEV Community

Cover image for Once upon a time a cy.session()…
Sebastian Clavijo Suero
Sebastian Clavijo Suero

Posted on • Updated on • Originally published at Medium

Once upon a time a cy.session()…

Cypress.io sessions made easy, and no more tales!


ACT 1: EXPOSITION

There are many comprehensive blogs about how to create and manage sessions in Cypress.io. But I must confess… this is NOT one of them, and it was NEVER intended to be! Despite what the blog’s title might suggest, I’m not here to spin you a child’s tale.

So, if you’re still reading and I haven’t lost you after that first paragraph, let me tell you what this blog is actually about:

A straightforward recipe to get sessions working in your Cypress tests right away. That’s it!

Nothing more, nothing less. And no tales!
 

I won’t bore you with explanations of what a Cypress session is or why you should use sessions in your tests (because you really should). If you’ve found your way to this blog post, you likely already know what a user session is and how it can benefit your tests.

What you might not yet know is how to implement them effectively, without unnecessary embellishments, and in a way that works. I’ve noticed that many QA engineers, particularly those who are new to Cypress, find it challenging to add user sessions to their tests. And I assure you, this is no fairy tale.


ACT 2: CONFRONTATION

There are essentially two things you need to know about cy.session():

  1. If you want to share the session across all your tests in the spec file, you should run it in the beforeEach() hook, and NEVER in the before() hook. If you use it in the before() hook, only the first test in the spec file will be able to utilize that session.
  2. After a session is created (or restored) by a test, you will need to perform an implicit cy.visit() to the page you want to test (even if the page to test is exactly the same as your website's landing page after login).   In my experience working with many QA engineers and testers, these two simple points are often overlooked and can be the cause of struggles when using cy.session() effectively.

So you might now ask: “How can I do it? But tell me no tales!”

 

FIRST

You might want to consider creating a custom command that encapsulates the creation of sessions for your tests. This allows you to reuse that command across all your test specs.

Hey… to be clear: We are talking about calling the custom command from different specs (adhering to the DRY principle), but you should not reuse the same user session between different specs. That’s a big NO-NO (you should also maintain the principle of test isolation as a good practice)!

In your cypress/support/commands.js file, create a custom command for logging into your app and creating a session. After the login, within the cy.session() block, I also recommend including a call to cy.url() to verify that your system navigates to the correct page.
 

Something like this:

// File cypress/support/commands.js

Cypress.Commands.add("createSession", (username, password) => {
    cy.session(
        // Session ID is going to be an array [user, password]
        [user, password], () => {
            cy.visit("/");
            cy.get('input[type="text"]').clear().type(username);
            cy.get('input[type="password"]').clear().type(password);
            cy.get('button[type="submit"]').click();

            // After login successfully it is supposed to goto the page '/shop'
            cy.url().should('contain', '/shop')
        }
    );
});
Enter fullscreen mode Exit fullscreen mode

 

This approach has two significant advantages:

  1. You can be certain that after a successful login, your app under test navigates to the intended page.
  2. Since cy.url() is a query command, it will continuously retry checking the target URL until the navigation to that page occurs or a timeout is reached. While some people use the validate option available in cy.session(), in my opinion, it's not necessary in most cases.

 

SECOND

In your test spec file, invoke the custom command to create the session within a beforeEach() hook (remember… not in the before() hook).

This will create a new session before the first test in your spec runs (with session ID [user, password]), and will automatically restore that same session before running each subsequent test in the spec.

// File tests-spec.js 

beforeEach(() => {
    cy.createSession(user, password)
});
Enter fullscreen mode Exit fullscreen mode

 

THIRD (and final)

You need to perform an explicit visit to the page you want to test (again remember… even if it’s the same as the landing page after login).

If all your tests in the spec file target the same page, then simply place the cy.visit() call in the beforeEach() hook, following the session creation.

// File tests-spec.js with visit in beforeEach() hook (same page under test in all tests)

beforeEach(() => {
    cy.createSession(user, password)

    // Explicitelly visit the page target of the tests
    cy.visit('/shop')
});

it('Test Shop Page Items', () => {
    // Your test logic for Shop items here
    // ...
});

it('Test Shop Page Totals', () => {
    // Your test logic for Shop totals here
    // ...
});
Enter fullscreen mode Exit fullscreen mode

 

However, if each of your tests in the spec file is checking a different page of your app, then it’s better to place the cy.visit() within each individual test.

// File tests-spec.js with visit within each individual test (different pages under test)

beforeEach(() => {
    cy.createSession(user, password)
});

it('Test Shop Page', () => {
    cy.visit('/shop')

    // Your test logic for Shop page test here
    // ...
});

it('Test Account Page', () => {
    cy.visit('/account')

    // Your test logic for Account page test here
    // ...
});
Enter fullscreen mode Exit fullscreen mode

ACT3: RESOLUTION

I would like to mention one last thing. I have noticed that when using sessions in Cypress, if you rerun the spec file again using the top-right ‘refresh’ button, the new execution of the spec will still use your previous session and restore it instead of creating a new one. This breaks the premise of test isolation!

If you go back to the Spec list and then select your spec again, the sessions are automatically cleared by Cypress.
 

So, if you want to ensure that two or more consecutive executions of the same spec using the ‘refresh’ button are session-independent, I have found it very useful to include a before() hook in the cypress/support/e2e.js file that clears all saved sessions.

// File cypress/support/e2e.js

before(() => {
    // Ensure that all sessions are cleared up even if you re-run the spec in the Cypress App UI (Test Runner)
    cy.log('close all sessions')
    Cypress.session.clearAllSavedSessions()
});
Enter fullscreen mode Exit fullscreen mode

That’s it! It’s that simple. And as promised… no tales! 🙂

Top comments (0)