Write Value to Local Storage via JavaScript in C# Test code...

4,203 views
Skip to first unread message

mawa316

unread,
Jul 31, 2015, 3:45:14 PM7/31/15
to Selenium Users
Hi there,
 
I think I mistakenly posted in the Selenium Developers group so I'll go ahead and repeat here as I don't know if my original post will be moved here or not.
 
What I'm trying to do is write a value to Local Storage in Firefox near the beginning of my test.  I've searched and it seems that this can be done with JavaScript.  Some posts indicate it could be a few lines of code to simply execute the JavaScript statement...
 

            IJavaScriptExecutor js = driver as IJavaScriptExecutor;


            String script = "localStorage.setItem('webApiUrl', 'http://localhost:49240/api/');";


            js.ExecuteScript(script);

...

Trying this gets me...
Message: Test method MyApp.SeliniumUITest.UnitTest1.TestMethod1 threw exception:
System.InvalidOperationException:  (UnexpectedJavaScriptError).
So, I'm not sure if its possible to do what I'd like in these few lines of code.  I wonder if I need to have an external .js file added to my project as a reference or something to that effect. ??
 
Here's my code so far.  Go easy on me as I'm fairly new to Selenium, C# and JavaScript.  I don't know whether to laugh or cry about that.  It's all good as I'm learning!!
 
Anyway, here's the overall code so far...
 

public class UnitTest1


    {


        //FirefoxDriver firefox;


        IWebDriver driver = new FirefoxDriver();



        // This is the test to be carried out...


        [TestMethod]


        public void TestMethod1()


        {



            // Write webApiUrl=""http://localhost:49240/api/"" to local storage


            //IWebDriver jdriver; // assume assigned elsewhere



            IJavaScriptExecutor js = driver as IJavaScriptExecutor;


            String script = "localStorage.setItem('webApiUrl', 'http://localhost:49240/api/');";


            js.ExecuteScript(script);



 


            //firefox = new FirefoxDriver();


            driver.Navigate().GoToUrl("http://localhost:52276/login");



 


            // Implicit wait until Element is present...


            driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));



            // Explicit wait...


            //WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));


            //IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>


            //{


            //    return d.FindElement(By.Id("login-name"));


            //});



            // Login...


            driver.FindElement(By.Id("login-name")).Clear();


            driver.FindElement(By.Id("login-name")).SendKeys("adm");


            //driver.FindElement(By.Id("login-password")).Clear();


            //driver.FindElement(By.Id("password")).SendKeys("");



            driver.FindElement(By.Id("login-button")).Click();



           


           



        }



        // This closes the driver down after the test has finished.


        [TestCleanup]



        public void TearDown()


        {


            driver.Quit();


        }



 


 


    }


 Again, any help you can give would be greatly appreciated!!!  THANK YOU!!
 

David

unread,
Aug 1, 2015, 1:01:19 AM8/1/15
to Selenium Users
You might want to read this: http://diveintohtml5.info/storage.html

LocalStorage is attached to browser window object in javascript, you don't access it directly. I do recall Selenium client bindings should have methods that deal with local storage so you don't have to go the direct javascript route. But you still can if the binding's don't seem to offer simplified access to it.

mawa316

unread,
Aug 1, 2015, 11:05:15 AM8/1/15
to Selenium Users
I think I did see that, but what I was trying was still not working.  I guess I'll keep hacking away at it.

Thanks for the reply!

mawa316 .

unread,
Aug 3, 2015, 7:30:27 PM8/3/15
to seleniu...@googlegroups.com
This seems to work!!....
 

IJavaScriptExecutor js = driver as IJavaScriptExecutor;

js.ExecuteScript("window.localStorage.setItem('webApiUrl', 'http://localhost:49240/api/');");

 

Someone please let me know if this could be streamlined or if there may be any pitfalls!

 

Thanks All!


--
You received this message because you are subscribed to a topic in the Google Groups "Selenium Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/selenium-users/DmPyAMPyy44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to selenium-user...@googlegroups.com.
To post to this group, send email to seleniu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/selenium-users/538e6249-c044-4338-9d66-5cfcc726af6b%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

David

unread,
Aug 3, 2015, 11:46:39 PM8/3/15
to Selenium Users
Good for you. That's actually what I meant/implied on how to access local storage (being bound to window object, access window object 1st then localstorage from it).

I don't see anything wrong with using it that way, as long as the target browser supports local storage. What do you mean by streamline? That's about as simple as it gets other than wrapping that code snippet into a method to hide away the JS executor logic.

