Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set local storage in Cypress

For one of our applications, I need to set local storage in order to bypass the login page process.

I have the following function that will return the accessToken that I need to set. This function works when running in node.

async function getAccessToken(email, pwd) {
    const form = {email: email, password: pwd};
    let config = {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        }
    };
    const accessToken = await axios.post(`${process.env.API_URL}/loginWithToken`, qs.stringify(form), config);
    console.log(accessToken.data.accessToken);
    return accessToken.data.accessToken
}

I'm trying to create a cypress command that will set local storage, then visit the application. When running, I get an error that I returned a promise from a command while also invoking one or more cy commands in that promise.

Cypress.Commands.add("logInAs", async(Useremail, Userpwd, TMURL) => {
    var accessToken = cy.task('getAccessToken', {email: Useremail, pwd: Userpwd
    }).then(Visit =>{
        window.localStorage.setItem("accessToken", accessToken);
        window.localStorage.setItem("refreshToken", accessToken);
        cy.visit(`${process.env.TM_API_URL}/`+TMURL+``);
    });
});

I've also tried the following cypress command

require('dotenv').config();

Cypress.Commands.add('logInAs3', (Useremail, Userpwd, TMURL) => {
        cy.request({
            method: 'POST',
            url: `${process.env.API_URL}/loginWithToken`,
            body: {
                user: {
                    email: Useremail,
                    password: Userpwd,
                }
            }
        })
            .then((resp) => {
                window.localStorage.setItem('accessToken', resp.body.data.data.accessToken);
                window.localStorage.setItem('refreshToken', resp.body.data.data.accessToken);
                cy.visit(`${process.env.TM_API_URL}/`+TMURL+``, {failOnStatusCode: false})
            })
    });

But I get the following error. The URL I need to post to in order to get the access token, is a different domain than the base url. So using the base in the post will not work for me.

cy.request() must be provided a fully qualified url - one that begins with 'http'. By default cy.request() will use either the current window's origin or the 'baseUrl' in cypress.json. Neither of those values were present.

like image 244
TestRaptor Avatar asked Jun 03 '19 16:06

TestRaptor


2 Answers

Try this one:

In cypress.json

{
  "env": {
    "EXTERNAL_API": "https://jsonplaceholder.typicode.com/todos/1"
  }
}

In support/commands.js

Cypress.Commands.add('logInAs3', (Useremail, Userpwd, TMURL) => {
  cy.request({
    method: 'POST',
    url: `${Cypress.env('EXTERNAL_API')}/loginWithToken`,
    body: {
      user: {
        email: Useremail,
        password: Userpwd,
      }
    }
  })
    .its('body')
    .then((body) => {
      window.localStorage.setItem('accessToken', body.data.data.accessToken);
      window.localStorage.setItem('refreshToken', body.data.data.accessToken);
    })
});

Inside your test

beforeEach(() => {
  cy.logInAs3()
})

it('check localStorage token', () => {
  cy.visit()
  expect(localStorage.getItem('accessToken')).not.null
  expect(localStorage.getItem('refreshToken')).not.null
})
like image 153
Danny Avatar answered Sep 21 '22 22:09

Danny


Based on the @Danny answer, you can use the cypress-localstorage-commands package to persist localStorage and reuse same user session for all tests in a block:

In cypress.json

{
  "env": {
    "EXTERNAL_API": "https://jsonplaceholder.typicode.com/"
  }
}

In support/commands.js

import "cypress-localstorage-commands";

Cypress.Commands.add('logInAs', (UserEmail, UserPwd) => {
  cy.request({
    method: 'POST',
    url: `${Cypress.env('EXTERNAL_API')}/loginWithToken`,
    body: {
      user: {
        email: UserEmail,
        password: UserPwd,
      }
    }
  })
    .its('body')
    .then((body) => {
      cy.setLocalStorage("accessToken", body.data.accessToken);
      cy.setLocalStorage("refreshToken", body.data.refreshToken);
    });
});

Inside your tests:

describe("when user FOO is logged in", ()=> {
  before(() => {
    cy.logInAs("[email protected]", "fooPassword");
    cy.saveLocalStorage();
  });

  beforeEach(() => {
    cy.restoreLocalStorage();
    cy.visit("");
  });

  it('should exist accessToken in localStorage', () => {
    cy.getLocalStorage("accessToken").should("exist");
  });

  it('should exist refreshToken in localStorage', () => {
    cy.getLocalStorage("refreshToken").should("exist");
  });
});
like image 24
Javier Brea Avatar answered Sep 20 '22 22:09

Javier Brea