Setting cookies before browser.get

All we need is an easy explanation of the problem, so here it is.

Our (PHP) application requires certain cookies to be set in order to load an Angular.js client app. If the cookies are not set an exception is thrown and error page is shown.

This means in order to run E2E tests we need to set the cookies, but the following fails because Protractor is trying to find Angular right after the browser.get call (it’s not there because the exception was thrown).

browser.get('http://' + domain + '/');
browser.manage().addCookie('foo', 'boo', '/', domain);

I tried to call browser.get after setting the cookies:

browser.manage().addCookie('foo', 'boo', '/', domain);
browser.get('http://' + domain + '/');

But this produces the following error:

Failed to set the ‘cookie’ property on ‘Document’: Cookies are
disabled inside ‘data:’ URLs.

Is there a way how to handle this situation? Perhaps to tell Protractor not to check for Angular when doing the first browser.get call or somehow set cookies for our domain before calling getting the URL?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I found the solution in the Protractor Getting Started doc:

browser.driver.get('http://' + domain + '/');
browser.manage().addCookie('foo', 'boo', '/', domain);

Note the browser.driver.get instead of browser.get. This will prevent Protractor looking for the Angular app and cookies can be set. I then use another browser.get inside of it statement.

Method 2

addCookie with newer Protractor versions (tested with 5.4.2) takes an object of type IWebDriverOptionsCookie instead.

Note: to fetch the cookie use getCookies

Example:

browser.manage().addCookie({ name: 'foo', value: 'bar' });

IWebDriverOptionsCookie documentation:

interface IWebDriverOptionsCookie {
  /** The name of the cookie. */
  name: string;

  /** The cookie value. */
  value: string;

  /** The cookie path. Defaults to "/" when adding a cookie. */
  path?: string;

  /**
   * The domain the cookie is visible to. Defaults to the current browsing
   * context's document's URL when adding a cookie.
   */
  domain?: string;

  /**
   * Whether the cookie is a secure cookie. Defaults to false when adding a new
   * cookie.
   */
  secure?: boolean;

  /**
   * Whether the cookie is an HTTP only cookie. Defaults to false when adding a
   * new cookie.
   */
  httpOnly?: boolean;

  /**
   * When the cookie expires.
   *
   * When adding a cookie, this may be specified in seconds since Unix epoch (January 1, 1970).
   * The expiry will default to 20 years in the future if omitted.
   *
   * The expiry is always returned in seconds since epoch when
   * retrieving cookies from the browser.
   *
   * @type {(!Date|number|undefined)}
   */
  expiry?: number | Date;
}

Method 3

As far as browser.driver.get() returns a promise, you should take it into account:

browser.driver.get('http://' + domain + '/').then(() => {
  browser.manage().addCookie({name: 'foo', value: 'boo'});
});

Also notice, in this case you don’t need to pass domain value to addCookie because protractor will use the current domain by default.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply