Thursday, February 25, 2016

The black hole in localStorage.setItem()

TL;DR

To fake some local storage data in Protractor E2E test, care about 2 things:
  • localStorage can not store Object directly, so you have to JSON.stringify it and then JSON.parse to get it back.
  • browser.executeScript actually returns a Promise, so you should JSON.parse the data received by its then function.
Now let's see how I created a black-hole in localStorage by setItem()

According to this thread I thought I found the way to store fake data into localStorage, so I brain-less-ly wrote code as below


Running this test threw me the expectation error, which indicate that data is a [object Object]

WTH is a [object Object] ? I'm not familiar with that.
Googling for a while gave me that setItem() will convert value to string before storing it to local storage, don't know how it convert, just not the JSON way.

Applied JSON.stringify() before setItem(), and JSON.parse() before expectation, as below
expect(JSON.parse(data)).toEqual(fakeLocalData);

Then the error evolved to:
Failed: Unexpected token P

I couldn't recognize this strange error either so it became really frustrating.
It's like my fakeLocalData was sucked into another dimension and never comes back.

The cause to my fail is well-explained in this article.
I should noted this quote for myself:
WebDriverJS (and thus, Protractor) APIs are entirely asynchronous. All functions return promises.
All functions return promises !!!
All functions return promises !!!
All functions return promises, you pathetic TDD developer!!!

So what I JSON.parse is actually a promise object, not the original stored data which is JSON.stringified.
I didn't realize this behavior of Protractor because Jasmine's expect() function takes good care of promises.
You can pass a regular variable or a promise to expect(), either way it can consume the parameter and knows what you want.
Hail to expect()~!!

So cut the crap, the right way to setItem() in Protractor is JSON.stringify it in advance, and the right way to get it back is kind of like this:

1 comment: