Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Commit

Permalink
Update async storage and remove compose dev dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
maier49 committed Feb 27, 2017
1 parent a60045f commit 9e78043
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 112 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"@dojo/shim": "2.0.0-beta.8"
},
"devDependencies": {
"@dojo/compose": "2.0.0-beta.21",
"@dojo/interfaces": "2.0.0-alpha.11",
"@dojo/loader": "2.0.0-beta.9",
"@types/chai": "~3.4.0",
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/storage/InMemoryStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function getStorageAndDfd(test: any, option = {}) {
}

registerSuite({
name: 'createInMemoryStorage',
name: 'InMemoryStorage',
'identify': {
'Should identify by idProperty if exists.'(this: any) {
const storage = new InMemoryStorage<ItemType & { custId: string }>({
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/store/ObservableStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as assert from 'intern/chai!assert';
import ObservableStore, { ObservableStoreInterface, StoreDelta, ItemUpdate } from '../../../src/store/ObservableStore';
import { ItemType, createData, createUpdates, patches, patchedItems } from '../support/createData';
import { CrudOptions, UpdateResults } from '../../../src/interfaces';
import createAsyncStorage from '../support/AsyncStorage';
import AsyncStorage from '../support/AsyncStorage';
import InMemoryStorage from '../../../src/storage/InMemoryStorage';
import Set from '@dojo/shim/Set';
import Promise from '@dojo/shim/Promise';
Expand All @@ -21,14 +21,14 @@ function getStoreAndDfd(test: any) {
}
function getStoreWithAsyncStorage(test: any, asyncOptions?: {}, useAsync = true) {
const dfd = useAsync ? test.async(1000) : null;
const asyncStorage = createAsyncStorage(asyncOptions);
const asyncStorage = new AsyncStorage(asyncOptions);
const observableStore = new ObservableStore({ storage: asyncStorage });

return { dfd, observableStore, asyncStorage };
}

registerSuite({
name: 'observableStoreMixin',
name: 'ObservableStore',

'with basic store': (function() {
const ids = createData().map(function(item) {
Expand Down
34 changes: 17 additions & 17 deletions tests/unit/store/QueryableStore/querying.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { createData, ItemType, patches, createUpdates } from '../../support/crea
import createFilter from '../../../../src/query/createFilter';
import createRange from '../../../../src/query/createStoreRange';
import createSort from '../../../../src/query/createSort';
import createAsyncStorage from '../../support/AsyncStorage';
import AsyncStorage from '../../support/AsyncStorage';
import QueryStore from '../../../../src/store/QueryableStore';
import { QueryResult } from '../../../../src/store/QueryResult';
import { diff } from '../../../../src/patch/Patch';
import Promise from '@dojo/shim/Promise';
import { CrudOptions } from '../../../../src/interfaces';

function getStoreAndDfd(test: any, useAsync = true) {
const dfd = useAsync ? test.async(1000) : null;
Expand All @@ -23,14 +24,14 @@ function getStoreAndDfd(test: any, useAsync = true) {
}
function getStoreWithAsyncStorage(test: any, asyncOptions?: {}, useAsync = true) {
const dfd = useAsync ? test.async(1000) : null;
const asyncStorage = createAsyncStorage(asyncOptions);
const asyncStorage = new AsyncStorage(asyncOptions);
const queryStore = new QueryStore({ storage: asyncStorage });

return { dfd, queryStore, asyncStorage };
}

registerSuite({
name: 'Query-Transform Mixin - Querying',
name: 'Queryable Store - Querying',
'single query': function(this: any) {
const { queryStore } = getStoreAndDfd(this, false);

Expand Down Expand Up @@ -624,7 +625,7 @@ registerSuite({

'async storage': {
'filtered subcollection fetch should not return items when it is done before add.'(this: any) {
const { queryStore: store } = getStoreWithAsyncStorage(this, { put: 20, fetch: 10 }, false);
const { queryStore: store } = getStoreWithAsyncStorage(this, { put: 20, fetch: 1 }, false);
const subcollection = store.filter(createFilter<ItemType>().greaterThanOrEqualTo('value', 2));

store.add(createData());
Expand All @@ -633,7 +634,7 @@ registerSuite({
});
},
'should complete initial add before subsequent operations'(this: any) {
const asyncStorage = createAsyncStorage();
const asyncStorage = new AsyncStorage();
const store = new QueryStore({
storage: asyncStorage,
data: createData()
Expand All @@ -646,18 +647,17 @@ registerSuite({
'failed initial add should not prevent subsequent operations'(this: any) {
let fail = true;
const stub = sinon.stub(console, 'error');
const asyncStorage = createAsyncStorage
.around('add', function(add: () => Promise<ItemType>) {
return function(this: any) {
if (fail) {
fail = false;
return Promise.reject(Error('error'));
}
else {
return add.apply(this, arguments);
}
};
})();
const asyncStorage = new (class extends AsyncStorage<any> {
add(items: any[], options?: CrudOptions): any {
if (fail) {
fail = false;
return Promise.reject(Error('error'));
}
else {
return super.add(items, options);
}
}
})();
const data = createData();
const store = new QueryStore({
storage: asyncStorage,
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/store/QueryableStore/tracking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ registerSuite(function() {
}

return {
name: 'Query-Transform Mixin - Tracking',
name: 'Queryable Store - Tracking',
beforeEach: function() {
trackableQueryStore = new QueryStore({
data: createData()
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/store/QueryableStore/transforming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function getStoreAndDfd(test: any, useAsync = true) {
}

registerSuite({
name: 'Query-Transform Mixin - Transform',
name: 'Queryable Store - Transform',
'single transformations'(this: any) {
const { queryStore } = getStoreAndDfd(this, false);

Expand Down
39 changes: 19 additions & 20 deletions tests/unit/store/StoreBase.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as registerSuite from 'intern!object';
import * as assert from 'intern/chai!assert';
import * as sinon from 'sinon';
import StoreBase from '../../../src/store/StoreBase';
import Map from '@dojo/shim/Map';
import Set from '@dojo/shim/Set';
import Promise from '@dojo/shim/Promise';
import Set from '@dojo/shim/Set';
import StoreBase from '../../../src/store/StoreBase';
import createRange from '../../../src/query/createStoreRange';
import createFilter from '../../../src/query/createFilter';
import JsonPointer from '../../../src/patch/JsonPointer';
Expand All @@ -14,8 +14,8 @@ import createOperation, { OperationType } from '../../../src/patch/createOperati
import CompoundQuery from '../../../src/query/CompoundQuery';
import InMemoryStorage from '../../../src/storage/InMemoryStorage';
import { createData, ItemType, createUpdates, patches, patchedItems } from '../support/createData';
import createAsyncStorage from '../support/AsyncStorage';
import { StoreOperation } from '../../../src/interfaces';
import AsyncStorage from '../support/AsyncStorage';
import { StoreOperation, CrudOptions } from '../../../src/interfaces';

function getStoreAndDfd(test: any, data = createData(), useAsync = true) {
const dfd = useAsync ? test.async(1000) : null;
Expand All @@ -27,7 +27,7 @@ function getStoreAndDfd(test: any, data = createData(), useAsync = true) {

function getStoreWithAsyncStorage(test: any, asyncOptions?: {}, useAsync = true) {
const dfd = useAsync ? test.async(1000) : null;
const asyncStorage = createAsyncStorage(asyncOptions);
const asyncStorage = new AsyncStorage(asyncOptions);
const store = new StoreBase({ storage: asyncStorage });

return { dfd, store, asyncStorage };
Expand All @@ -38,7 +38,7 @@ const ids = createData().map(function(item) {
});

registerSuite({
name: 'createStore',
name: 'StoreBase',

'initialize store'(this: any) {
const { store, data } = getStoreAndDfd(this, createData(), false);
Expand Down Expand Up @@ -499,7 +499,7 @@ registerSuite({

'async storage': {
'async operation should not be done immediately.'(this: any) {
const{ store } = getStoreWithAsyncStorage(this, { put: 50}, false);
const { store } = getStoreWithAsyncStorage(this, { put: 50}, false);

const start = Date.now();
return store.add(createData()).then(function() {
Expand All @@ -508,7 +508,7 @@ registerSuite({
});
},
'should complete initial add before subsequent operations'(this: any) {
const asyncStorage = createAsyncStorage();
const asyncStorage = new AsyncStorage();
const store = new StoreBase({
storage: asyncStorage,
data: createData()
Expand All @@ -521,18 +521,17 @@ registerSuite({
'failed initial add should not prevent subsequent operations'(this: any) {
let fail = true;
const stub = sinon.stub(console, 'error');
const asyncStorage = createAsyncStorage
.around('add', function(add: () => Promise<ItemType>) {
return function(this: any) {
if (fail) {
fail = false;
return Promise.reject(Error('error'));
}
else {
return add.apply(this, arguments);
}
};
})();
const asyncStorage = new (class extends AsyncStorage<any> {
add(items: any[], options?: CrudOptions): any {
if (fail) {
fail = false;
return Promise.reject(Error('error'));
}
else {
return super.add(items, options);
}
}
})();
const data = createData();
const store = new StoreBase({
storage: asyncStorage,
Expand Down
121 changes: 53 additions & 68 deletions tests/unit/support/AsyncStorage.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,65 @@
import InMemoryStorage from '../../../src/storage/InMemoryStorage';
import Map from '@dojo/shim/Map';
import Promise from '@dojo/shim/Promise';
import WeakMap from '@dojo/shim/WeakMap';
import { delay } from '@dojo/core/async/timing';
import compose from '@dojo/compose/compose';

const instanceStateMap = new WeakMap<{}, any>();
import { Query, FetchResult, CrudOptions } from '../../../src/interfaces';
import Patch from '../../../src/patch/Patch';

function getRandomInt(max = 100) {
return Math.floor(Math.random() * max);
}

function delayOperation(operation: Function, operationName: string) {
return function(this: any, ...args: any[]) {
const state = instanceStateMap.get(this);
const milliseconds = state[operationName] || getRandomInt();
return delay(milliseconds)(operation.bind(this, ...args));
};
}
export default class AsyncStorage<T> extends InMemoryStorage<T> {
timing: { [ index: string ]: number | undefined };

constructor(options?: any) {
super(options);
this.timing = options || {};
}

get(ids: string[]): Promise<T[]> {
return delay(this.timing['get'] || getRandomInt())(() => super.get(ids));
}

createId() {
return delay(this.timing['createId'] || getRandomInt())(() => super.createId());
}

const createAsyncStorage = compose(InMemoryStorage).mixin({
initialize(instance: any, options: any = {}) {
instance.data = [];
instance.index = new Map<string, number>();
instance.idProperty = options.idProperty;
instance.idFunction = options.idFunction;
instance.returnsPromise = Promise.resolve();
put(items: T[], options?: CrudOptions) {
return delay(this.timing['put'] || getRandomInt())(() => super.put(items, options));
}
}).mixin({
initialize(instance, asyncOptions = {}) {
instanceStateMap.set(instance, asyncOptions);
},
aspectAdvice: {
around: {
createId(createId: Function) {
return delayOperation(createId, 'createId');
},
fetch(fetch: Function) {
const delayed = delayOperation(fetch, 'fetch');
return function(this: any, ...args: any[]) {
let resolveTotalLength: (totalLength: number) => void;
let rejectTotalLength: (error: any) => void;
const totalLength = new Promise((resolve, reject) => {
resolveTotalLength = resolve;
rejectTotalLength = reject;
});
const returnPromise = delayed.bind(this, ...args)();
returnPromise.totalLength = returnPromise.dataLength = totalLength;
delayed.bind(this)().then(
(fullResults: any) => {
resolveTotalLength(fullResults.length);
},
(error: any) => {
rejectTotalLength(error);
}
);
return returnPromise;
};
},
get(get: Function) {
return delayOperation(get, 'get');
},
add(add: Function) {
return delayOperation(add, 'put');
},
put(put: Function) {
return delayOperation(put, 'put');
},
delete(_delete: Function) {
return delayOperation(_delete, 'delete');
},
patch(patch: Function) {
return delayOperation(patch, 'patch');
}
}

add(items: T[], options?: CrudOptions) {
return delay(this.timing['add'] || getRandomInt())(() => super.add(items, options));
}
});
export default createAsyncStorage;

delete(ids: string[]) {
return delay(this.timing['delete'] || getRandomInt())(() => super.delete(ids));
}

patch(updates: { id: string; patch: Patch<T, T> }[]) {
return delay(this.timing['patch'] || getRandomInt())(() => super.patch(updates));
}

fetch(query?: Query<T>) {
let totalLengthResolve: () => void;
let totalLengthReject: () => void;
let fetchResultResolve: () => void;
let fetchResultReject: () => void;
const totalLengthPromise = new Promise((resolve, reject) => {
totalLengthResolve = resolve;
totalLengthReject = reject;
});
const fetchResult: FetchResult<T> = <any> new Promise((resolve, reject) => {
fetchResultResolve = resolve;
fetchResultReject = reject;
});
fetchResult.totalLength = fetchResult.dataLength = totalLengthPromise;
setTimeout(() => {
const result = super.fetch();
result.then(fetchResultResolve, fetchResultReject);
result.totalLength.then(totalLengthResolve, totalLengthReject);
}, this.timing['fetch'] || getRandomInt());

return fetchResult;
}
}

0 comments on commit 9e78043

Please sign in to comment.