Reputation: 2183
I'm using Protractor (with Jasmine) to test my AngulaJs application.
As result of some of my action I get some data saved in the localStorage. Now I need to test other case, so I need to empty my storage (or better delete only some items) but If I try to run:
browser.executeScript('localStorage.removeItem("config");');
I get the following error:
UnknownError: <unknown>: Failed to read the 'localStorage' property from 'Window': Storage is disabled inside 'data:' URLs.
(Session info: chrome=35.0.1916.153)
(Driver info: chromedriver=2.10.267517,platform=Mac OS X 10.9.2 x86_64)
Any idea on how to solve?
Thanks in advance
Upvotes: 27
Views: 29959
Reputation: 8948
If you want the full control of your storage, use this class
class Storage {
constructor(storage) {
// 'localStorage' or 'sessionStorage'
this.storage = storage;
}
/**
* get local/session storage as object
* @returns {Promise<Object>}
*/
async get() {
log(`${this.storage}.get()`);
let keys = await browser.executeScript(`return Object.keys(window.${this.storage});`),
storage = {};
for (let key of keys) {
storage[key] = await browser.executeScript(`return window.${this.storage}.getItem('${key}');`);
}
return storage;
}
/**
* Clear local/session storage
* @returns null
*/
async clear() {
log(`${this.storage}.clear()`);
return browser.executeScript(`return window.${this.storage}.clear();`);
}
/**
* Set a value of local/session storage
* @param key
* @param value
* @returns
*/
async setValue(key, value) {
log(`${this.storage}.setValue(${key}, ${value})`);
return browser.executeScript(`return window.${this.storage}.setItem('${key}', '${value}');`);
}
/**
* Get value of a key of local/session storage
* @param key
* @returns
*/
async getValue(key) {
log(`${this.storage}.getValue(${key})`);
return browser.executeScript(`return window.${this.storage}.getItem('${key}');`);
}
async removeItem(key) {
log(`${this.storage}.removeItem(${key})`);
return browser.executeScript(`return window.${this.storage}.removeItem('${key}');`);
}
}
and then use it
let sessionStorage = new Storage('sessionStorage'),
localStorage = new Storage('localStorage');
// get storage as JSON
console.log(await sessionStorage.get())
// clear storage
await localStorage.clear();
// set key
await localStorage.setValue('key', 'value');
// and many more
Upvotes: 0
Reputation: 980
If there's still a problem with the localStorage when executing a "removeItem()", you can use a try-catch, like:
browser.executeScript("try {localStorage.removeItem('access_token');} catch(exception) {}");
Upvotes: 3
Reputation: 8062
I solved this issue by checking the window.location before attempting to clear/modify sessionStorage or localStorage.
If a page has not been loaded then window.location.hostname
will equal the empty string ''
. So if you get the emptystring, then don't attempt to interact with sessionStorage
or localStorage
.
Here's some (ES6) code I used in my protractor suite to prevent this error. Note it's a cucumber-js After function, but it is still executed from protractor using chrome, and it demonstrates what you need to do to avoid this error:
this.After(function(scenario) {
function getWindowLocation() {
return window.location;
}
function clearStorage() {
window.sessionStorage.clear();
window.localStorage.clear();
}
return browser.executeScript(getWindowLocation).then(function(location) {
// NB If no page is loaded in the scneario then calling clearStorage will cause exception
// so guard against this by checking hostname (If no page loaded then hostname == '')
if (location.hostname.length > 0) {
return browser.executeScript(clearStorage);
}
else {
return Promise.resolve();
}
});
});
Upvotes: 5
Reputation: 12437
It's because you haven't navigated to a valid url yet. Do a browser.get('/foo')
before trying to interact with page objects like localStorage
.
Upvotes: 19
Reputation: 3474
Another potential solution is to put any state clearing in an afterEach, which will run after any test is run: (see https://github.com/angular/protractor/issues/188)
afterEach(function() {
browser.executeScript('window.sessionStorage.clear();');
browser.executeScript('window.localStorage.clear();');
});
Upvotes: 41
Reputation: 2183
I haven't found a cool way to do that, but if I run my statement
browser.executeScript("localStorage.removeItem('config');")
within a it('description') statement it works. Example:
it('should compile and save base config for billing',function(){
browser.executeScript("localStorage.removeItem('config');")
//my test
});
This remove the item named config, and so my test works, but while searching and talking about this issue the main response I got is:
"localStorage is not you product, so you don't need (read: you must not) test it. The right way is to mock it and inject it contents when they are needed"
I'm still looking into this to understrand how, meanwhile I think that a not philosophically perfect test is still better than nothing so..
Hope this helps...
Upvotes: 3