From fd36780129db92894fd4ae3d826579ea535c3317 Mon Sep 17 00:00:00 2001 From: Krzysztof Borowy Date: Sat, 22 Jun 2019 12:41:29 +0200 Subject: [PATCH 1/5] feat: initial implementation --- .prettierrc | 2 +- core/src/AsyncStorage.ts | 143 +++++++++++++++++++++++++++++++++++++-- core/src/defaults.ts | 62 +++++++++++++++++ core/src/index.ts | 18 ++++- core/types/index.d.ts | 113 +++++++++++++++++++++++++++++-- tsconfig.json | 7 +- 6 files changed, 329 insertions(+), 16 deletions(-) create mode 100644 core/src/defaults.ts diff --git a/.prettierrc b/.prettierrc index e58d2642..22b5d665 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,5 +4,5 @@ "trailingComma": "all", "bracketSpacing": false, "jsxBracketSameLine": true, - "parser": "flow" + "parser": "typescript" } diff --git a/core/src/AsyncStorage.ts b/core/src/AsyncStorage.ts index 957ee140..0115f02b 100644 --- a/core/src/AsyncStorage.ts +++ b/core/src/AsyncStorage.ts @@ -1,12 +1,143 @@ -class AsyncStorage implements IAsyncStorage { - backend: IStorageBackend; +import {simpleErrorHandler, simpleLogger} from './defaults'; - constructor(storageBackend: IStorageBackend) { - this.backend = storageBackend; +class AsyncStorage> { + private readonly _backend: STR; + private readonly _config: FactoryOptions; + private readonly log: (action: LoggerAction) => void; + private readonly error: (e: Error | string) => void; + + constructor(storageBackend: STR, asOptions: FactoryOptions) { + this._backend = storageBackend; + this._config = asOptions; + + this.log = + typeof this._config.logger === 'function' + ? this._config.logger + : simpleLogger; + + this.error = + typeof this._config.errorHandler === 'function' + ? this._config.errorHandler + : simpleErrorHandler; + } + + async get(key: string, opts?: StorageOptions): Promise { + let value = null; + try { + this.log({ + action: 'read-single', + key: key, + }); + value = await this._backend.getSingle(key, opts); + } catch (e) { + this.error(e); + } + + return value; + } + + async set(key: string, value: VAL, opts?: StorageOptions): Promise { + try { + this.log({ + action: 'save-single', + key, + value, + }); + await this._backend.setSingle(key, value, opts); + } catch (e) { + this.error(e); + } + } + + async getMultiple( + keys: Array, + opts?: StorageOptions, + ): Promise> { + let values: Array = []; + + try { + this.log({ + action: 'read-many', + key: keys, + }); + values = await this._backend.getMany(keys, opts); + } catch (e) { + this.error(e); + } + + return values; + } + + async setMultiple( + keyValues: Array<{[key: string]: VAL}>, + opts?: StorageOptions, + ): Promise { + try { + this.log({ + action: 'save-many', + value: keyValues, + }); + await this._backend.setMany(keyValues, opts); + } catch (e) { + this.error(e); + } + } + + async remove(key: string, opts?: StorageOptions): Promise { + try { + this.log({ + action: 'delete-single', + key, + }); + await this._backend.removeSingle(key, opts); + } catch (e) { + this.error(e); + } + } + + async removeMultiple( + keys: Array, + opts?: StorageOptions, + ): Promise { + try { + this.log({ + action: 'delete-many', + key: keys, + }); + await this._backend.removeMany(keys, opts); + } catch (e) { + this.error(e); + } + } + + async getKeys(opts?: StorageOptions): Promise> { + let keys: Array = []; + + try { + this.log({ + action: 'keys', + }); + keys = await this._backend.getKeys(opts); + } catch (e) { + this.error(e); + } + + return keys; + } + + async clearStorage(opts?: StorageOptions): Promise { + try { + this.log({ + action: 'drop', + }); + await this._backend.dropStorage(opts); + } catch (e) { + this.error(e); + } } - set(): Promise { - return Promise.resolve(undefined); + instance(): STR { + return this._backend; } } diff --git a/core/src/defaults.ts b/core/src/defaults.ts new file mode 100644 index 00000000..d4472720 --- /dev/null +++ b/core/src/defaults.ts @@ -0,0 +1,62 @@ +/** + * By default, logging and error handling are done only in dev + */ +export const factoryOptions: FactoryOptions = { + logger: __DEV__, + errorHandler: __DEV__, +}; + +export function simpleErrorHandler(e: Error | string) { + if (__DEV__) { + let errorMessage = e instanceof Error ? e.message : e; + console.error(errorMessage); + } +} + +export function simpleLogger(logInfo: LoggerAction) { + if (__DEV__) { + const log = (message: string) => { + console.log(`[AsyncStorage] ${message}`); + }; + + const {action, key, value} = logInfo; + + switch (action) { + case 'read-single': { + log(`Reading a value for a key: ${key}`); + break; + } + case 'save-single': { + log(`Saving a value: ${value} for a key: ${key}`); + break; + } + case 'delete-single': { + log(`Removing value at a key: ${key}`); + break; + } + case 'read-many': { + log(`Reading values for keys: ${key}`); + break; + } + case 'save-many': { + log(`Saving values ${value} for keys: ${key}`); + break; + } + case 'delete-many': { + log(`Removing multiple values for keys: ${key}`); + break; + } + case 'drop': { + log('Dropping whole database'); + break; + } + case 'keys': { + log('Retrieving keys'); + break; + } + default: { + log(`Unknown action: ${action}`); + } + } + } +} diff --git a/core/src/index.ts b/core/src/index.ts index a713c0a2..af8b7f22 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -1 +1,17 @@ -export {default as AsyncStorage} from './AsyncStorage'; +import AsyncStorage from './AsyncStorage'; +import {factoryOptions} from './defaults'; + +class AsyncStorageFactory { + constructor() { + throw new Error('Do not instantiate AsyncStorageFactory!'); + } + + static create( + storage: STR, + opts: FactoryOptions = factoryOptions, + ): AsyncStorage> { + return new AsyncStorage(storage, opts); + } +} + +export default AsyncStorageFactory; diff --git a/core/types/index.d.ts b/core/types/index.d.ts index 90e3b839..9ed5bd94 100644 --- a/core/types/index.d.ts +++ b/core/types/index.d.ts @@ -1,9 +1,110 @@ -interface IStorageBackend { - getSingle(): Promise; - //todo +/** + * + * Core Async Storage API + * + */ +declare class AsyncStorage< + STR extends IStorageBackend, + VAL = StorageModelType +> { + get(key: string, opts?: StorageOptions): Promise; + + set(key: string, value: VAL, opts?: StorageOptions): Promise; + + getMultiple( + keys: Array, + opts?: StorageOptions, + ): Promise>; + + setMultiple( + keyValues: Array<{[key: string]: VAL}>, + opts?: StorageOptions, + ): Promise; + + remove(key: string, opts?: StorageOptions): Promise; + + removeMultiple(keys: Array, opts?: StorageOptions): Promise; + + getKeys(opts?: StorageOptions): Promise>; + + clearStorage(opts?: StorageOptions): Promise; + + instance(): STR; } -interface IAsyncStorage { - set(): Promise; - // todo +/** + * + * Storage Backend API + * + */ +declare interface IStorageBackend { + getSingle(key: string, opts?: StorageOptions): Promise; + + setSingle(key: string, value: VAL, opts?: StorageOptions): Promise; + + getMany( + keys: Array, + opts?: StorageOptions, + ): Promise>; + + setMany( + values: Array<{[key: string]: VAL}>, + opts?: StorageOptions, + ): Promise; + + removeSingle(key: string, opts?: StorageOptions): Promise; + + removeMany(keys: Array, opts?: StorageOptions): Promise; + + getKeys(opts?: StorageOptions): Promise>; + + dropStorage(opts?: StorageOptions): Promise; } + +/** + * + * Factory types + * + */ +declare class AsyncStorageFactory { + static create( + storage: STR, + opts: FactoryOptions, + ): AsyncStorage>; +} + +// infers Model type from Storage instance +type StorageModelType = T extends IStorageBackend ? V : any; + +// Options provided to the factory +declare type FactoryOptions = { + logger: ((action: LoggerAction) => void) | boolean | void; + errorHandler: ((error: Error | string) => void) | boolean | void; +}; + +/** + * + * Global types + * + */ +declare type LoggerAction = { + action: + | 'read-single' + | 'save-single' + | 'delete-single' + | 'read-many' + | 'save-many' + | 'delete-many' + | 'drop' + | 'keys'; + + value?: any; + key?: string | Array; +}; + +declare const __DEV__: boolean; +declare const console: any; + +declare type StorageOptions = { + [key: string]: any; +}; diff --git a/tsconfig.json b/tsconfig.json index 1f2dcae3..d92a82de 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,8 +16,11 @@ "esModuleInterop": true }, "include": [ - "core/src", + "core/src/", "core/types/", - "storages/**/src" + "core/__tests__/", + "storages/**/src/", + "storages/**/types/", + "storages/**/__tests__/" ] } From 967bdc92bdd9d285d62d3e43f9b175c2840360c8 Mon Sep 17 00:00:00 2001 From: Krzysztof Borowy Date: Wed, 26 Jun 2019 08:01:02 +0200 Subject: [PATCH 2/5] fix: correct logger/error funcs --- core/src/AsyncStorage.ts | 26 ++++++++---- core/src/defaults.ts | 90 ++++++++++++++++++++-------------------- 2 files changed, 62 insertions(+), 54 deletions(-) diff --git a/core/src/AsyncStorage.ts b/core/src/AsyncStorage.ts index 0115f02b..7aa12fde 100644 --- a/core/src/AsyncStorage.ts +++ b/core/src/AsyncStorage.ts @@ -1,4 +1,4 @@ -import {simpleErrorHandler, simpleLogger} from './defaults'; +import {simpleErrorHandler, simpleLogger, noop} from './defaults'; class AsyncStorage> { private readonly _backend: STR; @@ -10,15 +10,23 @@ class AsyncStorage> { this._backend = storageBackend; this._config = asOptions; - this.log = - typeof this._config.logger === 'function' - ? this._config.logger - : simpleLogger; + // off by default + this.log = noop; + this.error = noop; - this.error = - typeof this._config.errorHandler === 'function' - ? this._config.errorHandler - : simpleErrorHandler; + if (this._config.logger) { + this.log = + typeof this._config.logger === 'function' + ? this._config.logger + : simpleLogger; + } + + if (this._config.errorHandler) { + this.error = + typeof this._config.errorHandler === 'function' + ? this._config.errorHandler + : simpleErrorHandler; + } } async get(key: string, opts?: StorageOptions): Promise { diff --git a/core/src/defaults.ts b/core/src/defaults.ts index d4472720..b2487b53 100644 --- a/core/src/defaults.ts +++ b/core/src/defaults.ts @@ -7,56 +7,56 @@ export const factoryOptions: FactoryOptions = { }; export function simpleErrorHandler(e: Error | string) { - if (__DEV__) { - let errorMessage = e instanceof Error ? e.message : e; - console.error(errorMessage); - } + let errorMessage = e instanceof Error ? e.message : e; + console.error(errorMessage); } export function simpleLogger(logInfo: LoggerAction) { - if (__DEV__) { - const log = (message: string) => { - console.log(`[AsyncStorage] ${message}`); - }; + const log = (message: string) => { + console.log(`[AsyncStorage] ${message}`); + }; - const {action, key, value} = logInfo; + const {action, key, value} = logInfo; - switch (action) { - case 'read-single': { - log(`Reading a value for a key: ${key}`); - break; - } - case 'save-single': { - log(`Saving a value: ${value} for a key: ${key}`); - break; - } - case 'delete-single': { - log(`Removing value at a key: ${key}`); - break; - } - case 'read-many': { - log(`Reading values for keys: ${key}`); - break; - } - case 'save-many': { - log(`Saving values ${value} for keys: ${key}`); - break; - } - case 'delete-many': { - log(`Removing multiple values for keys: ${key}`); - break; - } - case 'drop': { - log('Dropping whole database'); - break; - } - case 'keys': { - log('Retrieving keys'); - break; - } - default: { - log(`Unknown action: ${action}`); - } + switch (action) { + case 'read-single': { + log(`Reading a value for a key: ${key}`); + break; + } + case 'save-single': { + log(`Saving a value: ${value} for a key: ${key}`); + break; + } + case 'delete-single': { + log(`Removing value at a key: ${key}`); + break; + } + case 'read-many': { + log(`Reading values for keys: ${key}`); + break; + } + case 'save-many': { + log(`Saving values ${value} for keys: ${key}`); + break; + } + case 'delete-many': { + log(`Removing multiple values for keys: ${key}`); + break; + } + case 'drop': { + log('Dropping whole database'); + break; + } + case 'keys': { + log('Retrieving keys'); + break; + } + default: { + log(`Unknown action: ${action}`); } } } + +export function noop() { + // noop +} From 24cae3ce92aa718bf6dfbbfb9bc665d45a3d4f2d Mon Sep 17 00:00:00 2001 From: Krzysztof Borowy Date: Sat, 29 Jun 2019 13:20:13 +0200 Subject: [PATCH 3/5] tests: add unit tests --- babel.config.js | 12 +- core/__tests__/AsyncStorage.test.ts | 121 ++++++++++++ core/__tests__/core.test.ts | 84 +++++++++ core/src/AsyncStorage.ts | 20 +- core/types/index.d.ts | 2 +- jest.config.js | 19 ++ package.json | 14 +- tsconfig.json | 1 + yarn.lock | 281 +++++++++++++++++++++++++--- 9 files changed, 513 insertions(+), 41 deletions(-) create mode 100644 core/__tests__/AsyncStorage.test.ts create mode 100644 core/__tests__/core.test.ts create mode 100644 jest.config.js diff --git a/babel.config.js b/babel.config.js index a240f65e..cd11c25f 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,5 +1,15 @@ module.exports = { - presets: ['@babel/preset-typescript'], + presets: [ + '@babel/preset-typescript', + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + ], plugins: [ '@babel/proposal-class-properties', '@babel/proposal-object-rest-spread', diff --git a/core/__tests__/AsyncStorage.test.ts b/core/__tests__/AsyncStorage.test.ts new file mode 100644 index 00000000..3e446b50 --- /dev/null +++ b/core/__tests__/AsyncStorage.test.ts @@ -0,0 +1,121 @@ +import AsyncStorage from '../src/AsyncStorage'; + +class StorageMock implements IStorageBackend { + getSingle = jest.fn(); + setSingle = jest.fn(); + getMany = jest.fn(); + setMany = jest.fn(); + removeSingle = jest.fn(); + removeMany = jest.fn(); + getKeys = jest.fn(); + dropStorage = jest.fn(); +} + +describe('AsyncStorage', () => { + const mockedStorage = new StorageMock(); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('main API', () => { + it('handles basic set/read/remove calls', async () => { + const as = new AsyncStorage(mockedStorage, { + logger: false, + errorHandler: false, + }); + + const key = 'myKey'; + const value = { + name: 'Jerry', + }; + + // get + await as.get(key); + expect(mockedStorage.getSingle).toBeCalledWith(key, null); + + //set + await as.set(key, value); + expect(mockedStorage.setSingle).toBeCalledWith(key, value, null); + + // remove + await as.remove(key); + expect(mockedStorage.removeSingle).toBeCalledWith(key, null); + }); + + it('handles basic multi set/read/remove calls', async () => { + const keys = ['key1', 'key2', 'key3']; + const keyValues = [{key1: 'value1'}, {key2: 'value2'}, {key3: 'value3'}]; + + const as = new AsyncStorage(mockedStorage, { + logger: false, + errorHandler: false, + }); + + // set + await as.setMultiple(keyValues); + expect(mockedStorage.setMany).toBeCalledWith(keyValues, null); + + // get + await as.getMultiple(keys); + expect(mockedStorage.getMany).toBeCalledWith(keys, null); + + // remove + await as.removeMultiple(keys); + expect(mockedStorage.removeMany).toBeCalledWith(keys, null); + }); + + it('handles getKeys/clearStorage/instance calls', async () => { + const asyncStorage = new AsyncStorage(mockedStorage, { + logger: false, + errorHandler: false, + }); + + // instance + expect(asyncStorage.instance()).toBe(mockedStorage); + + //drop storage + await asyncStorage.clearStorage(); + expect(mockedStorage.dropStorage).toBeCalledTimes(1); + + // getKeys + mockedStorage.getKeys.mockImplementationOnce(() => ['key1', 'key2']); + const keys = await asyncStorage.getKeys(); + + expect(keys).toEqual(['key1', 'key2']); + }); + + describe('utils', () => { + it('uses logger when provided', async () => { + const loggerFunc = jest.fn(); + + const as = new AsyncStorage(mockedStorage, { + logger: loggerFunc, + errorHandler: false, + }); + + await as.get('key'); + expect(loggerFunc).toBeCalledTimes(1); + }); + + it('uses error handler when provided', async () => { + const errorHandler = jest.fn(); + + const error = new Error('Fatal!'); + mockedStorage.getSingle.mockImplementationOnce(async () => { + throw error; + }); + + const as = new AsyncStorage(mockedStorage, { + errorHandler, + logger: false, + }); + + await as.get('key'); + + expect(errorHandler).toBeCalledTimes(1); + expect(errorHandler.mock.calls[0][0]).toBe(error); + }); + }); + }); +}); diff --git a/core/__tests__/core.test.ts b/core/__tests__/core.test.ts new file mode 100644 index 00000000..57bf2656 --- /dev/null +++ b/core/__tests__/core.test.ts @@ -0,0 +1,84 @@ +import Factory from '../src/'; +import {simpleLogger, simpleErrorHandler} from '../src/defaults'; + +describe('AsyncStorageFactory', () => { + it('Throws when tried to instantiate', () => { + expect(() => new Factory()).toThrow(); + }); +}); + +describe('SimpleLogger', () => { + beforeAll(() => { + jest.spyOn(console, 'log').mockImplementation(); + }); + + beforeEach(() => { + console.log.mockReset(); + }); + + afterAll(() => { + console.log.mockRestore(); + }); + + it('logs basic info about action', () => { + const actionInfo: LoggerAction = { + action: 'save-single', + key: 'MyKey', + value: 'MyValue', + }; + + simpleLogger(actionInfo); + + expect(console.log).toBeCalledTimes(1); + + const callArgs = console.log.mock.calls[0][0]; + expect(callArgs).toContain('[AsyncStorage]'); + expect(callArgs).toContain(actionInfo.key); + expect(callArgs).toContain(actionInfo.value); + }); + + it('handles unknown action by logging it', () => { + const actionInfo: LoggerAction = { + // @ts-ignore need to handle unknown + action: 'unknown-action', + }; + + simpleLogger(actionInfo); + + expect(console.log).toBeCalledTimes(1); + + const callArgs = console.log.mock.calls; + expect(callArgs[0][0]).toContain('unknown-action'); + }); +}); + +describe('SimpleErrorHandler', () => { + beforeAll(() => { + jest.spyOn(console, 'error').mockImplementation(); + }); + + beforeEach(() => { + console.error.mockReset(); + }); + + afterAll(() => { + console.error.mockRestore(); + }); + it('logs error when it is a string', () => { + const errorMessage = 'Fatal!'; + + simpleErrorHandler(errorMessage); + + expect(console.error).toBeCalledTimes(1); + expect(console.error.mock.calls[0][0]).toEqual(errorMessage); + }); + + it('logs error when it is an Error', () => { + const error = new Error('Fatal!'); + + simpleErrorHandler(error); + + expect(console.error).toBeCalledTimes(1); + expect(console.error.mock.calls[0][0]).toEqual(error.message); + }); +}); diff --git a/core/src/AsyncStorage.ts b/core/src/AsyncStorage.ts index 7aa12fde..ad5b5097 100644 --- a/core/src/AsyncStorage.ts +++ b/core/src/AsyncStorage.ts @@ -29,7 +29,7 @@ class AsyncStorage> { } } - async get(key: string, opts?: StorageOptions): Promise { + async get(key: string, opts: StorageOptions = null): Promise { let value = null; try { this.log({ @@ -44,7 +44,11 @@ class AsyncStorage> { return value; } - async set(key: string, value: VAL, opts?: StorageOptions): Promise { + async set( + key: string, + value: VAL, + opts: StorageOptions = null, + ): Promise { try { this.log({ action: 'save-single', @@ -59,7 +63,7 @@ class AsyncStorage> { async getMultiple( keys: Array, - opts?: StorageOptions, + opts: StorageOptions = null, ): Promise> { let values: Array = []; @@ -78,7 +82,7 @@ class AsyncStorage> { async setMultiple( keyValues: Array<{[key: string]: VAL}>, - opts?: StorageOptions, + opts: StorageOptions = null, ): Promise { try { this.log({ @@ -91,7 +95,7 @@ class AsyncStorage> { } } - async remove(key: string, opts?: StorageOptions): Promise { + async remove(key: string, opts: StorageOptions = null): Promise { try { this.log({ action: 'delete-single', @@ -105,7 +109,7 @@ class AsyncStorage> { async removeMultiple( keys: Array, - opts?: StorageOptions, + opts: StorageOptions = null, ): Promise { try { this.log({ @@ -118,7 +122,7 @@ class AsyncStorage> { } } - async getKeys(opts?: StorageOptions): Promise> { + async getKeys(opts: StorageOptions = null): Promise> { let keys: Array = []; try { @@ -133,7 +137,7 @@ class AsyncStorage> { return keys; } - async clearStorage(opts?: StorageOptions): Promise { + async clearStorage(opts: StorageOptions = null): Promise { try { this.log({ action: 'drop', diff --git a/core/types/index.d.ts b/core/types/index.d.ts index 9ed5bd94..678c8fe5 100644 --- a/core/types/index.d.ts +++ b/core/types/index.d.ts @@ -107,4 +107,4 @@ declare const console: any; declare type StorageOptions = { [key: string]: any; -}; +} | null; diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..6ab028f9 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,19 @@ +const commonSettings = { + transform: { + '^.+\\.tsx?$': 'babel-jest', + }, + globals: { + __DEV__: true, + }, +}; + +module.exports = { + projects: [ + { + ...commonSettings, + displayName: 'core', + roots: ['/core', '/storages/**/'], + testMatch: ['/core/__tests__/*{.,-}test.ts'], + }, + ], +}; diff --git a/package.json b/package.json index 4c346f33..f308d647 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "author": "Krzysztof Borowy ", "contributors": [], "homepage": "https://github.com/react-native-community/react-native-async-storage#readme", - "repository": { "type": "git", "url": "https://github.com/react-native-community/react-native-async-storage.git" @@ -24,22 +23,26 @@ "scripts": { "build": "lerna run build", "clean": "lerna run clean", - "test": "yarn test:lint && yarn test:types", + "test": "yarn test:lint && yarn test:unit && yarn test:types", "test:lint": "eslint core/src/** storages/**/src", - "test:types": "tsc --noEmit --declaration false -emitDeclarationOnly false" + "test:types": "tsc --noEmit --declaration false -emitDeclarationOnly false", + "test:unit": "jest" }, "devDependencies": { "@babel/cli": "7.4.4", "@babel/core": "7.4.5", "@babel/plugin-proposal-class-properties": "7.4.4", "@babel/plugin-proposal-object-rest-spread": "7.4.4", + "@babel/preset-env": "7.4.5", "@babel/preset-typescript": "7.3.3", "@react-native-community/eslint-config": "0.0.5", + "@types/jest": "24.0.15", + "babel-jest": "24.8.0", "eslint": "5.16.0", + "jest": "24.8.0", "lerna": "3.15.0", "typescript": "3.5.2" }, - "license": "MIT", "keywords": [ "react-native", "react native", @@ -47,5 +50,6 @@ "asyncstorage", "async-storage", "react native storage" - ] + ], + "license": "MIT" } diff --git a/tsconfig.json b/tsconfig.json index d92a82de..8f00bc25 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ "esModuleInterop": true }, "include": [ + "@types/jest", "core/src/", "core/types/", "core/__tests__/", diff --git a/yarn.lock b/yarn.lock index 02386bd5..2e0f3a02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -155,7 +155,7 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-module-transforms@^7.4.4": +"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8" integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w== @@ -262,6 +262,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" + integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-proposal-class-properties@7.4.4", "@babel/plugin-proposal-class-properties@^7.0.0": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz#93a6486eed86d53452ab9bab35e368e9461198ce" @@ -278,6 +287,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-export-default-from" "^7.2.0" +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz#41c360d59481d88e0ce3a3f837df10121a769b39" @@ -286,7 +303,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@7.4.4", "@babel/plugin-proposal-object-rest-spread@^7.0.0": +"@babel/plugin-proposal-object-rest-spread@7.4.4", "@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz#1ef173fcf24b3e2df92a678f027673b55e7e3005" integrity sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g== @@ -294,7 +311,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": +"@babel/plugin-proposal-optional-catch-binding@^7.0.0", "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== @@ -310,6 +327,22 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-chaining" "^7.2.0" +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" + integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-class-properties@^7.0.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.2.0.tgz#23b3b7b9bcdabd73672a9149f728cd3be6214812" @@ -338,6 +371,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" @@ -380,14 +420,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-arrow-functions@^7.0.0": +"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-async-to-generator@^7.0.0": +"@babel/plugin-transform-async-to-generator@^7.0.0", "@babel/plugin-transform-async-to-generator@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz#a3f1d01f2f21cadab20b33a82133116f14fb5894" integrity sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA== @@ -396,14 +436,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" -"@babel/plugin-transform-block-scoped-functions@^7.0.0": +"@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.0.0": +"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz#c13279fabf6b916661531841a23c4b7dae29646d" integrity sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA== @@ -411,7 +451,7 @@ "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.11" -"@babel/plugin-transform-classes@^7.0.0": +"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz#0ce4094cdafd709721076d3b9c38ad31ca715eb6" integrity sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw== @@ -425,21 +465,37 @@ "@babel/helper-split-export-declaration" "^7.4.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.0.0": +"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@^7.0.0": +"@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz#9d964717829cc9e4b601fc82a26a71a4d8faf20f" integrity sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-exponentiation-operator@^7.0.0": +"@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" + integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" + +"@babel/plugin-transform-duplicate-keys@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3" + integrity sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.0.0", "@babel/plugin-transform-exponentiation-operator@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== @@ -455,14 +511,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-flow" "^7.2.0" -"@babel/plugin-transform-for-of@^7.0.0": +"@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-function-name@^7.0.0": +"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== @@ -470,21 +526,29 @@ "@babel/helper-function-name" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-literals@^7.0.0": +"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-member-expression-literals@^7.0.0": +"@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-commonjs@^7.0.0": +"@babel/plugin-transform-modules-amd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6" + integrity sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz#0bef4713d30f1d78c2e59b3d6db40e60192cac1e" integrity sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw== @@ -493,6 +557,36 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" +"@babel/plugin-transform-modules-systemjs@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz#dc83c5665b07d6c2a7b224c00ac63659ea36a405" + integrity sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ== + dependencies: + "@babel/helper-hoist-variables" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-umd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" + integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" + integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== + dependencies: + regexp-tree "^0.1.6" + +"@babel/plugin-transform-new-target@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" + integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-object-assign@^7.0.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.2.0.tgz#6fdeea42be17040f119e38e23ea0f49f31968bde" @@ -500,7 +594,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-object-super@^7.0.0": +"@babel/plugin-transform-object-super@^7.0.0", "@babel/plugin-transform-object-super@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg== @@ -508,7 +602,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.1.0" -"@babel/plugin-transform-parameters@^7.0.0": +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== @@ -517,7 +611,7 @@ "@babel/helper-get-function-arity" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-property-literals@^7.0.0": +"@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== @@ -548,13 +642,20 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.2.0" -"@babel/plugin-transform-regenerator@^7.0.0": +"@babel/plugin-transform-regenerator@^7.0.0", "@babel/plugin-transform-regenerator@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== dependencies: regenerator-transform "^0.14.0" +"@babel/plugin-transform-reserved-words@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" + integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-runtime@^7.0.0": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.4.tgz#a50f5d16e9c3a4ac18a1a9f9803c107c380bce08" @@ -565,21 +666,21 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.0.0": +"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-spread@^7.0.0": +"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.2.0": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-sticky-regex@^7.0.0": +"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== @@ -587,7 +688,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.0.0": +"@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== @@ -595,6 +696,13 @@ "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-typescript@^7.0.0", "@babel/plugin-transform-typescript@^7.3.2": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.5.tgz#ab3351ba35307b79981993536c93ff8be050ba28" @@ -603,7 +711,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-typescript" "^7.2.0" -"@babel/plugin-transform-unicode-regex@^7.0.0": +"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== @@ -612,6 +720,60 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/preset-env@7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" + integrity sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.4.4" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.4.4" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.4.4" + "@babel/plugin-transform-classes" "^7.4.4" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/plugin-transform-duplicate-keys" "^7.2.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.4.4" + "@babel/plugin-transform-function-name" "^7.4.4" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-member-expression-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.2.0" + "@babel/plugin-transform-modules-commonjs" "^7.4.4" + "@babel/plugin-transform-modules-systemjs" "^7.4.4" + "@babel/plugin-transform-modules-umd" "^7.2.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.5" + "@babel/plugin-transform-new-target" "^7.4.4" + "@babel/plugin-transform-object-super" "^7.2.0" + "@babel/plugin-transform-parameters" "^7.4.4" + "@babel/plugin-transform-property-literals" "^7.2.0" + "@babel/plugin-transform-regenerator" "^7.4.5" + "@babel/plugin-transform-reserved-words" "^7.2.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.4.4" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.4.4" + "@babel/types" "^7.4.4" + browserslist "^4.6.0" + core-js-compat "^3.1.1" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + "@babel/preset-typescript@7.3.3": version "7.3.3" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz#88669911053fa16b2b276ea2ede2ca603b3f307a" @@ -1717,6 +1879,18 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/jest-diff@*": + version "20.0.1" + resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" + integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA== + +"@types/jest@24.0.15": + version "24.0.15" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.15.tgz#6c42d5af7fe3b44ffff7cc65de7bf741e8fa427f" + integrity sha512-MU1HIvWUme74stAoc3mgAi+aMlgKOudgEvQDIm1v4RkrDudBh1T+NFp5sftpBAdXdx1J0PbdpJ+M2EsSOi1djA== + dependencies: + "@types/jest-diff" "*" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -2354,6 +2528,15 @@ browser-resolve@^1.11.3: dependencies: resolve "1.1.7" +browserslist@^4.6.0, browserslist@^4.6.2: + version "4.6.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.3.tgz#0530cbc6ab0c1f3fc8c819c72377ba55cf647f05" + integrity sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ== + dependencies: + caniuse-lite "^1.0.30000975" + electron-to-chromium "^1.3.164" + node-releases "^1.1.23" + bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -2492,6 +2675,11 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +caniuse-lite@^1.0.30000975: + version "1.0.30000978" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000978.tgz#1e3346c27fc46bce9ac1ccd77863153a263dde56" + integrity sha512-H6gK6kxUzG6oAwg/Jal279z8pHw0BzrpZfwo/CA9FFm/vA0l8IhDfkZtepyJNE2Y4V6Dp3P3ubz6czby1/Mgsw== + capture-exit@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" @@ -2881,6 +3069,20 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +core-js-compat@^3.1.1: + version "3.1.4" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.1.4.tgz#e4d0c40fbd01e65b1d457980fe4112d4358a7408" + integrity sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg== + dependencies: + browserslist "^4.6.2" + core-js-pure "3.1.4" + semver "^6.1.1" + +core-js-pure@3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.4.tgz#5fa17dc77002a169a3566cc48dc774d2e13e3769" + integrity sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA== + core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" @@ -3233,6 +3435,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +electron-to-chromium@^1.3.164: + version "1.3.175" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.175.tgz#a269716af5e549f9f3989ae38ba484881dcb3702" + integrity sha512-cQ0o7phcPA0EYkN4juZy/rq4XVxl/1ywQnytDT9hZTC0cHfaOBqWK2XlWp9Mk8xRGntgnmxlHTOux4HLb2ZNnA== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4509,7 +4716,7 @@ inquirer@^6.2.0, inquirer@^6.2.2: strip-ansi "^5.1.0" through "^2.3.6" -invariant@^2.2.4: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -5280,6 +5487,11 @@ jest@24.8.0: import-local "^2.0.0" jest-cli "^24.8.0" +js-levenshtein@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -6392,6 +6604,13 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" +node-releases@^1.1.23: + version "1.1.23" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.23.tgz#de7409f72de044a2fa59c097f436ba89c39997f0" + integrity sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w== + dependencies: + semver "^5.3.0" + "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -7553,6 +7772,11 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp-tree@^0.1.6: + version "0.1.10" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" + integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -7850,6 +8074,11 @@ semver@^6.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b" integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ== +semver@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.2.tgz#079960381376a3db62eb2edc8a3bfb10c7cfe318" + integrity sha512-z4PqiCpomGtWj8633oeAdXm1Kn1W++3T8epkZYnwiVgIYIJ0QHszhInYSJTYxebByQH7KVCEAn8R9duzZW2PhQ== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" From 495709356e0b459b580917e28e824f92132ad102 Mon Sep 17 00:00:00 2001 From: Krzysztof Borowy Date: Sat, 29 Jun 2019 13:28:22 +0200 Subject: [PATCH 4/5] chore: temp disable lint for storages, ci unit tests --- .circleci/config.yml | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index efb5d5b6..a6c48883 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -137,6 +137,14 @@ jobs: name: Type check command: yarn test:types + "Test: unit": + <<: *js_defaults + steps: + - *addWorkspace + - run: + name: Unit tests run + command: yarn test:unit + "Test: iOS e2e": <<: *macos_defaults steps: @@ -291,3 +299,6 @@ workflows: - "Test: types": requires: - "Setup environment" + - "Test: unit": + requires: + - "Setup environment" diff --git a/package.json b/package.json index f308d647..806b81a3 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build": "lerna run build", "clean": "lerna run clean", "test": "yarn test:lint && yarn test:unit && yarn test:types", - "test:lint": "eslint core/src/** storages/**/src", + "test:lint": "eslint core/src/**", "test:types": "tsc --noEmit --declaration false -emitDeclarationOnly false", "test:unit": "jest" }, From d6773586b8e4361468868bcee3406412c543eb25 Mon Sep 17 00:00:00 2001 From: Krzysztof Borowy Date: Tue, 2 Jul 2019 17:30:41 +0200 Subject: [PATCH 5/5] tests: improve tests --- babel.config.js | 2 +- core/__tests__/AsyncStorage.test.ts | 201 +++++++++++++++++----------- core/__tests__/core.test.ts | 16 ++- core/src/AsyncStorage.ts | 2 + core/src/index.ts | 4 +- jest.config.js | 3 - 6 files changed, 135 insertions(+), 93 deletions(-) diff --git a/babel.config.js b/babel.config.js index cd11c25f..b73eb51d 100644 --- a/babel.config.js +++ b/babel.config.js @@ -5,7 +5,7 @@ module.exports = { '@babel/preset-env', { targets: { - node: 'current', + node: 8, }, }, ], diff --git a/core/__tests__/AsyncStorage.test.ts b/core/__tests__/AsyncStorage.test.ts index 3e446b50..72af17b5 100644 --- a/core/__tests__/AsyncStorage.test.ts +++ b/core/__tests__/AsyncStorage.test.ts @@ -19,103 +19,142 @@ describe('AsyncStorage', () => { }); describe('main API', () => { - it('handles basic set/read/remove calls', async () => { - const as = new AsyncStorage(mockedStorage, { - logger: false, - errorHandler: false, - }); - - const key = 'myKey'; - const value = { - name: 'Jerry', - }; + it.each(['get', 'set', 'remove'])( + 'handles single %s api call', + async (methodName: string) => { + const as = new AsyncStorage(mockedStorage, { + logger: false, + errorHandler: false, + }); - // get - await as.get(key); - expect(mockedStorage.getSingle).toBeCalledWith(key, null); + const key = 'myKey'; + const value = { + name: 'Jerry', + }; + + switch (methodName) { + case 'get': { + await as.get(key); + expect(mockedStorage.getSingle).toBeCalledWith(key, null); + break; + } + + case 'set': { + await as.set(key, value); + expect(mockedStorage.setSingle).toBeCalledWith(key, value, null); + break; + } + + case 'remove': { + await as.remove(key); + expect(mockedStorage.removeSingle).toBeCalledWith(key, null); + break; + } + } + }, + ); + + it.each(['set', 'read', 'remove'])( + 'handles basic multi %s api call', + async (methodName: string) => { + const keys = ['key1', 'key2', 'key3']; + const keyValues = [ + {key1: 'value1'}, + {key2: 'value2'}, + {key3: 'value3'}, + ]; - //set - await as.set(key, value); - expect(mockedStorage.setSingle).toBeCalledWith(key, value, null); + const as = new AsyncStorage(mockedStorage, { + logger: false, + errorHandler: false, + }); - // remove - await as.remove(key); - expect(mockedStorage.removeSingle).toBeCalledWith(key, null); - }); + switch (methodName) { + case 'get': { + await as.getMultiple(keys); + expect(mockedStorage.getMany).toBeCalledWith(keys, null); + break; + } + + case 'set': { + await as.setMultiple(keyValues); + expect(mockedStorage.setMany).toBeCalledWith(keyValues, null); + break; + } + + case 'remove': { + await as.removeMultiple(keys); + expect(mockedStorage.removeMany).toBeCalledWith(keys, null); + break; + } + } + }, + ); + + it.each(['instance', 'getKeys', 'clearStorage'])( + 'handles %s api call', + async (methodName: string) => { + const asyncStorage = new AsyncStorage(mockedStorage, { + logger: false, + errorHandler: false, + }); - it('handles basic multi set/read/remove calls', async () => { - const keys = ['key1', 'key2', 'key3']; - const keyValues = [{key1: 'value1'}, {key2: 'value2'}, {key3: 'value3'}]; + switch (methodName) { + case 'instance': { + expect(asyncStorage.instance()).toBe(mockedStorage); + break; + } + + case 'getKeys': { + mockedStorage.getKeys.mockImplementationOnce(() => [ + 'key1', + 'key2', + ]); + const keys = await asyncStorage.getKeys(); + expect(keys).toEqual(['key1', 'key2']); + break; + } + + case 'dropStorage': { + await asyncStorage.clearStorage(); + expect(mockedStorage.dropStorage).toBeCalledTimes(1); + break; + } + } + }, + ); + }); + describe('utils', () => { + it('uses logger when provided', async () => { + const loggerFunc = jest.fn(); const as = new AsyncStorage(mockedStorage, { - logger: false, - errorHandler: false, - }); - - // set - await as.setMultiple(keyValues); - expect(mockedStorage.setMany).toBeCalledWith(keyValues, null); - - // get - await as.getMultiple(keys); - expect(mockedStorage.getMany).toBeCalledWith(keys, null); - - // remove - await as.removeMultiple(keys); - expect(mockedStorage.removeMany).toBeCalledWith(keys, null); - }); - - it('handles getKeys/clearStorage/instance calls', async () => { - const asyncStorage = new AsyncStorage(mockedStorage, { - logger: false, + logger: loggerFunc, errorHandler: false, }); - // instance - expect(asyncStorage.instance()).toBe(mockedStorage); - - //drop storage - await asyncStorage.clearStorage(); - expect(mockedStorage.dropStorage).toBeCalledTimes(1); - - // getKeys - mockedStorage.getKeys.mockImplementationOnce(() => ['key1', 'key2']); - const keys = await asyncStorage.getKeys(); - - expect(keys).toEqual(['key1', 'key2']); + await as.get('key'); + expect(loggerFunc).toBeCalledTimes(1); + expect(loggerFunc).toBeCalledWith({action: 'read-single', key: 'key'}); }); - describe('utils', () => { - it('uses logger when provided', async () => { - const loggerFunc = jest.fn(); - - const as = new AsyncStorage(mockedStorage, { - logger: loggerFunc, - errorHandler: false, - }); + it('uses error handler when provided', async () => { + const errorHandler = jest.fn(); - await as.get('key'); - expect(loggerFunc).toBeCalledTimes(1); + const error = new Error('Fatal!'); + mockedStorage.getSingle.mockImplementationOnce(async () => { + throw error; }); - it('uses error handler when provided', async () => { - const errorHandler = jest.fn(); - - const error = new Error('Fatal!'); - mockedStorage.getSingle.mockImplementationOnce(async () => { - throw error; - }); - - const as = new AsyncStorage(mockedStorage, { - errorHandler, - logger: false, - }); + const as = new AsyncStorage(mockedStorage, { + errorHandler, + logger: false, + }); - await as.get('key'); + await as.get('key'); - expect(errorHandler).toBeCalledTimes(1); - expect(errorHandler.mock.calls[0][0]).toBe(error); - }); + expect(errorHandler).toBeCalledTimes(1); + expect(errorHandler).toBeCalledWith(error); }); }); }); diff --git a/core/__tests__/core.test.ts b/core/__tests__/core.test.ts index 57bf2656..e6d5a571 100644 --- a/core/__tests__/core.test.ts +++ b/core/__tests__/core.test.ts @@ -3,7 +3,9 @@ import {simpleLogger, simpleErrorHandler} from '../src/defaults'; describe('AsyncStorageFactory', () => { it('Throws when tried to instantiate', () => { - expect(() => new Factory()).toThrow(); + expect(() => new Factory()).toThrow( + "[AsyncStorage] AsyncStorageFactory must not be instantiated.\nInstead, use static functions, like 'create' to get AsyncStorage instance.", + ); }); }); @@ -40,15 +42,15 @@ describe('SimpleLogger', () => { it('handles unknown action by logging it', () => { const actionInfo: LoggerAction = { // @ts-ignore need to handle unknown - action: 'unknown-action', + action: 'my-action', }; simpleLogger(actionInfo); expect(console.log).toBeCalledTimes(1); - - const callArgs = console.log.mock.calls; - expect(callArgs[0][0]).toContain('unknown-action'); + expect(console.log).toBeCalledWith( + '[AsyncStorage] Unknown action: my-action', + ); }); }); @@ -70,7 +72,7 @@ describe('SimpleErrorHandler', () => { simpleErrorHandler(errorMessage); expect(console.error).toBeCalledTimes(1); - expect(console.error.mock.calls[0][0]).toEqual(errorMessage); + expect(console.error).toBeCalledWith(errorMessage); }); it('logs error when it is an Error', () => { @@ -79,6 +81,6 @@ describe('SimpleErrorHandler', () => { simpleErrorHandler(error); expect(console.error).toBeCalledTimes(1); - expect(console.error.mock.calls[0][0]).toEqual(error.message); + expect(console.error).toBeCalledWith('Fatal!'); }); }); diff --git a/core/src/AsyncStorage.ts b/core/src/AsyncStorage.ts index ad5b5097..3c1d7a7e 100644 --- a/core/src/AsyncStorage.ts +++ b/core/src/AsyncStorage.ts @@ -148,6 +148,8 @@ class AsyncStorage> { } } + // todo: think how we could provide additional functions through AS, without returning the instance + // some kind of extension-like functionality instance(): STR { return this._backend; } diff --git a/core/src/index.ts b/core/src/index.ts index af8b7f22..4850e315 100644 --- a/core/src/index.ts +++ b/core/src/index.ts @@ -3,7 +3,9 @@ import {factoryOptions} from './defaults'; class AsyncStorageFactory { constructor() { - throw new Error('Do not instantiate AsyncStorageFactory!'); + throw new Error( + "[AsyncStorage] AsyncStorageFactory must not be instantiated.\nInstead, use static functions, like 'create' to get AsyncStorage instance.", + ); } static create( diff --git a/jest.config.js b/jest.config.js index 6ab028f9..87a83acb 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,4 @@ const commonSettings = { - transform: { - '^.+\\.tsx?$': 'babel-jest', - }, globals: { __DEV__: true, },