diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts index 1a7c4254c31475dde3488c115c80245b758d0145..db02b9a18f8e000c512b8339c441599529e7efe1 100644 --- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts @@ -4,7 +4,7 @@ import { fakeAsync, tick } from '@angular/core/testing'; import { faker } from '@faker-js/faker'; import { Resource, ResourceUri, getUrl } from '@ngxp/rest'; import { cold } from 'jest-marbles'; -import { Observable, lastValueFrom, of, throwError } from 'rxjs'; +import { BehaviorSubject, Observable, lastValueFrom, of, throwError } from 'rxjs'; import { createProblemDetail } from '../../../test//error'; import { singleCold, singleHot } from '../../../test/marbles'; import { createDummyResource } from '../../../test/resource'; @@ -33,6 +33,8 @@ describe('ResourceService', () => { const getLinkRel: LinkRelationName = 'dummyGetLinkRel'; const deleteLinkRel: LinkRelationName = 'dummyDeleteLinkRel'; + const linkedResourceUri = faker.internet.url(); + beforeEach(() => { config = { resource: configStateResource$, @@ -348,6 +350,49 @@ describe('ResourceService', () => { }); }); + describe('getLinkedResoure', () => { + beforeEach(() => { + service.linkedResources[linkedResourceUri] = new BehaviorSubject(createEmptyStateResource()); + }); + + it('should call createIfNotExist ', () => { + service.createIfNotExist = jest.fn(); + service.loadLinkedResoure = jest.fn(); + + service.getLinkedResoure(linkedResourceUri); + + expect(service.createIfNotExist).toHaveBeenCalled(); + }); + + it('should call loadLinkedResource if loading is required', () => { + service.createIfNotExist(linkedResourceUri); + service.loadLinkedResoure = jest.fn(); + + service.getLinkedResoure(linkedResourceUri); + + expect(service.loadLinkedResoure).toHaveBeenCalledWith(linkedResourceUri); + }); + }); + + describe('createIfNotExists', () => { + it('should create linked resource if none exists', () => { + service.createIfNotExist(linkedResourceUri); + + expect(service.linkedResources[linkedResourceUri].value).toEqual(createEmptyStateResource()); + }); + }); + + describe('loadLinkedResource', () => { + it('should call repository getResource', () => { + repository.getResource = jest.fn().mockReturnValue(of(createDummyResource())); + service.createIfNotExist(linkedResourceUri); + + service.loadLinkedResoure(linkedResourceUri); + + expect(repository.getResource).toHaveBeenCalledWith(linkedResourceUri); + }); + }); + describe('update stateresource', () => { const resourceToBeSet: Resource = createDummyResource(); diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts index 1b5ea7e05416786b91861e5f79a247501076fed3..d2d2c83a291b42b2385a371660f1e095c572903e 100644 --- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts +++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts @@ -1,6 +1,6 @@ import { HttpErrorResponse } from '@angular/common/http'; import { getUrl, hasLink, Resource, ResourceUri } from '@ngxp/rest'; -import { isEqual, isNull } from 'lodash-es'; +import { isEqual, isNil, isNull } from 'lodash-es'; import { BehaviorSubject, catchError, combineLatest, filter, first, map, Observable, of, startWith, tap, throwError } from 'rxjs'; import { isUnprocessableEntity } from '../http.util'; import { HttpError } from '../tech.model'; @@ -12,6 +12,7 @@ import { createEmptyStateResource, createErrorStateResource, createStateResource, + doIfLoadingRequired, isInvalidResourceCombination, isLoadingRequired, isStateResoureStable, @@ -26,6 +27,7 @@ export abstract class ResourceService<B extends Resource, T extends Resource> { readonly stateResource: BehaviorSubject<StateResource<T>> = new BehaviorSubject(createEmptyStateResource()); configResource: B = null; + linkedResources = {}; constructor( protected config: ResourceServiceConfig<B>, @@ -111,6 +113,33 @@ export abstract class ResourceService<B extends Resource, T extends Resource> { .subscribe((loadedResource: T) => this.updateStateResource(loadedResource)); } + public getLinkedResoure<F extends Resource>(resourceUri: ResourceUri): Observable<StateResource<F>> { + this.createIfNotExist(resourceUri); + + //todo: In Funktion auslagern + doIfLoadingRequired(this.linkedResources[resourceUri].value, () => { + this.setLinkedResourceLoading(resourceUri); + this.loadLinkedResoure(resourceUri); + }); + + return this.linkedResources[resourceUri].asObservable(); + } + + createIfNotExist(uri: ResourceUri): void { + if (isNil(this.linkedResources[uri])) this.linkedResources[uri] = new BehaviorSubject(createEmptyStateResource()); + } + + loadLinkedResoure(resourceUri: ResourceUri): void { + this.repository + .getResource(resourceUri) + .pipe(first()) + .subscribe((loadedResource: any) => this.linkedResources[resourceUri].next(createStateResource(loadedResource))); + } + + setLinkedResourceLoading(resourceUri: ResourceUri): void { + this.linkedResources[resourceUri].next(createEmptyStateResource(true)); + } + setStateResourceLoading(): void { this.stateResource.next({ ...createEmptyStateResource(true), reload: false }); }