Ideally though you should check for the official Selenium API methods for local storage if they exist for target browser (they don't for Safari, so what you have is good for Safari), instead of going directly with JS approach.

mawa316

unread,
Aug 5, 2015, 11:31:08 AM8/5/15
to Selenium Users
Here's what I found.  I do get the value to Local Storage, however I am still unable to login during the test because the url is still not found.
 
Here is the order of operations...
 

IWebDriver driver = new FirefoxDriver();


driver.Navigate().GoToUrl("http://localhost:12345/login");

// Write webApiUrl to local storage...

IJavaScriptExecutor js = driver as IJavaScriptExecutor;
js.ExecuteScript("window.localStorage.setItem('webApiUrl', 'http://localhost:49240/api/');");

If I put the script code before I navigate to the site Firefox just launches and does nothing.
 
I wonder if there is a way, after setting up the driver, to do something like this  driver.SetLocalStorage or something to that effect.  I thought I saw reference to something like that, but nothing I tried worked.

David

unread,
Aug 6, 2015, 12:38:57 AM8/6/15
to Selenium Users
So the localhost login page makes use of the webApiUrl as part of the login? But you still have to manually login (well automate with selenium here) right? Meaning visiting the login page doesn't auto log you in based on the local storage value or does it?

In any case, do note that local storage behaves like cookies and are domain/site specific. That means, they can't be set (or cleared) prior to being on the domain of interest. So in order to set (or clear) an item, you first must be on the domain, which per your code you do.

But there's another caveat. Setting an item like that (especially via javascript instead of native Selenium APIs), it will not immediately persist or take effect on the page you are on. This is not an issue if you use the item value on another page on the site, it takes effect when you navigate there next. But if you need it on the same page, you'll need to specifically invoke a page refresh to "see" the recently set item. This behavior may also be observed with cookies added/modified/deleted (they don't take effect immediately on same page and require page refresh).
...

mawa316 .

unread,
Aug 6, 2015, 10:23:39 AM8/6/15
to seleniu...@googlegroups.com
Ah, page refresh, I bet that was the issue.
 
I can't really test it as development has told me that this mechanism has been changed as it pertains to login.  They will be using a default for now.
 
However, I do want to make note of the Selenium page refresh code as I'll probably need that down the road.  More research!!
 
Thanks for that information!!

--
You received this message because you are subscribed to a topic in the Google Groups "Selenium Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/selenium-users/DmPyAMPyy44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to selenium-user...@googlegroups.com.
To post to this group, send email to seleniu...@googlegroups.com.

mawa316 .

unread,
Aug 20, 2015, 11:26:20 PM8/20/15
to seleniu...@googlegroups.com
I need a little more help with local storage again.  On login to our web app there is a local storage value written that contains the words login, token and a long guid that changes per login.  On logout, these are gone and when I check the storage value I see """".
 
What I would like to do is make use of .getItem, but I'm not getting good results.  On login I was thinking I could possible do getItem('keyname').indexOf('login') or one of the other terms and then validate with Assert.  I just can't get it to work.
 
On logout I would think I could have checked Assert.IsNull, but that is giving inconsistent results.  That's probably thrown off by """" remaining after logout.
 
So, I would like to check the value on Login and ensure its been cleaned up on Logout.  Can anyone give me some pointers?

David

unread,
Aug 21, 2015, 9:22:35 PM8/21/15
to Selenium Users
Well, you'd probably 1st want to debug this on the browser before continuing on the Selenium side. Here's what I recommend. Set breakpoints in your test and run in debug mode.

During the breakpoints (before login?, after login, after logout), query for the local storage data but do that directly from javascript via the browser's developer/javascript console (in Chrome/Safari or Firebug console). If it don't look right in browser, it's not going to be right in Selenium.

As a comparison, you should also do this debug process manually w/o Selenium 1st. Manually login, logout and query for the local storage data from browser console. When that's good, you know you can then go to debug mode in C# with the Selenium test. If manual session fails, no point in doing debug mode.

mawa316 .

unread,
Aug 21, 2015, 9:37:26 PM8/21/15
to seleniu...@googlegroups.com
I had already debugged through the C# test. I most always if not always saw null returned.
 
If I look in the browser storage both during the C# debugging and outside of running the test code, I see what is expected...
 
userinfo storage value displays as...

"{"loginName":"alittle","...1485589cda0df41a2e39c"}"

When I log out, the value is displayed in local storage as ...

""""

That's four double quotes.

 

I just need to make sure it has the longer string after login and whatever the value is displayed above when logged out.  When I double click on the logged out value displayed I see escaped quotes as follows - "\"\"".  I guess I'll play around with that a bit.


--
You received this message because you are subscribed to a topic in the Google Groups "Selenium Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/selenium-users/DmPyAMPyy44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to selenium-user...@googlegroups.com.
To post to this group, send email to seleniu...@googlegroups.com.

mawa316 .

unread,
Aug 21, 2015, 10:16:08 PM8/21/15
to seleniu...@googlegroups.com
I'm able to finally get a non null return from local storage with:

String storageValue = (String)js.ExecuteScript("return localStorage.getItem('ngStorage-userInfo')");

Now the problem is this...  I think I'm running up against a timing issue of some sort.  I leave the browser open on my test so I can check local storage when the login page is once again displayed.  I'm getting the full login screen in the code while local storage shows """" in the browser.

 

Everything seems to work properly in my Login test where I use the following code...

 

driver.FindElement(By.Id("user-dropdown"));

// Check local storage for login token

IJavaScriptExecutor js = driver as IJavaScriptExecutor;

 

 

 

 

 

String storageValue = (String)js.ExecuteScript("return localStorage.getItem('ngStorage-userInfo')");

// Assert that the local storage value is not empty (contains login token information)...

Assert.AreNotEqual("\"\"", storageValue);

 

I wonder why I'm not seeing the same timing like scenario as I see in the Logout test. ?  I don't want to use Thread.sleep method of doing things.  I would have hoped that the local storage would have been cleared before the user name element on the login screen was displayed.

David

unread,
Aug 23, 2015, 12:29:30 AM8/23/15
to Selenium Users
Maybe you should check with your devs on the sequence of events as in when do they actually clear out local storage in their code vs displaying login page. Then you would know when to do the checks based on that or what to wait for before proceeding with the checks.

As a last resort, you may actually have to use Thread.sleep or a forced page refresh (to be able to expect local storage to be cleared by then I suppose).
...

mawa316 .

unread,
Aug 23, 2015, 9:04:36 PM8/23/15
to seleniu...@googlegroups.com
I think I like driver.Navigate().Refresh better than Thread.Sleep at this point because that too works!

--
You received this message because you are subscribed to a topic in the Google Groups "Selenium Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/selenium-users/DmPyAMPyy44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to selenium-user...@googlegroups.com.
To post to this group, send email to seleniu...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages