SH0CK
SH0CK

Reputation: 61

How to set cookies in Cypress before visiting react app running on localhost

The steps I want to take are:

  1. Start the Cypress test-suite and use cy.setCookie to set the JSESSIONID cookie (already acquired and up-to-date)
  2. After the cookie is set, then use cy.visit to access the running app

The issue:

What I have done so far:

Cypress.Cookies.defaults({
  preserve: 'JSESSIONID'
})

cy.setCookie('JSESSIONID', Cypress.env('JSESSIONID'), {
  path: '/',
  domain: '<domain.name>',
  httpOnly: true,
  secure: true,
  sameSite: 'no_restriction',
  log: true,
}).then(() => cy.visit('localhost:3000/<authenticated-route>')

It might be worth mentioning that <domain.name> is of the form www.staging.etc.com whereas is running locally: localhost:3000/

Any help would be greatly appreciated. Thanks in advance

Upvotes: 5

Views: 19378

Answers (5)

Paul Murdin
Paul Murdin

Reputation: 175

To set the cookie in the onBeforeLoad hook and avoid the error from cy.setCookie(), you can use Cypress.browser

cy.visit('http://localhost:3000/#dashboard', {
  onBeforeLoad: (contentWindow) => {
    Cypress.browser.cookies.set({
      path: '/',
      domain: '<domain.name>',
      httpOnly: true,
      secure: true,
      sameSite: 'no_restriction',
      log: true,
    })
  }
})

Upvotes: 6

froblesmartin
froblesmartin

Reputation: 1891

What you could also do, is set the cookie with the Cookie HTTP header:

cy.visit('/whatever', {
  headers: {
    'Cookie': '<cookie-name>=<cookie-value>'
}})

Upvotes: 1

SH0CK
SH0CK

Reputation: 61

I solved the issue by doing a cy.request to login before using cy.visit.

Code looks something like this:

const login = () => {
  const headers = new Headers()
  headers.append("Content", "application/x-www-form-urlencoded")
  headers.append("Accept-Encoding", "gzip:deflate")
  headers.append("Content-Type", "application/x-www-form-urlencoded")

  cy.request({
    url: Cypress.env("LOGIN_URL"),
    method: 'POST',
    form: true,
    headers,
    body: {
      "email": Cypress.env("EMAIL"),
      "password": Cypress.env("PASSWORD")
    }
  }).then((response) => {
    console.log(response)
    console.log(response.body)
    setCookie(response.COOKIE)
  })
}

export const loginAndStartTests = () => {
  login()
  cy.visit('/<homepage>')
}

Upvotes: 0

Pavel
Pavel

Reputation: 11

You need to set a cookie from the argument contentWindow:

A cookie setter util:

export const setCookieToContentWindow = (
  contentWindow,
  name,
  value,
  { expireMinutes = 1 } = {},
) => {
  const date = new Date();
  const expireTime = expireMinutes * 60 * 1000;

  date.setTime(date.getTime() + expireTime);

  const assignment = `${name}=${encodeURIComponent(value)}`;
  const expires = `expires=${date.toGMTString()}`;
  const path = 'path=/';

  contentWindow.document.cookie = [assignment, expires, path].join(';');
};

Using onBeforeLoad:

cy.visit('http://localhost:3000/#dashboard', {
  onBeforeLoad: (contentWindow) => {
    setCookieToContentWindow(contentWindow, 'COOKIE_NAME', 'COOKIE_VALUE');
  },
});

Upvotes: 1

user14783414
user14783414

Reputation:

Take a look at Provide an onBeforeLoad callback function

The example recipe mentioned (code is here) is setting a token in local storage, but should apply as well to cookies

cy.visit('http://localhost:3000/#dashboard', {
  onBeforeLoad: (contentWindow) => {
    cy.setCookie('JSESSIONID', Cypress.env('JSESSIONID'), {
      path: '/',
      ...
    })
  }
})

I think the problem is that cy.visit() is one of the places where everything is cleared down, but the hook is provided to get around that. Although, I would expect preserve to work as well.

Upvotes: 3

Related Questions