sjt003
sjt003

Reputation: 2607

How to set sessionStorage in PhantomJS and CasperJS?

The sessionStorage is not properly set using the below script. I'm trying to set the storage in a page.evaluate callback, but I'm not having any luck and my "complete" check endlessly loops. I've encountered the very same problem with casper, trying a similar pattern of evaluate and reload. I can't test because all ajax requests use sessionStorage to pick up the authorization JWT. I know I should have access to window in evaluate so I'm not sure why this isn't working.

var page = require("webpage").create();
var url = "http://xxxxxxxx.com";
var t0 = Date.now;
function onPageReady() {
    var t1 = Date.now;
    var elapsed = t1 - t0; 
    var htmlContent = page.evaluate(function () {
        return document.documentElement.outerHTML;
    }); 
    console.log(htmlContent);
    console.log("ELAPSED TIME: " , elapsed + "\n") ;
    phantom.exit(0);
}

page.open(url, function (status) {
    var sessionStorage = page.evaluate(function(){
      sessionStorage.setItem('authorization','xxxxxxxxxxxxxxxxx');
      //window.sessionStorage.setItem('authorization','xxxxxxxxxx');
      window.sessionStorage.setItem('_USER','value');
      window.sessionStorage.setItem('USERNAME','value');
      window.sessionStorage.setItem('INTERNAL','value');
      console.log(window.sessionStorage);
      return sessionStorage;
    }); 
    t0 = Date.now;
    console.log(JSON.stringify(sessionStorage));
    console.log(JSON.stringify(window.sessionStorage));
    function checkReadyState() {
        setTimeout(function () {
            var readyState = page.evaluate(function () {
                return document.readyState;
            }); 

            if ("complete" === readyState) {
              // checking if my ng-repeat has loaded
              if (document.getElementsByClassName('quoteTr').length > 1){ 
                  console.log("ready!")
                  onPageReady();
              } else {
                  console.log("script not complete")
                  checkReadyState();
              }   
            } else {
                checkReadyState();
            }   
        }); 
    }   

    checkReadyState();
});

Upvotes: 2

Views: 1415

Answers (1)

Artjom B.
Artjom B.

Reputation: 61892

If you're setting the sessionStorage inside of the page context (inside page.evaluate()), then you need to retrieve it in the page context. Although, sessionStorage exists outside of the page context, it is some dummy object which has no access to the page's sessionStorage.

page.evaluate(function(){
    sessionStorage.setItem('authorization','xxxxxxxxxxxxxxxxx');
});
var authorization = page.evaluate(function(){
    sessionStorage.getItem('authorization');
});
console.log("authorization: " + authorization);

Since sessionStorage is a non-primitive object, you can't pass it outside of the page context. You can only pass representations of it, such as its key-value pairs. For the docs:

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!

The same is true in CasperJS.


On the subject of "looping". I see three problems with your code.

First Date.now is a reference to a function. If you want the current time, then you have to call it as Date.now().

You're not giving PhantomJS much time to do any work. You're essentially using setTimeout() without a second parameter which defaults to 0 which means the callback is immediately called. Try using a small timeout such as 50: setTimeout(function(){...}, 50).

You're trying to access document.getElementsByClassName('quoteTr') outside of the page context, but document is only a dummy object, so it will always return an empty array no matter what happens on the page. You have to use page.evaluate(). CasperJS provides the casper.exists() function for such as case.


I haven't exactly understood why you need to set some sessionStorage values, but if you need to set them as soon as possible for the page, then you can try to employ two different strategies:

  • Open the page normally, set the values to the sessionStorage and then load the page again so that the page's JavaScript picks up the values.

  • You can try to register to page.onLoadStarted, page.onNavigationRequested or page.onUrlChanged events in order to set the session values as soon as possible.

Upvotes: 3

Related Questions