mock-async-storage
Version:
Its a mock of react-native AsyncStorage for jest tests
140 lines (111 loc) • 3.13 kB
text/typescript
import merge from "deepmerge";
export type Entry<K, V> = [K, V | null];
export type Entries<K, V> = Array<Entry<K, V>>;
export type ErrBack<V> = (err: Error | null, val?: V | null) => void;
export type ArrErrBack<V> = (err: Array<Error> | null, val?: V) => void;
const isStringified = (str: string): boolean => {
try {
JSON.parse(str);
return true;
} catch (e) {
return false;
}
};
class AsyncDict<K, V> {
store: Map<K, V | null>;
size(): number {
return this.store.size;
}
getStore(): Map<K, V | null> {
return new Map(this.store);
}
constructor() {
this.store = new Map();
}
async getItem(k: K, cb?: ErrBack<V>): Promise<V | null> {
const val = this.store.get(k) || null;
if (cb) cb(null, val);
return val;
}
async setItem(k: K, v: V, cb?: ErrBack<V>): Promise<void> {
this.store.set(k, v);
if (cb) cb(null);
}
async removeItem(k: K, cb?: ErrBack<V>): Promise<void> {
this.store.delete(k);
if (cb) cb(null);
}
async clear(cb?: ErrBack<V>): Promise<void> {
this.store.clear();
if (cb) cb(null);
}
async getAllKeys(cb?: ErrBack<Array<K>>): Promise<Array<K>> {
const keys: Array<K> = Array.from(this.store.keys());
if (cb) cb(null, keys);
return keys;
}
async multiGet(
keys: Array<K>,
cb?: ErrBack<Entries<K, V>>
): Promise<Entries<K, V>> {
const requested: Entries<K, V> = keys.map((k) => [
k,
this.store.get(k) || null,
]);
if (cb) cb(null, requested);
return requested;
}
async multiSet(entries: Entries<K, V>, cb?: ErrBack<V>): Promise<void> {
for (const [key, value] of entries) {
this.store.set(key, value);
}
if (cb) cb(null);
}
async multiRemove(keys: Array<K>, cb?: ErrBack<V>): Promise<void> {
for (const key of keys) {
this.store.delete(key);
}
if (cb) cb(null);
}
}
class MockAsyncStorage extends AsyncDict<string, string> {
async mergeItem(
key: string,
value: string,
cb?: ErrBack<string>
): Promise<void> {
const item: string | null = await this.getItem(key);
if (!item) throw new Error(`No item with ${key} key`);
if (!isStringified(item)) throw new Error(`Invalid item with ${key} key`);
if (!isStringified(value))
throw new Error(`Invalid value to merge with ${key}`);
const itemObj: unknown = JSON.parse(item);
const valueObj: unknown = JSON.parse(value);
const merged: unknown = merge(itemObj, valueObj);
await this.setItem(key, JSON.stringify(merged));
if (cb) cb(null);
}
async multiMerge(
entries: Entries<string, string>,
cb?: ArrErrBack<string>
): Promise<void> {
const errors: Array<Error> = [];
for (const [key, value] of entries) {
try {
if (value) {
await this.mergeItem(key, value);
}
} catch (err) {
errors.push(err as Error);
}
}
if (errors.length) {
if (cb) cb(errors);
return Promise.reject(errors);
}
if (cb) cb(null);
return Promise.resolve();
}
flushGetRequests() {}
}
export default MockAsyncStorage;