Full PromisifiedStorage + Simplifications

This commit is contained in:
Chi Vinh Le
2018-09-06 23:53:29 +02:00
parent 3a1b043eb7
commit e132087682
41 changed files with 642 additions and 238 deletions
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should call clear 1`] = `"{\\"a\\":\\"0\\",\\"b\\":\\"1\\",\\"d\\":\\"3\\"}"`;
+2
View File
@@ -1,2 +1,4 @@
export { default as buildURL } from "./buildURL";
export { default as ensureEndSlash } from "./ensureEndSlash";
export { default as startsWith } from "./startsWith";
export { default as prefixStorage } from "./prefixStorage";
@@ -0,0 +1,79 @@
import sinon from "sinon";
import { createInMemoryStorage } from "../testUtils";
import prefixStorage from "./prefixStorage";
it("should get nth key", () => {
const storage = createInMemoryStorage({
a: "0",
b: "1",
"talk:c": "2",
d: "3",
"talk:e": "4",
});
const prefixed = prefixStorage(storage, "talk:");
expect(prefixed.key(0)).toBe("talk:c");
expect(prefixed.key(1)).toBe("talk:e");
expect(prefixed.key(2)).toBeNull();
});
it("should call clear", () => {
const storage = createInMemoryStorage({
a: "0",
b: "1",
"talk:c": "2",
d: "3",
"talk:e": "4",
});
const prefixed = prefixStorage(storage, "talk:");
prefixed.clear();
expect(storage.toString()).toMatchSnapshot();
});
it("should call length", () => {
const storage = createInMemoryStorage({
a: "0",
b: "1",
"talk:c": "2",
d: "3",
"talk:e": "4",
});
const prefixed = prefixStorage(storage, "talk:");
expect(prefixed.length).toBe(2);
});
it("should prefix setItem", () => {
const storage = {
setItem: sinon.mock().withArgs("talk:key", "value"),
};
const prefixed = prefixStorage(storage as any, "talk:");
prefixed.setItem("key", "value");
storage.setItem.verify();
});
it("should prefix removeItem", () => {
const storage = {
removeItem: sinon.mock().withArgs("talk:key"),
};
const prefixed = prefixStorage(storage as any, "talk:");
prefixed.removeItem("key");
storage.removeItem.verify();
});
it("should prefix getItem", () => {
const ret = "value";
const storage = {
getItem: sinon
.mock()
.withArgs("talk:key")
.returns(ret),
};
const prefixed = prefixStorage(storage as any, "talk:");
expect(prefixed.getItem("key")).toBe(ret);
(storage.getItem as any).verify();
});
@@ -0,0 +1,66 @@
import startsWith from "./startsWith";
/**
* PrefixedStorage decorates a Storage and prefixes keys in
* getItem, setItem and removeItem with given prefix.
*/
class PrefixedStorage implements Storage {
private storage: Storage;
private prefix: string;
constructor(storage: Storage, prefix: string) {
this.storage = storage;
this.prefix = prefix;
}
get length() {
let count = 0;
for (let i = 0; i < this.storage.length; i++) {
if (startsWith(this.storage.key(i)!, this.prefix)) {
count++;
}
}
return count;
}
public clear() {
const toBeDeleted = [];
for (let i = 0; i < this.storage.length; i++) {
const key = this.storage.key(i)!;
if (startsWith(key, this.prefix)) {
toBeDeleted.push(key);
}
}
toBeDeleted.forEach(key => this.storage.removeItem(key));
}
public key(n: number) {
let count = 0;
for (let i = 0; i < this.storage.length; i++) {
const key = this.storage.key(i)!;
if (startsWith(key, this.prefix)) {
if (count === n) {
return key;
}
count++;
}
}
return null;
}
public getItem(key: string) {
return this.storage.getItem(`${this.prefix}${key}`);
}
public setItem(key: string, value: string) {
return this.storage.setItem(`${this.prefix}${key}`, value);
}
public removeItem(key: string) {
return this.storage.removeItem(`${this.prefix}${key}`);
}
}
export default function prefixStorage(storage: Storage, prefix: string) {
return new PrefixedStorage(storage, prefix);
}
@@ -0,0 +1,7 @@
import startsWith from "./startsWith";
it("should work correctly", () => {
const str1 = "Saturday night plans";
expect(startsWith(str1, "Sat")).toBe(true);
expect(startsWith(str1, "Sat", 3)).toBe(false);
});
@@ -0,0 +1,4 @@
/** A substitute for string.startsWith */
export default function startsWith(str: string, search: string, pos?: number) {
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
}