Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Protractor wait for a localStorage change (caused by REST call)?

I am using Protractor to test whether a value gets set in localStorage after a login submit. If I bind the localStorage value to a DOM-element, Protractor automatically waits for the REST response (after the login submit), checks the value and tests it. But I would like test the value of localStorage without writing it to the DOM. Before each test I clear the localStorage.

browser.executeScript("window.localStorage.clear();");

I can get the value in the test.

var key = browser.executeScript("return window.localStorage.getItem('ngStorage-initKey');")

But that happens too early. I also tried returning that value in a browser.wait() statement, but in that case, it seems like the return value is not usable by wait(). probably because it's not a promise.

I would even consider giving protractor access to the the $localStorage instance from ngStorage if that would solve this.

Can anyone tell me if watching localStorage values async with Protractor is possible, and if so, how to approach this?

like image 977
Micros Avatar asked Jan 21 '26 15:01

Micros


2 Answers

What turned out to be the solution, was how to handle the promise which browser.executeScript returns.
And it's good news: Protractor is already async, so custom waiting is not necessary. However, you should not just check if the returned value is of type string or isEqual to an expected string. But matching it via regular expressions works fine, whether you get a string or a promise returned. For example, if I expect a hash of 40 characters, you can match it like this:

it('should store key in localStorage when logging in', function() {
    loginFormSubmitButton.click();
    var newUserKey = browser.executeScript("return window.localStorage.getItem('ngStorage-userKey');");
    expect(newUserKey).toMatch(/^\"[a-f0-9]{40}\"$/i);
});

Feels like magic, but the expect statement actually waits for the promise to resolve. In this case that means a call to the server is made or mocked, the result is written into localStorage and detected as-it-happens by the expect statement.
No need for custom timeouts.

like image 166
Micros Avatar answered Jan 24 '26 06:01

Micros


You probably aren't waiting correctly in your browser.wait() function, the value doesnt have to be a promise, just a simple boolean value, that exits the wait once it's true, the following will work:

browser.wait(function () { 
    return browser.executeScript("return window.localStorage.getItem('ngStorage-initKey');") 
    == theValueYouExpect;
}, 5000);

read more about protractors wait !

Alternatively, browser.executeScript("window.localStorage.clear();"); returns a promise AFTER the script was executed, (but not neccessarily the script finished, if it is async), so here another solution will be:

browser.executeScript("window.localStorage.clear();")
    .then(function (){
    browser.executeScript("return window.localStorage.getItem('ngStorage-initKey');")
        .then(function (key) {//do something with the key});
});
like image 42
vrachlin Avatar answered Jan 24 '26 05:01

vrachlin