forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request elastic#8021 from spalger/reimplement/BrowserStora…
…geStub [stub/BrowserStorage] reimplement and test the BrowserStorage stub Former-commit-id: ce33785
- Loading branch information
Showing
3 changed files
with
177 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import expect from 'expect.js'; | ||
|
||
import StubBrowserStorage from '../stub_browser_storage'; | ||
|
||
describe('StubBrowserStorage', () => { | ||
describe('#getItem() / #setItem()', () => { | ||
it('stores items as strings', () => { | ||
const store = new StubBrowserStorage(); | ||
store.setItem(1, 1); | ||
expect(store.getItem(1)).to.be('1'); | ||
}); | ||
|
||
it('stores keys as strings', () => { | ||
const store = new StubBrowserStorage(); | ||
store.setItem(1, 1); | ||
expect(store.key(0)).to.be('1'); | ||
}); | ||
|
||
it('returns null for missing keys', () => { | ||
const store = new StubBrowserStorage(); | ||
expect(store.getItem('unknown key')).to.be(null); | ||
}); | ||
}); | ||
|
||
describe('#length', () => { | ||
it('reports the number of items stored', () => { | ||
const store = new StubBrowserStorage(); | ||
store.setItem(1, 1); | ||
store.setItem(2, 2); | ||
store.setItem(3, 3); | ||
store.setItem(4, 4); | ||
expect(store).to.have.length(4); | ||
}); | ||
|
||
it('does not trip on items getting reset', () => { | ||
const store = new StubBrowserStorage(); | ||
store.setItem(1, 1); | ||
store.setItem(1, 2); | ||
expect(store).to.have.length(1); | ||
}); | ||
}); | ||
|
||
describe('#key()', () => { | ||
it('returns the key as a specific index', () => { | ||
const store = new StubBrowserStorage(); | ||
store.setItem(1, 2); | ||
expect(store.key(0)).to.be('1'); | ||
expect(store.key(1)).to.be(undefined); | ||
}); | ||
}); | ||
|
||
describe('size limiting', () => { | ||
it('allows limiting the storage size', () => { | ||
const store = new StubBrowserStorage(); | ||
store._setSizeLimit(10); | ||
store.setItem('abc', 'def'); // store size is 6, key.length + val.length | ||
expect(() => { | ||
store.setItem('ghi', 'jkl'); | ||
}).throwError(/quota/); | ||
}); | ||
|
||
it('allows defining the limit as infinity', () => { | ||
const store = new StubBrowserStorage(); | ||
store._setSizeLimit(Infinity); | ||
store.setItem('abc', 'def'); | ||
store.setItem('ghi', 'jkl'); // unlike the previous test, this doesn't throw | ||
}); | ||
|
||
it('requires setting the limit before keys', () => { | ||
const store = new StubBrowserStorage(); | ||
store.setItem('key', 'val'); | ||
expect(() => { | ||
store._setSizeLimit(10); | ||
}).throwError(/before setting/); | ||
}); | ||
|
||
it('respects removed items', () => { | ||
const store = new StubBrowserStorage(); | ||
store._setSizeLimit(10); | ||
store.setItem('abc', 'def'); | ||
store.removeItem('abc'); | ||
store.setItem('ghi', 'jkl'); // unlike the previous test, this doesn't throw | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,92 @@ | ||
const store = Symbol('store'); | ||
const keys = Symbol('keys'); | ||
const values = Symbol('values'); | ||
const remainingSize = Symbol('remainingSize'); | ||
|
||
export default class StubBrowserStorage { | ||
constructor() { this[store] = new Map(); } | ||
getItem(k) { return this[store].get(k); } | ||
setItem(k, v) { return this[store].set(k, String(v)); } | ||
removeItem(k) { return this[store].delete(k); } | ||
getKeys() { return [ ...this[store].keys() ]; } | ||
getValues() { return [ ...this[store].values() ]; } | ||
constructor() { | ||
this[keys] = []; | ||
this[values] = []; | ||
this[remainingSize] = 5000000; // 5mb, minimum browser storage size | ||
} | ||
|
||
get length() { | ||
return this[keys].length; | ||
} | ||
|
||
key(i) { | ||
return this[keys][i]; | ||
} | ||
|
||
getItem(key) { | ||
key = String(key); | ||
|
||
const i = this[keys].indexOf(key); | ||
if (i === -1) return null; | ||
return this[values][i]; | ||
} | ||
|
||
setItem(key, value) { | ||
key = String(key); | ||
value = String(value); | ||
this._takeUpSpace(this._calcSizeOfAdd(key, value)); | ||
|
||
const i = this[keys].indexOf(key); | ||
if (i === -1) { | ||
this[keys].push(key); | ||
this[values].push(value); | ||
} else { | ||
this[values][i] = value; | ||
} | ||
} | ||
|
||
removeItem(key) { | ||
key = String(key); | ||
this._takeUpSpace(this._calcSizeOfRemove(key)); | ||
|
||
const i = this[keys].indexOf(key); | ||
if (i === -1) return; | ||
this[keys].splice(i, 1); | ||
this[values].splice(i, 1); | ||
} | ||
|
||
// non-standard api methods | ||
_getKeys() { | ||
return this[keys].slice(); | ||
} | ||
|
||
_getValues() { | ||
return this[values].slice(); | ||
} | ||
|
||
_setSizeLimit(limit) { | ||
if (this[keys].length) { | ||
throw new Error('You must call _setSizeLimit() before setting any values'); | ||
} | ||
|
||
this[remainingSize] = limit; | ||
} | ||
|
||
_calcSizeOfAdd(key, value) { | ||
const i = this[keys].indexOf(key); | ||
if (i === -1) { | ||
return key.length + value.length; | ||
} | ||
return value.length - this[values][i].length; | ||
} | ||
|
||
_calcSizeOfRemove(key) { | ||
const i = this[keys].indexOf(key); | ||
if (i === -1) { | ||
return 0; | ||
} | ||
return 0 - (key.length + this[values][i].length); | ||
} | ||
|
||
_takeUpSpace(delta) { | ||
if (this[remainingSize] - delta < 0) { | ||
throw new Error('something about quota exceeded, browsers are not consistent here'); | ||
} | ||
|
||
this[remainingSize] -= delta; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters