Skip to content
Snippets Groups Projects
Commit 766a51b9 authored by Albert Bruns's avatar Albert Bruns
Browse files

OZG-7712 fix refresh bug

parent ca41aec5
No related branches found
No related tags found
1 merge request!101OZG-7712 Fix reloading bug
......@@ -40,6 +40,9 @@ describe('KeycloakResourceService', () => {
const dummyObject: Dummy = createDummy();
const dummyAction: Observable<Dummy> = of(dummyObject);
const dummyError: Error = new Error('Test error');
const dummyErrorAction: Observable<Error> = new Observable((observer) => observer.error(dummyError));
beforeEach(() => {
TestBed.configureTestingModule({
providers: [TestResourceService],
......@@ -52,7 +55,7 @@ describe('KeycloakResourceService', () => {
const stateResource: StateResource<unknown> = createStateResource([]);
beforeEach(() => {
service.handleChanges = jest.fn().mockReturnValue(singleCold(stateResource));
service._handleChanges = jest.fn().mockReturnValue(singleCold(stateResource));
});
it('should return stateResource', () => {
......@@ -64,7 +67,7 @@ describe('KeycloakResourceService', () => {
it('should call handleChanges ', fakeAsync(() => {
service.getAll().subscribe();
expect(service.handleChanges).toHaveBeenCalled();
expect(service._handleChanges).toHaveBeenCalled();
}));
});
......@@ -76,7 +79,7 @@ describe('KeycloakResourceService', () => {
});
it('should call doIfLoadingRequired', () => {
service.handleChanges(emptyStateResource);
service._handleChanges(emptyStateResource);
expect(doIfLoadingRequiredSpy).toHaveBeenCalled();
});
......@@ -84,7 +87,7 @@ describe('KeycloakResourceService', () => {
it('should return stateResource', (done) => {
service.stateResource.next(createStateResource([]));
service.handleChanges(emptyStateResource).subscribe((stateResource: StateResource<[]>) => {
service._handleChanges(emptyStateResource).subscribe((stateResource: StateResource<[]>) => {
expect(stateResource).toEqual(createStateResource([]));
done();
});
......@@ -93,18 +96,18 @@ describe('KeycloakResourceService', () => {
describe('loadResource', () => {
it('should call set loading', () => {
service.setLoading = jest.fn();
service._setLoading = jest.fn();
service.loadResource();
service._loadResource();
expect(service.setLoading).toHaveBeenCalled();
expect(service._setLoading).toHaveBeenCalled();
});
it('should update Resource', fakeAsync(() => {
const dummyItems = [createDummy(), createDummy()];
jest.spyOn(service, '_getItemsFromKeycloak' as any).mockReturnValue(of(dummyItems));
service.loadResource();
service._loadResource();
tick();
expect(service.stateResource.value.resource).toEqual(dummyItems);
......@@ -115,11 +118,11 @@ describe('KeycloakResourceService', () => {
const saveObject: Dummy = createDummy();
it('should call handleLoading', () => {
service.handleLoading = jest.fn();
service._handleLoading = jest.fn();
service.create(saveObject);
expect(service.handleLoading).toHaveBeenCalled();
expect(service._handleLoading).toHaveBeenCalled();
});
it('should call createInKeycloak', () => {
......@@ -133,11 +136,11 @@ describe('KeycloakResourceService', () => {
describe('save', () => {
it('should call handleLoading', () => {
service.handleLoading = jest.fn();
service._handleLoading = jest.fn();
service.save(dummyObject);
expect(service.handleLoading).toHaveBeenCalled();
expect(service._handleLoading).toHaveBeenCalled();
});
it('should call createInKeycloak', () => {
......@@ -151,11 +154,11 @@ describe('KeycloakResourceService', () => {
describe('delete', () => {
it('should call handleLoading', () => {
service.handleLoading = jest.fn();
service._handleLoading = jest.fn();
service.delete(id);
expect(service.handleLoading).toHaveBeenCalled();
expect(service._handleLoading).toHaveBeenCalled();
});
it('should call createInKeycloak', () => {
......@@ -168,37 +171,58 @@ describe('KeycloakResourceService', () => {
});
describe('handleLoading', () => {
it('should set loading', () => {
service._handleLoading(dummyAction);
expect(service.stateResource.value.loading).toBe(true);
});
it('should call refreshAfterFirstEmit', () => {
service.refreshAfterFirstEmit = jest.fn().mockReturnValue(dummyAction);
service._refreshAfterEmit = jest.fn().mockReturnValue(dummyAction);
service.handleLoading(dummyAction);
service._handleLoading(dummyAction);
expect(service.refreshAfterFirstEmit).toHaveBeenCalled();
expect(service._refreshAfterEmit).toHaveBeenCalled();
});
it('should call progress', () => {
service.setLoadingInStateResource = jest.fn().mockReturnValue(dummyAction);
service._setLoadingInStateResource = jest.fn().mockReturnValue(dummyAction);
service.handleLoading(dummyAction);
service._handleLoading(dummyAction);
expect(service.setLoadingInStateResource).toHaveBeenCalled();
expect(service._setLoadingInStateResource).toHaveBeenCalled();
});
});
describe('refreshAfterFirstEmit', () => {
it('should call refresh after first emit', fakeAsync(() => {
describe('refreshAfterEmit', () => {
it('should call refresh after first emit', () => {
service.refresh = jest.fn();
service.refreshAfterFirstEmit(dummyAction).subscribe();
tick();
service._refreshAfterEmit(dummyAction).subscribe();
expect(service.refresh).toHaveBeenCalled();
}));
});
it('should call refresh on error', () => {
service.refresh = jest.fn();
service._refreshAfterEmit(dummyErrorAction).subscribe();
expect(service.refresh).toHaveBeenCalled();
});
it('should throw error refresh on error', () => {
service.refresh = jest.fn();
const result: Observable<unknown> = service._refreshAfterEmit(dummyErrorAction);
expect(result).toBeObservable(cold('#', null, dummyError));
});
});
describe('setLoadingInStateResource', () => {
it('should emit emptyState first with loading and then state without loading', () => {
const result: Observable<StateResource<Dummy>> = service.setLoadingInStateResource<Dummy>(cold('--x', { x: dummyObject }));
const result: Observable<StateResource<Dummy>> = service._setLoadingInStateResource<Dummy>(cold('--x', { x: dummyObject }));
expect(result).toBeObservable(cold('a-b', { a: createEmptyStateResource(true), b: createStateResource(dummyObject) }));
});
......@@ -208,7 +232,7 @@ describe('KeycloakResourceService', () => {
it('should set loading in state to true without parameter', () => {
service.stateResource.value.loading = false;
service.setLoading();
service._setLoading();
expect(service.stateResource.value.loading).toEqual(true);
});
......
......@@ -22,7 +22,7 @@
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared';
import { BehaviorSubject, first, map, Observable, startWith, switchMap, tap } from 'rxjs';
import { BehaviorSubject, catchError, first, map, Observable, startWith, switchMap, tap } from 'rxjs';
export abstract class KeycloakResourceService<T> {
readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject(createEmptyStateResource());
......@@ -30,16 +30,16 @@ export abstract class KeycloakResourceService<T> {
public getAll(): Observable<StateResource<T[]>> {
return this.stateResource
.asObservable()
.pipe(switchMap((stateResource: StateResource<T[]>) => this.handleChanges(stateResource)));
.pipe(switchMap((stateResource: StateResource<T[]>) => this._handleChanges(stateResource)));
}
handleChanges(stateResource: StateResource<T[]>): Observable<StateResource<T[]>> {
doIfLoadingRequired(stateResource, (): void => this.loadResource());
_handleChanges(stateResource: StateResource<T[]>): Observable<StateResource<T[]>> {
doIfLoadingRequired(stateResource, (): void => this._loadResource());
return this.stateResource.asObservable();
}
loadResource(): void {
this.setLoading();
_loadResource(): void {
this._setLoading();
this._getItemsFromKeycloak()
.pipe(first())
.subscribe((items: T[]): void => this.updateResource(items));
......@@ -52,42 +52,49 @@ export abstract class KeycloakResourceService<T> {
}
public create(item: Partial<T>): Observable<StateResource<T>> {
return this.handleLoading<T>(this._createInKeycloak(item));
return this._handleLoading<T>(this._createInKeycloak(item));
}
protected abstract _createInKeycloak(item: Partial<T>): Observable<T>;
public save(item: T): Observable<StateResource<T>> {
return this.handleLoading<T>(this._saveInKeycloak(item));
return this._handleLoading<T>(this._saveInKeycloak(item));
}
protected abstract _saveInKeycloak(item: T): Observable<T>;
public delete(id: string): Observable<StateResource<void>> {
return this.handleLoading(this._deleteInKeycloak(id));
return this._handleLoading(this._deleteInKeycloak(id));
}
protected abstract _deleteInKeycloak(id: string): Observable<void>;
handleLoading<D>(action: Observable<D>): Observable<StateResource<D>> {
return this.setLoadingInStateResource<D>(this.refreshAfterFirstEmit<D>(action));
_handleLoading<D>(action: Observable<D>): Observable<StateResource<D>> {
this._setLoading();
return this._setLoadingInStateResource<D>(this._refreshAfterEmit<D>(action));
}
refreshAfterFirstEmit<D>(action: Observable<D>): Observable<D> {
_refreshAfterEmit<D>(action: Observable<D>): Observable<D> {
return action.pipe(
first(),
tap((): void => this.refresh()),
catchError((err: Error) => this.handleError(err)),
);
}
setLoadingInStateResource<D>(action: Observable<D>): Observable<StateResource<D>> {
handleError(err: Error): never {
this.refresh();
throw err;
}
_setLoadingInStateResource<D>(action: Observable<D>): Observable<StateResource<D>> {
return action.pipe(
map((value: D): StateResource<D> => createStateResource<D>(value)),
startWith(createEmptyStateResource<D>(true)),
);
}
setLoading(): void {
_setLoading(): void {
this.stateResource.next({ ...this.stateResource.value, loading: true });
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment