How to access localStorage from custom command?

2,724 views
Skip to first unread message

GrayedFox

unread,
Nov 10, 2015, 5:18:14 AM11/10/15
to NightwatchJs
I can't figure out how to do this!

Have tried passing the client (browser) to the custom function and using:

client.localStorage
client.window.localStorage

Also using:

this.localStorage
this.window.localStorage

But they are all undefined. 

I need the information stored locally on my machine after logging into our website, and I know the exact key name and can see the existing key inside my Local Storage on Chrome and Firefox after logging in.

Problem is scope, probably something obvious I'm missing, but I can't figure it out. 

Thanks in advance!

Andrei Rusu

unread,
Nov 10, 2015, 8:35:05 AM11/10/15
to nightw...@googlegroups.com
Your best bet is to use .execute() for now. In the future we might
implement the selenium localStorage commands.
> --
> You received this message because you are subscribed to the Google Groups
> "NightwatchJs" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to nightwatchjs...@googlegroups.com.
> To post to this group, send email to nightw...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/nightwatchjs/3a02f4f1-2abe-4acb-94a0-3f1e422f5e16%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

GrayedFox

unread,
Nov 11, 2015, 11:45:03 AM11/11/15
to NightwatchJs
Hi Andrei thanks for the speedy reply,

I am using this code in my custom command at the moment:

exports.command = function(client, callback) {
  var self = this;

  this.execute(function getStorage() {
    client.globals.session = document.window.localStorage.getItem('__ef__');
    console.log(document.window.localStorage.getItem('__ef__'));
  })

  // ensures command is chainable
  if (typeof callback == 'function') {
    callback.call(self);
  }
};

However I notice that:

a) nothing appears in the output during the test (from the console log)
b) as far as I can tell, from logging the global.session object in a later test, these values have not changed

No errors are thrown when running the test however.

GrayedFox

unread,
Nov 11, 2015, 11:49:38 AM11/11/15
to NightwatchJs
Note: there is a missing semicolon in the above code snippet which is present in my code.

Che Fisher

unread,
Nov 11, 2015, 12:31:16 PM11/11/15
to nightw...@googlegroups.com
Sorry for the spam - I figured the scope of the console.log in the above example would be tied to the window (hence any output would appear there instead of in my terminal) - so I tried appending .bind(self); to it, and still no luck.

Che Fisher

Quality Assurance Analyst @ EatFirst GmbH
m: +49 176 4566 3935 



--
You received this message because you are subscribed to a topic in the Google Groups "NightwatchJs" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nightwatchjs/_EABR-ZbzJs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nightwatchjs...@googlegroups.com.

To post to this group, send email to nightw...@googlegroups.com.

Che Fisher

unread,
Nov 11, 2015, 2:08:55 PM11/11/15
to nightw...@googlegroups.com
Okay... good news. I've manage to access the local storage by digging a little deeper, and making sure I do the handy work in the callback function passed. So, the working (but unoptimised) code looks like this:

exports.command = function(session, callback) {
  var self = this;

  this.execute(function getStorage() {
    session = window.localStorage.getItem('__ef__');
    return session;
  },

  // allows for use of callbacks with custom function
  function(result) {
    if (typeof callback === 'function') {
      callback.call(self, result);
    }
  });

  // allows command to be chained
  return this;
};

And the calling test looks like this:

function hweAccLogin(client, user, pass) {
  var eFormEmail = '#email';
  var eFormPass = '#password';
  var eButton = 'user-login .button';
  var eLogout = 'app-navigation a[href="/logout"]';
  var session = {};

  client
    .waitForElementVisible(eFormEmail, 1000, 'Email field %s visible after %d ms')
    .setValue(eFormEmail, user)
    .waitForElementVisible(eFormPass, 1000, 'Password field %s visible after %d ms')
    .setValue(eFormPass, pass)
    .waitForElementVisible(eButton, 1000, 'Login button %s visible after %d ms')
    .click(eButton)
    .waitForElementVisible(eLogout, 1000, 'Logout link present - user logged in successfully')
    .setAuth(session, function showSession() {
      client.globals.session = session;
      console.log(client.globals.session);
    });
}

This function is called from the actual test file, using the my globals.js file (which itself requires the .js file containing the log in function, and then exports it).

It's complex but allows for recycling some code while still forcing me to write everything async friendly. And, it works!

My problem now is that I thought I would be able to simply call client.setAuth as follows, without the optional callback parameter:

client.setAuth(client.globals.session);

But this doesn't work. It's definitely in how I've structured the custom command - but any time I change something I somehow break the command (have tried a bunch of things) - and now I'm afraid that the only way for me to do this is to always pass a callback, which is wasteful. I only really wanted to follow the Nightwatch custom command guidelines and keep it nice and modular / chainable / etc.

Thanks for your time!

Che Fisher

Quality Assurance Analyst @ EatFirst GmbH
m: +49 176 4566 3935 



Che Fisher

unread,
Nov 11, 2015, 2:54:23 PM11/11/15
to nightw...@googlegroups.com
Edit: deleted post before this, code was wrong. Not showing up for me, might show up for others, apologies if it does.

So, progress has been made! I realised some of my mistakes as I climbed deeper down the rabbit hole.

Here is a function, called from my main test file. This function is in it's own .js file, which is linked to my globals.js file. The globals file requires it, then exports it. So, bit messy, but it works, given the Nightwatch config and setup (advice always welcome).

function hweAccLogin(client, user, pass) {
  var eFormEmail = '#email';
  var eFormPass = '#password';
  var eButton = 'user-login .button';
  var eLogout = 'app-navigation a[href="/logout"]';
  var session = {};

  client
    .waitForElementVisible(eFormEmail, 1000, 'Email field %s visible after %d ms')
    .setValue(eFormEmail, user)
    .waitForElementVisible(eFormPass, 1000, 'Password field %s visible after %d ms')
    .setValue(eFormPass, pass)
    .waitForElementVisible(eButton, 1000, 'Login button %s visible after %d ms')
    .click(eButton)
    .waitForElementVisible(eLogout, 1000, 'Logout link present - user logged in successfully')
    .setAuth(session, function showSession(result) {
      client.globals.session = result.value;
      console.log(client.globals.session);
      console.log(session);
    });
}

And here is the custom command:

exports.command = function(session, callback) {
  var self = this;

  this.execute(function getStorage() {
    session = window.localStorage.getItem('__ef__');
    return session;
  },

  // allows for use of callbacks with custom function
  function(result) {
    if (typeof callback === 'function') {
      callback.call(self, result);
    }
  });

  // allows command to be chained
  return this;
};

Now the first console.log outputs the expected information (that is, a specific key within the localStorage). 

The second console.log outputs an empty object - meaning the session variable I pass to the custom function never has it's value changed. 

I thought, given the structure of the setAuth custom command, I could simply call it with setAuth(variable); and that would set the variable to the returned result, but that is not working, as shown by the output.

Thanks for the helps!

Che Fisher

Quality Assurance Analyst @ EatFirst GmbH
m: +49 176 4566 3935 



On 11 November 2015 at 18:31, Che Fisher <che.f...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages