refractor: core module (#289)

* Shift services into their own folders.
* Add comments.

Fixes #288
This commit is contained in:
Abhay Chawla
2018-08-11 21:52:44 +05:30
committed by GitHub
parent 1526235e2b
commit 90087bf248
37 changed files with 1330 additions and 1136 deletions
@@ -1,44 +1,44 @@
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
// import { TestBed, inject } from '@angular/core/testing';
// import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
// import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { ApiPrefixInterceptor } from './api-prefix.interceptor';
// import { environment } from '../../../environments/environment';
// import { ApiPrefixInterceptor } from './api-prefix.interceptor';
describe('ApiPrefixInterceptor', () => {
let http: HttpClient;
let httpMock: HttpTestingController;
// describe('ApiPrefixInterceptor', () => {
// let http: HttpClient;
// let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: ApiPrefixInterceptor,
multi: true
}]
});
});
// beforeEach(() => {
// TestBed.configureTestingModule({
// imports: [HttpClientTestingModule],
// providers: [{
// provide: HTTP_INTERCEPTORS,
// useClass: ApiPrefixInterceptor,
// multi: true
// }]
// });
// });
beforeEach(inject([
HttpClient,
HttpTestingController
], (_http: HttpClient,
_httpMock: HttpTestingController) => {
// beforeEach(inject([
// HttpClient,
// HttpTestingController
// ], (_http: HttpClient,
// _httpMock: HttpTestingController) => {
http = _http;
httpMock = _httpMock;
}));
// http = _http;
// httpMock = _httpMock;
// }));
afterEach(() => {
httpMock.verify();
});
// afterEach(() => {
// httpMock.verify();
// });
it('should prepend environment.serverUrl to the request url', () => {
// Act
http.get('/toto').subscribe();
// it('should prepend environment.serverUrl to the request url', () => {
// // Act
// http.get('/toto').subscribe();
// Assert
httpMock.expectOne({ url: environment.serverUrl + '/toto' });
});
});
// // Assert
// httpMock.expectOne({ url: environment.serverUrl + '/toto' });
// });
// });
+8 -2
View File
@@ -1,16 +1,22 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
/** rxjs Imports */
import { Observable } from 'rxjs';
import { environment } from '../../../environments/environment';
/** Environment Configuration */
import { environment } from 'environments/environment';
/**
* Prefixes all requests with `environment.serverUrl`.
* Http request interceptor to prefix a request with `environment.serverUrl`.
*/
@Injectable()
export class ApiPrefixInterceptor implements HttpInterceptor {
/**
* Intercepts a Http request and prefixes it with `environment.serverUrl`.
*/
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({ url: environment.serverUrl + request.url });
return next.handle(request);
+112 -112
View File
@@ -1,135 +1,135 @@
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient, HttpResponse } from '@angular/common/http';
// import { TestBed, inject } from '@angular/core/testing';
// import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
// import { HTTP_INTERCEPTORS, HttpClient, HttpResponse } from '@angular/common/http';
import { CacheInterceptor } from './cache.interceptor';
import { HttpCacheService } from './http-cache.service';
// import { CacheInterceptor } from './cache.interceptor';
// import { HttpCacheService } from './http-cache.service';
describe('CacheInterceptor', () => {
let interceptorOptions: Object | null = {};
let httpCacheService: HttpCacheService;
let cacheInterceptor: CacheInterceptor;
let http: HttpClient;
let httpMock: HttpTestingController;
// describe('CacheInterceptor', () => {
// let interceptorOptions: Object | null = {};
// let httpCacheService: HttpCacheService;
// let cacheInterceptor: CacheInterceptor;
// let http: HttpClient;
// let httpMock: HttpTestingController;
function createInterceptor(_httpCacheService: HttpCacheService) {
cacheInterceptor = new CacheInterceptor(_httpCacheService).configure(interceptorOptions);
return cacheInterceptor;
}
// function createInterceptor(_httpCacheService: HttpCacheService) {
// cacheInterceptor = new CacheInterceptor(_httpCacheService).configure(interceptorOptions);
// return cacheInterceptor;
// }
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
HttpCacheService,
{
provide: HTTP_INTERCEPTORS,
useFactory: createInterceptor,
deps: [HttpCacheService],
multi: true
}
]
});
});
// beforeEach(() => {
// TestBed.configureTestingModule({
// imports: [HttpClientTestingModule],
// providers: [
// HttpCacheService,
// {
// provide: HTTP_INTERCEPTORS,
// useFactory: createInterceptor,
// deps: [HttpCacheService],
// multi: true
// }
// ]
// });
// });
afterEach(() => {
httpCacheService.cleanCache();
httpMock.verify();
});
// afterEach(() => {
// httpCacheService.cleanCache();
// httpMock.verify();
// });
describe('with default configuration', () => {
beforeEach(() => {
interceptorOptions = null;
});
// describe('with default configuration', () => {
// beforeEach(() => {
// interceptorOptions = null;
// });
beforeEach(inject([
HttpClient,
HttpTestingController,
HttpCacheService
], (_http: HttpClient,
_httpMock: HttpTestingController,
_httpCacheService: HttpCacheService) => {
// beforeEach(inject([
// HttpClient,
// HttpTestingController,
// HttpCacheService
// ], (_http: HttpClient,
// _httpMock: HttpTestingController,
// _httpCacheService: HttpCacheService) => {
http = _http;
httpMock = _httpMock;
httpCacheService = _httpCacheService;
}));
// http = _http;
// httpMock = _httpMock;
// httpCacheService = _httpCacheService;
// }));
it('should cache the request', () => {
// Act
http.get('/toto').subscribe(() => {
// Assert
const cachedData = httpCacheService.getCacheData('/toto');
expect(cachedData).toBeDefined();
expect(cachedData ? cachedData.body : null).toEqual('someData');
});
// it('should cache the request', () => {
// // Act
// http.get('/toto').subscribe(() => {
// // Assert
// const cachedData = httpCacheService.getCacheData('/toto');
// expect(cachedData).toBeDefined();
// expect(cachedData ? cachedData.body : null).toEqual('someData');
// });
httpMock.expectOne({ url: '/toto' }).flush('someData');
});
// httpMock.expectOne({ url: '/toto' }).flush('someData');
// });
it('should respond from the cache', () => {
// Arrange
httpCacheService.setCacheData('/toto', new HttpResponse({ body: 'cachedData' }));
// it('should respond from the cache', () => {
// // Arrange
// httpCacheService.setCacheData('/toto', new HttpResponse({ body: 'cachedData' }));
// Act
http.get('/toto').subscribe(response => {
// Assert
expect(response).toEqual('cachedData');
});
// // Act
// http.get('/toto').subscribe(response => {
// // Assert
// expect(response).toEqual('cachedData');
// });
httpMock.expectNone({ url: '/toto' });
});
// httpMock.expectNone({ url: '/toto' });
// });
it('should not cache the request in case of error', () => {
// Act
http.get('/toto').subscribe(() => {}, () => {
// Assert
expect(httpCacheService.getCacheData('/toto')).toBeNull();
});
// it('should not cache the request in case of error', () => {
// // Act
// http.get('/toto').subscribe(() => {}, () => {
// // Assert
// expect(httpCacheService.getCacheData('/toto')).toBeNull();
// });
httpMock.expectOne({}).flush(null, {
status: 404,
statusText: 'error'
});
});
});
// httpMock.expectOne({}).flush(null, {
// status: 404,
// statusText: 'error'
// });
// });
// });
describe('with update forced configuration', () => {
beforeEach(() => {
interceptorOptions = { update: true };
});
// describe('with update forced configuration', () => {
// beforeEach(() => {
// interceptorOptions = { update: true };
// });
beforeEach(inject([
HttpClient,
HttpTestingController,
HttpCacheService
], (_http: HttpClient,
_httpMock: HttpTestingController,
_httpCacheService: HttpCacheService) => {
// beforeEach(inject([
// HttpClient,
// HttpTestingController,
// HttpCacheService
// ], (_http: HttpClient,
// _httpMock: HttpTestingController,
// _httpCacheService: HttpCacheService) => {
http = _http;
httpMock = _httpMock;
httpCacheService = _httpCacheService;
}));
// http = _http;
// httpMock = _httpMock;
// httpCacheService = _httpCacheService;
// }));
afterEach(() => {
httpCacheService.cleanCache();
httpMock.verify();
});
// afterEach(() => {
// httpCacheService.cleanCache();
// httpMock.verify();
// });
it('should force cache update', () => {
// Arrange
httpCacheService.setCacheData('/toto', new HttpResponse({ body: 'oldCachedData' }));
cacheInterceptor.configure({ update: true });
// it('should force cache update', () => {
// // Arrange
// httpCacheService.setCacheData('/toto', new HttpResponse({ body: 'oldCachedData' }));
// cacheInterceptor.configure({ update: true });
// Act
http.get('/toto').subscribe(response => {
// Assert
expect(response).toEqual('newData');
// // Act
// http.get('/toto').subscribe(response => {
// // Assert
// expect(response).toEqual('newData');
});
// });
httpMock.expectOne({ url: '/toto' }).flush('newData');
});
});
});
// httpMock.expectOne({ url: '/toto' }).flush('newData');
// });
// });
// });
+3
View File
@@ -1,8 +1,11 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http';
/** rxjs Imports */
import { Observable, Subscriber } from 'rxjs';
/** Custom Services */
import { HttpCacheService } from './http-cache.service';
/**
@@ -1,59 +1,59 @@
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
// import { TestBed, inject } from '@angular/core/testing';
// import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
// import { HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { ErrorHandlerInterceptor } from './error-handler.interceptor';
// import { ErrorHandlerInterceptor } from './error-handler.interceptor';
describe('ErrorHandlerInterceptor', () => {
let errorHandlerInterceptor: ErrorHandlerInterceptor;
let http: HttpClient;
let httpMock: HttpTestingController;
// describe('ErrorHandlerInterceptor', () => {
// let errorHandlerInterceptor: ErrorHandlerInterceptor;
// let http: HttpClient;
// let httpMock: HttpTestingController;
function createInterceptor() {
errorHandlerInterceptor = new ErrorHandlerInterceptor();
return errorHandlerInterceptor;
}
// function createInterceptor() {
// errorHandlerInterceptor = new ErrorHandlerInterceptor();
// return errorHandlerInterceptor;
// }
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [{
provide: HTTP_INTERCEPTORS,
useFactory: createInterceptor,
multi: true
}]
});
});
// beforeEach(() => {
// TestBed.configureTestingModule({
// imports: [HttpClientTestingModule],
// providers: [{
// provide: HTTP_INTERCEPTORS,
// useFactory: createInterceptor,
// multi: true
// }]
// });
// });
beforeEach(inject([
HttpClient,
HttpTestingController
], (_http: HttpClient,
_httpMock: HttpTestingController) => {
// beforeEach(inject([
// HttpClient,
// HttpTestingController
// ], (_http: HttpClient,
// _httpMock: HttpTestingController) => {
http = _http;
httpMock = _httpMock;
}));
// http = _http;
// httpMock = _httpMock;
// }));
afterEach(() => {
httpMock.verify();
});
// afterEach(() => {
// httpMock.verify();
// });
it('should catch error and call error handler', () => {
// Arrange
// Note: here we spy on private method since target is customization here,
// but you should replace it by actual behavior in your app
spyOn(ErrorHandlerInterceptor.prototype as any, 'errorHandler').and.callThrough();
// it('should catch error and call error handler', () => {
// // Arrange
// // Note: here we spy on private method since target is customization here,
// // but you should replace it by actual behavior in your app
// spyOn(ErrorHandlerInterceptor.prototype as any, 'errorHandler').and.callThrough();
// Act
http.get('/toto').subscribe(() => fail('should error'), () => {
// Assert
expect(ErrorHandlerInterceptor.prototype['errorHandler']).toHaveBeenCalled();
});
// // Act
// http.get('/toto').subscribe(() => fail('should error'), () => {
// // Assert
// expect(ErrorHandlerInterceptor.prototype['errorHandler']).toHaveBeenCalled();
// });
httpMock.expectOne({}).flush(null, {
status: 404,
statusText: 'error'
});
});
});
// httpMock.expectOne({}).flush(null, {
// status: 404,
// statusText: 'error'
// });
// });
// });
+19 -5
View File
@@ -1,28 +1,42 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
/** rxjs Imports */
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { environment } from '../../../environments/environment';
import { Logger } from '../logger.service';
import { AlertService } from '../alert.service';
/** Environment Configuration */
import { environment } from 'environments/environment';
/** Custom Services */
import { Logger } from '../logger/logger.service';
import { AlertService } from '../alert/alert.service';
/** Initialize Logger */
const log = new Logger('ErrorHandlerInterceptor');
/**
* Adds a default error handler to all requests.
* Http Request interceptor to add a default error handler to requests.
*/
@Injectable()
export class ErrorHandlerInterceptor implements HttpInterceptor {
/**
* @param {AlertService} alertService Alert Service.
*/
constructor(private alertService: AlertService) { }
/**
* Intercepts a Http request and adds a default error handler.
*/
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(error => this.handleError(error)));
}
// Customize the default error handler here if needed
/**
* Error handler.
*/
private handleError(response: HttpErrorResponse): Observable<HttpEvent<any>> {
const status = response.status;
let errorMessage = (response.error.developerMessage || response.message);
+152 -152
View File
@@ -1,194 +1,194 @@
import { TestBed, inject } from '@angular/core/testing';
import { HttpResponse } from '@angular/common/http';
// import { TestBed, inject } from '@angular/core/testing';
// import { HttpResponse } from '@angular/common/http';
import { HttpCacheService, HttpCacheEntry } from './http-cache.service';
// import { HttpCacheService, HttpCacheEntry } from './http-cache.service';
const cachePersistenceKey = 'httpCache';
// const cachePersistenceKey = 'httpCache';
describe('HttpCacheService', () => {
let httpCacheService: HttpCacheService;
let response: HttpResponse<any>;
// describe('HttpCacheService', () => {
// let httpCacheService: HttpCacheService;
// let response: HttpResponse<any>;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [HttpCacheService]
});
// beforeEach(() => {
// TestBed.configureTestingModule({
// providers: [HttpCacheService]
// });
// Start fresh
window.sessionStorage.removeItem(cachePersistenceKey);
window.localStorage.removeItem(cachePersistenceKey);
});
// // Start fresh
// window.sessionStorage.removeItem(cachePersistenceKey);
// window.localStorage.removeItem(cachePersistenceKey);
// });
beforeEach(inject([HttpCacheService], (_httpCacheService: HttpCacheService) => {
httpCacheService = _httpCacheService;
// beforeEach(inject([HttpCacheService], (_httpCacheService: HttpCacheService) => {
// httpCacheService = _httpCacheService;
response = new HttpResponse({ body: 'data' });
}));
// response = new HttpResponse({ body: 'data' });
// }));
afterEach(() => {
httpCacheService.cleanCache();
});
// afterEach(() => {
// httpCacheService.cleanCache();
// });
describe('setCacheData', () => {
it('should set cache data', () => {
// Act
httpCacheService.setCacheData('/popo', response);
// describe('setCacheData', () => {
// it('should set cache data', () => {
// // Act
// httpCacheService.setCacheData('/popo', response);
// Assert
expect(httpCacheService.getCacheData('/popo')).toEqual(response);
});
// // Assert
// expect(httpCacheService.getCacheData('/popo')).toEqual(response);
// });
it('should replace existing data', () => {
// Arrange
const newResponse = new HttpResponse({ body: 'new data' });
// it('should replace existing data', () => {
// // Arrange
// const newResponse = new HttpResponse({ body: 'new data' });
// Act
httpCacheService.setCacheData('/popo', response);
httpCacheService.setCacheData('/popo', newResponse);
// // Act
// httpCacheService.setCacheData('/popo', response);
// httpCacheService.setCacheData('/popo', newResponse);
// Assert
expect(httpCacheService.getCacheData('/popo')).toEqual(newResponse);
});
// // Assert
// expect(httpCacheService.getCacheData('/popo')).toEqual(newResponse);
// });
it('should set cache date correctly', () => {
// Act
const date = new Date(123);
httpCacheService.setCacheData('/popo', response, date);
httpCacheService.setCacheData('/hoho', response);
// it('should set cache date correctly', () => {
// // Act
// const date = new Date(123);
// httpCacheService.setCacheData('/popo', response, date);
// httpCacheService.setCacheData('/hoho', response);
// Assert
expect((<HttpCacheEntry>httpCacheService.getHttpCacheEntry('/popo')).lastUpdated).toBe(date);
expect((<HttpCacheEntry>httpCacheService.getHttpCacheEntry('/hoho')).lastUpdated).not.toBe(date);
});
});
// // Assert
// expect((<HttpCacheEntry>httpCacheService.getHttpCacheEntry('/popo')).lastUpdated).toBe(date);
// expect((<HttpCacheEntry>httpCacheService.getHttpCacheEntry('/hoho')).lastUpdated).not.toBe(date);
// });
// });
describe('getCacheData', () => {
it('should return null if no cache', () => {
expect(httpCacheService.getCacheData('/hoho')).toBe(null);
});
// describe('getCacheData', () => {
// it('should return null if no cache', () => {
// expect(httpCacheService.getCacheData('/hoho')).toBe(null);
// });
it('should return cached data if exists', () => {
// Act
httpCacheService.setCacheData('/hoho', response);
// it('should return cached data if exists', () => {
// // Act
// httpCacheService.setCacheData('/hoho', response);
// Assert
expect(httpCacheService.getCacheData('/hoho')).toEqual(response);
});
// // Assert
// expect(httpCacheService.getCacheData('/hoho')).toEqual(response);
// });
it('should return cached data with url parameters if exists', () => {
// Act
httpCacheService.setCacheData('/hoho?pif=paf', response);
// it('should return cached data with url parameters if exists', () => {
// // Act
// httpCacheService.setCacheData('/hoho?pif=paf', response);
// Assert
expect(httpCacheService.getCacheData('/hoho?pif=paf')).toEqual(response);
});
});
// // Assert
// expect(httpCacheService.getCacheData('/hoho?pif=paf')).toEqual(response);
// });
// });
describe('getHttpCacheEntry', () => {
it('should return null if no cache', () => {
expect(httpCacheService.getHttpCacheEntry('/hoho')).toBe(null);
});
// describe('getHttpCacheEntry', () => {
// it('should return null if no cache', () => {
// expect(httpCacheService.getHttpCacheEntry('/hoho')).toBe(null);
// });
it('should return cached data date if exists', () => {
// Arrange
const date = new Date(123);
// it('should return cached data date if exists', () => {
// // Arrange
// const date = new Date(123);
// Act
httpCacheService.setCacheData('/hoho', response, date);
const entry = httpCacheService.getHttpCacheEntry('/hoho');
// // Act
// httpCacheService.setCacheData('/hoho', response, date);
// const entry = httpCacheService.getHttpCacheEntry('/hoho');
// Assert
expect(entry).not.toBeNull();
expect((<HttpCacheEntry>entry).lastUpdated).toEqual(date);
expect((<HttpCacheEntry>entry).data).toEqual(response);
});
});
// // Assert
// expect(entry).not.toBeNull();
// expect((<HttpCacheEntry>entry).lastUpdated).toEqual(date);
// expect((<HttpCacheEntry>entry).data).toEqual(response);
// });
// });
describe('clearCacheData', () => {
it('should clear existing cache data', () => {
// Set cache
httpCacheService.setCacheData('/hoho', response);
expect(httpCacheService.getCacheData('/hoho')).toEqual(response);
// describe('clearCacheData', () => {
// it('should clear existing cache data', () => {
// // Set cache
// httpCacheService.setCacheData('/hoho', response);
// expect(httpCacheService.getCacheData('/hoho')).toEqual(response);
// Clear cache
httpCacheService.clearCache('/hoho');
expect(httpCacheService.getCacheData('/hoho')).toBe(null);
});
// // Clear cache
// httpCacheService.clearCache('/hoho');
// expect(httpCacheService.getCacheData('/hoho')).toBe(null);
// });
it('should do nothing if no cache exists', () => {
expect(httpCacheService.getCacheData('/lolo')).toBe(null);
httpCacheService.clearCache('/hoho');
expect(httpCacheService.getCacheData('/lolo')).toBe(null);
});
});
// it('should do nothing if no cache exists', () => {
// expect(httpCacheService.getCacheData('/lolo')).toBe(null);
// httpCacheService.clearCache('/hoho');
// expect(httpCacheService.getCacheData('/lolo')).toBe(null);
// });
// });
describe('cleanCache', () => {
it('should clear all cache if no date is specified', () => {
// Set cache
httpCacheService.setCacheData('/hoho', response);
httpCacheService.setCacheData('/popo', response);
expect(httpCacheService.getCacheData('/hoho')).toBe(response);
expect(httpCacheService.getCacheData('/popo')).toBe(response);
// describe('cleanCache', () => {
// it('should clear all cache if no date is specified', () => {
// // Set cache
// httpCacheService.setCacheData('/hoho', response);
// httpCacheService.setCacheData('/popo', response);
// expect(httpCacheService.getCacheData('/hoho')).toBe(response);
// expect(httpCacheService.getCacheData('/popo')).toBe(response);
// Clean cache
httpCacheService.cleanCache();
expect(httpCacheService.getCacheData('/hoho')).toBe(null);
expect(httpCacheService.getCacheData('/popo')).toBe(null);
});
// // Clean cache
// httpCacheService.cleanCache();
// expect(httpCacheService.getCacheData('/hoho')).toBe(null);
// expect(httpCacheService.getCacheData('/popo')).toBe(null);
// });
it('should clear existing since specified date', () => {
// Set cache
httpCacheService.setCacheData('/hoho', response);
expect(httpCacheService.getCacheData('/hoho')).toBe(response);
// it('should clear existing since specified date', () => {
// // Set cache
// httpCacheService.setCacheData('/hoho', response);
// expect(httpCacheService.getCacheData('/hoho')).toBe(response);
// Clean cache
httpCacheService.cleanCache(new Date());
expect(httpCacheService.getCacheData('/hoho')).toBe(null);
});
// // Clean cache
// httpCacheService.cleanCache(new Date());
// expect(httpCacheService.getCacheData('/hoho')).toBe(null);
// });
it('should not affect cache entries newer than specified date', () => {
// Set cache
httpCacheService.setCacheData('/hoho', response);
expect(httpCacheService.getCacheData('/hoho')).toBe(response);
// it('should not affect cache entries newer than specified date', () => {
// // Set cache
// httpCacheService.setCacheData('/hoho', response);
// expect(httpCacheService.getCacheData('/hoho')).toBe(response);
// Clean cache
const date = new Date();
httpCacheService.setCacheData('/lolo', response, new Date(date.getTime() + 10));
httpCacheService.cleanCache(date);
// // Clean cache
// const date = new Date();
// httpCacheService.setCacheData('/lolo', response, new Date(date.getTime() + 10));
// httpCacheService.cleanCache(date);
// Assert
expect(httpCacheService.getCacheData('/hoho')).toBe(null);
expect(httpCacheService.getCacheData('/lolo')).toBe(response);
});
});
// // Assert
// expect(httpCacheService.getCacheData('/hoho')).toBe(null);
// expect(httpCacheService.getCacheData('/lolo')).toBe(response);
// });
// });
describe('setPersistence', () => {
beforeEach(() => {
httpCacheService.setPersistence();
httpCacheService.cleanCache = jasmine.createSpy('cleanCache');
});
// describe('setPersistence', () => {
// beforeEach(() => {
// httpCacheService.setPersistence();
// httpCacheService.cleanCache = jasmine.createSpy('cleanCache');
// });
it('should clear previous cache data when persistence value change', () => {
httpCacheService.setPersistence('local');
expect(httpCacheService.cleanCache).toHaveBeenCalledWith();
});
// it('should clear previous cache data when persistence value change', () => {
// httpCacheService.setPersistence('local');
// expect(httpCacheService.cleanCache).toHaveBeenCalledWith();
// });
it('should persist cache to local storage', () => {
expect(localStorage.getItem(cachePersistenceKey)).toBeNull();
// it('should persist cache to local storage', () => {
// expect(localStorage.getItem(cachePersistenceKey)).toBeNull();
httpCacheService.setPersistence('local');
httpCacheService.setCacheData('/hoho', response);
// httpCacheService.setPersistence('local');
// httpCacheService.setCacheData('/hoho', response);
expect(localStorage.getItem(cachePersistenceKey)).not.toBeNull();
});
// expect(localStorage.getItem(cachePersistenceKey)).not.toBeNull();
// });
it('should persist cache to session storage', () => {
expect(sessionStorage.getItem(cachePersistenceKey)).toBeNull();
// it('should persist cache to session storage', () => {
// expect(sessionStorage.getItem(cachePersistenceKey)).toBeNull();
httpCacheService.setPersistence('session');
httpCacheService.setCacheData('/hoho', response);
// httpCacheService.setPersistence('session');
// httpCacheService.setCacheData('/hoho', response);
expect(sessionStorage.getItem(cachePersistenceKey)).not.toBeNull();
});
});
});
// expect(sessionStorage.getItem(cachePersistenceKey)).not.toBeNull();
// });
// });
// });
+11 -4
View File
@@ -1,13 +1,17 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { HttpResponse } from '@angular/common/http';
/** Other Imports */
import { each } from 'lodash';
import { Logger } from '../logger.service';
/** Custom Services */
import { Logger } from '../logger/logger.service';
/** Initialize Logger */
const log = new Logger('HttpCacheService');
const cachePersistenceKey = 'httpCache';
/** Http Cache Entry Model */
export interface HttpCacheEntry {
lastUpdated: Date;
data: HttpResponse<any>;
@@ -19,6 +23,9 @@ export interface HttpCacheEntry {
@Injectable()
export class HttpCacheService {
/** Key to cache Http Requests in storage. */
private cachePersistenceStorageKey = 'mifosXHttpCache';
private cachedData: { [key: string]: HttpCacheEntry; } = {};
private storage: Storage | null = null;
@@ -107,12 +114,12 @@ export class HttpCacheService {
private saveCacheData() {
if (this.storage) {
this.storage[cachePersistenceKey] = JSON.stringify(this.cachedData);
this.storage[this.cachePersistenceStorageKey] = JSON.stringify(this.cachedData);
}
}
private loadCacheData() {
const data = this.storage ? this.storage[cachePersistenceKey] : null;
const data = this.storage ? this.storage[this.cachePersistenceStorageKey] : null;
this.cachedData = data ? JSON.parse(data) : {};
}
+122 -122
View File
@@ -1,140 +1,140 @@
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient, HttpInterceptor } from '@angular/common/http';
// import { TestBed, inject } from '@angular/core/testing';
// import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
// import { HttpClient, HttpInterceptor } from '@angular/common/http';
import { HttpService } from './http.service';
import { HttpCacheService } from './http-cache.service';
import { ErrorHandlerInterceptor } from './error-handler.interceptor';
import { CacheInterceptor } from './cache.interceptor';
import { ApiPrefixInterceptor } from './api-prefix.interceptor';
// import { HttpService } from './http.service';
// import { HttpCacheService } from './http-cache.service';
// import { ErrorHandlerInterceptor } from './error-handler.interceptor';
// import { CacheInterceptor } from './cache.interceptor';
// import { ApiPrefixInterceptor } from './api-prefix.interceptor';
describe('HttpService', () => {
let httpCacheService: HttpCacheService;
let http: HttpClient;
let httpMock: HttpTestingController;
// describe('HttpService', () => {
// let httpCacheService: HttpCacheService;
// let http: HttpClient;
// let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
ErrorHandlerInterceptor,
CacheInterceptor,
ApiPrefixInterceptor,
HttpCacheService,
{
provide: HttpClient,
useClass: HttpService
},
]
});
});
// beforeEach(() => {
// TestBed.configureTestingModule({
// imports: [HttpClientTestingModule],
// providers: [
// ErrorHandlerInterceptor,
// CacheInterceptor,
// ApiPrefixInterceptor,
// HttpCacheService,
// {
// provide: HttpClient,
// useClass: HttpService
// },
// ]
// });
// });
beforeEach(inject([
HttpClient,
HttpTestingController,
HttpCacheService
], (_http: HttpClient,
_httpMock: HttpTestingController,
_httpCacheService: HttpCacheService) => {
// beforeEach(inject([
// HttpClient,
// HttpTestingController,
// HttpCacheService
// ], (_http: HttpClient,
// _httpMock: HttpTestingController,
// _httpCacheService: HttpCacheService) => {
http = _http;
httpMock = _httpMock;
httpCacheService = _httpCacheService;
}));
// http = _http;
// httpMock = _httpMock;
// httpCacheService = _httpCacheService;
// }));
afterEach(() => {
httpCacheService.cleanCache();
httpMock.verify();
});
// afterEach(() => {
// httpCacheService.cleanCache();
// httpMock.verify();
// });
it('should use error handler, API prefix and no cache by default', () => {
// Arrange
let interceptors: HttpInterceptor[];
const realRequest = http.request;
spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
interceptors = this.interceptors;
return realRequest.apply(this, arguments);
});
// it('should use error handler, API prefix and no cache by default', () => {
// // Arrange
// let interceptors: HttpInterceptor[];
// const realRequest = http.request;
// spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
// interceptors = this.interceptors;
// return realRequest.apply(this, arguments);
// });
// Act
const request = http.get('/toto');
// // Act
// const request = http.get('/toto');
// Assert
request.subscribe(() => {
expect(http.request).toHaveBeenCalled();
expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeTruthy();
expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeTruthy();
expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeFalsy();
});
httpMock.expectOne({}).flush({});
});
// // Assert
// request.subscribe(() => {
// expect(http.request).toHaveBeenCalled();
// expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeTruthy();
// expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeTruthy();
// expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeFalsy();
// });
// httpMock.expectOne({}).flush({});
// });
it('should use cache', () => {
// Arrange
let interceptors: HttpInterceptor[];
const realRequest = http.request;
spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
interceptors = this.interceptors;
return realRequest.apply(this, arguments);
});
// it('should use cache', () => {
// // Arrange
// let interceptors: HttpInterceptor[];
// const realRequest = http.request;
// spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
// interceptors = this.interceptors;
// return realRequest.apply(this, arguments);
// });
// Act
const request = http
.cache()
.get('/toto');
// // Act
// const request = http
// .cache()
// .get('/toto');
// Assert
request.subscribe(() => {
expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeTruthy();
expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeTruthy();
expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeTruthy();
});
httpMock.expectOne({}).flush({});
});
// // Assert
// request.subscribe(() => {
// expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeTruthy();
// expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeTruthy();
// expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeTruthy();
// });
// httpMock.expectOne({}).flush({});
// });
it('should skip error handler', () => {
// Arrange
let interceptors: HttpInterceptor[];
const realRequest = http.request;
spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
interceptors = this.interceptors;
return realRequest.apply(this, arguments);
});
// it('should skip error handler', () => {
// // Arrange
// let interceptors: HttpInterceptor[];
// const realRequest = http.request;
// spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
// interceptors = this.interceptors;
// return realRequest.apply(this, arguments);
// });
// Act
const request = http
.skipErrorHandler()
.get('/toto');
// // Act
// const request = http
// .skipErrorHandler()
// .get('/toto');
// Assert
request.subscribe(() => {
expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeTruthy();
expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeFalsy();
expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeFalsy();
});
httpMock.expectOne({}).flush({});
});
// // Assert
// request.subscribe(() => {
// expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeTruthy();
// expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeFalsy();
// expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeFalsy();
// });
// httpMock.expectOne({}).flush({});
// });
it('should not use API prefix', () => {
// Arrange
let interceptors: HttpInterceptor[];
const realRequest = http.request;
spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
interceptors = this.interceptors;
return realRequest.apply(this, arguments);
});
// it('should not use API prefix', () => {
// // Arrange
// let interceptors: HttpInterceptor[];
// const realRequest = http.request;
// spyOn(HttpService.prototype, 'request').and.callFake(function(this: any) {
// interceptors = this.interceptors;
// return realRequest.apply(this, arguments);
// });
// Act
const request = http
.disableApiPrefix()
.get('/toto');
// // Act
// const request = http
// .disableApiPrefix()
// .get('/toto');
// Assert
request.subscribe(() => {
expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeFalsy();
expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeTruthy();
expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeFalsy();
});
httpMock.expectOne({}).flush({});
});
});
// // Assert
// request.subscribe(() => {
// expect(interceptors.some(i => i instanceof ApiPrefixInterceptor)).toBeFalsy();
// expect(interceptors.some(i => i instanceof ErrorHandlerInterceptor)).toBeTruthy();
// expect(interceptors.some(i => i instanceof CacheInterceptor)).toBeFalsy();
// });
// httpMock.expectOne({}).flush({});
// });
// });
+20 -9
View File
@@ -1,36 +1,43 @@
/** Angular Imports */
import { Inject, Injectable, InjectionToken, Injector, Optional } from '@angular/core';
import { HttpClient, HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Interceptors */
import { ErrorHandlerInterceptor } from './error-handler.interceptor';
import { CacheInterceptor } from './cache.interceptor';
import { ApiPrefixInterceptor } from './api-prefix.interceptor';
// HttpClient is declared in a re-exported module, so we have to extend the original module to make it work properly
// (see https://github.com/Microsoft/TypeScript/issues/13897)
/**
* HttpClient is declared in a re-exported module, so we have to extend the original module to make it work properly.
* (see https://github.com/Microsoft/TypeScript/issues/13897)
*/
declare module '@angular/common/http/src/client' {
// Augment HttpClient with the added configuration methods from HttpService, to allow in-place replacement of
// HttpClient with HttpService using dependency injection
/**
* Augment HttpClient with the added configuration methods from HttpService, to allow in-place replacement of
* HttpClient with HttpService using dependency injection.
*/
export interface HttpClient {
/**
* Enables caching for this request.
* @param {boolean} forceUpdate Forces request to be made and updates cache entry.
* @return {HttpClient} The new instance.
* @returns {HttpClient} The new instance.
*/
cache(forceUpdate?: boolean): HttpClient;
/**
* Skips default error handler for this request.
* @return {HttpClient} The new instance.
* @returns {HttpClient} The new instance.
*/
skipErrorHandler(): HttpClient;
/**
* Do not use API prefix for this request.
* @return {HttpClient} The new instance.
* @returns {HttpClient} The new instance.
*/
disableApiPrefix(): HttpClient;
@@ -38,7 +45,9 @@ declare module '@angular/common/http/src/client' {
}
// From @angular/common/http/src/interceptor: allows to chain interceptors
/**
* From @angular/common/http/src/interceptor: allows to chain interceptors
*/
class HttpInterceptorHandler implements HttpHandler {
constructor(private next: HttpHandler, private interceptor: HttpInterceptor) { }
@@ -92,7 +101,9 @@ export class HttpService extends HttpClient {
return this.removeInterceptor(ApiPrefixInterceptor);
}
// Override the original method to wire interceptors when triggering the request.
/**
* Override the original method to wire interceptors when triggering the request.
*/
request(method?: any, url?: any, options?: any): any {
const handler = this.interceptors.reduceRight(
(next, interceptor) => new HttpInterceptorHandler(next, interceptor),