diff --git a/src/app/memoryLocalStore.js b/src/app/memoryLocalStore.js new file mode 100644 index 0000000..54c8c29 --- /dev/null +++ b/src/app/memoryLocalStore.js @@ -0,0 +1,29 @@ +// @flow + +import {LocalStore} from "./localStore"; + +/* + * A completely in-memory `LocalStore` implementation that matches the + * happy path of browsers' `localStorage`: storage is always enabled and + * functioning, and there is no storage limit. + */ +export default class MemoryLocalStore implements LocalStore { + _data: Map; + + constructor(): void { + this._data = new Map(); + } + + get(key: string, whenUnavailable: T): T { + const raw = this._data.get(key); + return raw == null ? whenUnavailable : JSON.parse(raw); + } + + set(key: string, data: mixed): void { + this._data.set(key, JSON.stringify(data)); + } + + del(key: string): void { + this._data.delete(key); + } +} diff --git a/src/app/memoryLocalStore.test.js b/src/app/memoryLocalStore.test.js new file mode 100644 index 0000000..c228d92 --- /dev/null +++ b/src/app/memoryLocalStore.test.js @@ -0,0 +1,36 @@ +// @flow + +import MemoryLocalStore from "./memoryLocalStore"; + +describe("src/app/memoryLocalStore", () => { + it("stores simple values", () => { + const ls = new MemoryLocalStore(); + ls.set("one", 1); + expect(ls.get("one")).toBe(1); + }); + + it("stores complex values", () => { + const ls = new MemoryLocalStore(); + ls.set("stuff", [{a: ["one"]}, {b: ["two"]}]); + expect(ls.get("stuff")).toEqual([{a: ["one"]}, {b: ["two"]}]); + }); + + it("stores null", () => { + const ls = new MemoryLocalStore(); + ls.set("one", null); + expect(ls.get("one")).toBe(null); + }); + + it("overwrites values", () => { + const ls = new MemoryLocalStore(); + ls.set("questions", 5); + ls.set("questions", 3); + expect(ls.get("questions")).toBe(3); + }); + + it("provides `whenUnavailable` for absent values", () => { + const ls = new MemoryLocalStore(); + const expected = Symbol(); + expect(ls.get("wat", expected)).toBe(expected); + }); +});