Search code examples
javascriptangularjslocal-storageprotractorangular-local-storage

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?


Solution

  • 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.