adding Paris.clearApiCallCache method to enable users to clear the apiCalls cache

* adding clearApiCallCache method to enable users to force clearing the apiCalls cache

* upgraded to jest 24 + added caching mechanism tests

* version bump
This commit is contained in:
Or Adler 2019-05-01 16:56:58 +03:00 коммит произвёл GitHub
Родитель 8e9213b8fd
Коммит 9635d65738
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 70 добавлений и 14 удалений

Просмотреть файл

@ -1,5 +1,6 @@
import {ApiCallBackendConfigInterface} from "../../config/api-call-backend-config.interface";
import {HttpOptions, RequestMethod} from "../../data_access/http.service";
import { ParisConfig } from "../../config/paris-config";
export class ApiCallModel<TResult = any, TInput = any>{
config:ApiCallConfig<TResult, TInput>
@ -12,7 +13,7 @@ export interface ApiCallType<TResult = any, TInput = any>{
export interface ApiCallConfig<TResult = any, TInput = any> extends ApiCallBackendConfigInterface<TResult> {
name:string,
parseQuery?:(input:TInput) => HttpOptions,
parseQuery?:(input:TInput, config?: ParisConfig) => HttpOptions,
parse?:(data?:any, input?:TInput) => TResult,
method?:RequestMethod,
responseType?: 'json' | 'blob' | 'text',

Просмотреть файл

@ -101,7 +101,7 @@ export interface EntityBackendConfig<TEntity extends ModelBase, TRawData = any,
* `parseDataQuery` receives that DataQuery object and allows to modify it, so Paris can send to the API what it expects.
* @param {DataQuery} dataQuery
*/
parseDataQuery?:(dataQuery:DataQuery) => { [index:string]:any },
parseDataQuery?:(dataQuery:DataQuery, config?: ParisConfig) => { [index:string]:any },
/**
* For query results, Paris accepts either an array of items or an object. That object may contain properties such as 'count', 'next' and 'previous'.

Просмотреть файл

@ -164,7 +164,7 @@ export class Paris<TConfigData = any> {
let httpOptions: HttpOptions = ((input !== undefined) && (input !== null))
? apiCallType.config.parseQuery
? apiCallType.config.parseQuery(input)
? apiCallType.config.parseQuery(input, this.config)
: apiCallType.config.method !== "GET" ? {data: input} : {params: input}
: null;
if (!httpOptions){
@ -260,6 +260,25 @@ export class Paris<TConfigData = any> {
return apiCall$;
}
/**
* Clears all or specific ApiCallType caches
* @param {ApiCallType<TResult, TInput>} apiCallType Optional ApiCallType class or array of classes. if omitted, all ApiCallType caches will be cleared. otherwise, only the caches of the specified ApiCallType(s) will be cleared.
* @returns {void}
*/
clearApiCallCache(apiCallType?:ApiCallType | Array<ApiCallType>): void {
if (!apiCallType) {
this.apiCallsCache.clear();
return;
}
const apiCallTypes = apiCallType instanceof Array ? apiCallType : [apiCallType];
apiCallTypes.forEach(apiCallType => {
const apiCallTypeCache = this.getApiCallCache(apiCallType);
if (apiCallTypeCache) {
apiCallTypeCache.clear();
}
})
}
private getApiCallCache<TResult, TInput>(apiCallType:ApiCallType<TResult, TInput>, addIfNotExists:boolean = false):DataCache<TResult>{
let apiCallCache:DataCache<TResult> = this.apiCallsCache.get(apiCallType);
if (!apiCallCache && addIfNotExists){
@ -334,7 +353,7 @@ export class Paris<TConfigData = any> {
* @returns {Observable<DataSet<TEntity extends ModelBase>>}
*/
callQuery<TEntity extends ModelBase>(entityConstructor:DataEntityType<TEntity>, backendConfig:EntityBackendConfig<TEntity>, query?: DataQuery, dataOptions: DataOptions = defaultDataOptions):Observable<DataSet<TEntity>>{
let httpOptions:HttpOptions = backendConfig.parseDataQuery ? { params: backendConfig.parseDataQuery(query) } : queryToHttpOptions(query);
let httpOptions:HttpOptions = backendConfig.parseDataQuery ? { params: backendConfig.parseDataQuery(query, this.config) } : queryToHttpOptions(query);
if (!httpOptions){
httpOptions = {};
}

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@microsoft/paris",
"version": "1.5.1",
"version": "1.6.0",
"description": "Library for the implementation of Domain Driven Design with TypeScript + RxJS",
"repository": {
"type": "git",
@ -48,7 +48,7 @@
"@types/gulp-protractor": "^1.0.30",
"@types/gulp-sass": "^0.0.30",
"@types/gulp-util": "^3.0.29",
"@types/jest": "^23.3.1",
"@types/jest": "^24.0.0",
"@types/json-stringify-safe": "^5.0.0",
"@types/lodash-es": "4.17.1",
"@types/node": "^8.0.25",
@ -63,7 +63,7 @@
"gulp-typescript": "^3.1.3",
"husky": "^1.0.0-rc.13",
"intl": "^1.2.5",
"jest": "^23.6.0",
"jest": "^24.7.1",
"json-stringify-safe": "^5.0.1",
"lodash-es": "4.17.10",
"merge2": "^1.0.2",
@ -77,7 +77,7 @@
"rxjs": "^6.0.0",
"standard-version": "^3.0.0",
"systemjs": ">=0.20.12",
"ts-jest": "^23.1.3",
"ts-jest": "^24.0.0",
"ts-node": "^7.0.0",
"typedoc": "^0.11.1",
"typescript": "^2.7.2",
@ -98,8 +98,10 @@
"/node_modules/",
"/dist/"
],
"setupTestFrameworkScriptFile": "<rootDir>/jest-setup.ts",
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|js)$",
"setupFilesAfterEnv": [
"<rootDir>/jest-setup.ts"
],
"testRegex": "\\.(test|spec)\\.(ts|js)$",
"moduleFileExtensions": [
"ts",
"js",

Просмотреть файл

@ -1,4 +1,4 @@
import { Observable, of } from 'rxjs';
import { Observable, of, forkJoin } from 'rxjs';
import { DataEntityType } from '../lib/api/entity/data-entity.base';
import { RelationshipRepository } from '../lib/api/repository/relationship-repository';
import { Repository } from '../lib/api/repository/repository';
@ -218,7 +218,7 @@ describe('Paris main', () => {
describe('apiCall', () => {
let jestGetApiCallCacheSpy: jest.SpyInstance<Observable<Paris>>;
let jestMakeApiCallSpy: jest.SpyInstance<Observable<Paris>>;
let jestMakeApiCallSpy: jest.SpyInstance<Observable<any>>;
beforeEach(() => {
paris = new Paris();
@ -228,8 +228,42 @@ describe('Paris main', () => {
jestMakeApiCallSpy = jest.spyOn(paris, 'makeApiCall' as any);
});
it.skip('should add data to cache if configured to', () => {
// TODO: we need to subscribe in order for this to work
describe('cache behaviour', () => {
function callTwoDifferentApiCalls() {
return forkJoin(paris.apiCall(CreateTodoListApiCall), paris.apiCall(UpdateTodoApiCall));
}
const testObj = {};
beforeEach(done => {
jestMakeApiCallSpy.mockReturnValue(of(testObj));
callTwoDifferentApiCalls().subscribe(_ => done());
});
it('should retreive data from cache', done => {
callTwoDifferentApiCalls().subscribe(val => {
expect(val[0]).toBe(testObj);
expect(jestMakeApiCallSpy).toHaveBeenCalledTimes(2);//expecting no additional calls to 'makeApiCall'
done();
})
});
it('should clear a specific ApiCall cache', done => {
paris.clearApiCallCache(CreateTodoListApiCall);
callTwoDifferentApiCalls().subscribe(_ => {
expect(jestMakeApiCallSpy).toHaveBeenCalledTimes(3);//expecting exactly one additional call to 'makeApiCall'
done();
})
});
it('should clear all ApiCalls cache', done => {
paris.clearApiCallCache();
callTwoDifferentApiCalls().subscribe(_ => {
expect(jestMakeApiCallSpy).toHaveBeenCalledTimes(4);//expecting exactly two additional calls to 'makeApiCall'
done();
})
});
});
it('should get data from cache if available and configured to', () => {