From 289d0c626196fa856ed7ad2034f87390447a5d6d Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Wed, 15 May 2024 15:23:11 +0200
Subject: [PATCH] OZG-5012 fix imports; split save/delete

---
 .../src/lib/bescheid.service.ts               |   3 +-
 .../src/lib/+state/command.reducer.spec.ts    |  10 +-
 .../src/lib/+state/command.selectors.ts       |   2 +-
 .../src/lib/command-resource.service.spec.ts  |   2 +-
 .../src/lib/command-resource.service.ts       |   4 +
 .../lib/assistive-technologies.util.spec.ts   |   2 +-
 .../catch-http-error.decorator.spec.ts        |   2 +-
 .../skip-error-interceptor.decorator.ts       |   2 +-
 .../lib/interceptor/http-xsrf.interceptor.ts  |   4 +-
 .../lib/resource/api-resource.service.spec.ts | 107 +++++++++++++++++-
 .../src/lib/resource/api-resource.service.ts  |  14 +++
 .../src/lib/resource/resource.model.ts        |   6 +-
 .../src/lib/resource/resource.util.spec.ts    |  18 +--
 13 files changed, 143 insertions(+), 33 deletions(-)

diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
index 1f32f6c10e..9fcd500a1b 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
@@ -123,14 +123,13 @@ export class BescheidService {
     return {
       resource: this.vorgangService.getVorgangWithEingang(),
       getLinkRel: VorgangWithEingangLinkRel.BESCHEID_DRAFT,
-      editLinkRel: null,
+      delete: { linkRel: BescheidLinkRel.DELETE, order: CommandOrder.DELETE_BESCHEID },
     };
   }
 
   buildBescheidListServiceConfig(): ListResourceServiceConfig<VorgangWithEingangResource> {
     return {
       baseResource: this.vorgangService.getVorgangWithEingang(),
-      createLinkRel: null,
       listLinkRel: VorgangWithEingangLinkRel.BESCHEIDE,
     };
   }
diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts b/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts
index be256c5e2d..0f1608566b 100644
--- a/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts
+++ b/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts
@@ -1,4 +1,3 @@
-import { CommandResource, CreateCommand } from '@alfa-client/command-shared';
 import {
   ApiError,
   createEmptyStateResource,
@@ -8,14 +7,15 @@ import {
 import { HttpErrorResponse } from '@angular/common/http';
 import { Action } from '@ngrx/store';
 import { Resource, ResourceUri } from '@ngxp/rest';
-import { createCommandResource, createCreateCommand } from 'libs/command-shared/test/command';
-import { createApiError, createHttpErrorResponse } from 'libs/tech-shared/test/error';
-import { createDummyResource } from 'libs/tech-shared/test/resource';
+import { createApiError, createHttpErrorResponse } from '../../../../tech-shared/test/error';
+import { createDummyResource } from '../../../../tech-shared/test/resource';
+import { createCommandResource, createCreateCommand } from '../../../test/command';
+import { CommandResource, CreateCommand } from '../command.model';
 import { CommandState, initialState, reducer } from './command.reducer';
 
 import faker from '@faker-js/faker';
 
-import * as CommandActions from '@alfa-client/command-shared';
+import * as CommandActions from '../+state/command.actions';
 
 describe('Command Reducer', () => {
   describe('unknown action', () => {
diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts b/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts
index 65ab3989b7..fcfe5311cc 100644
--- a/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts
+++ b/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts
@@ -1,7 +1,7 @@
-import { CommandOrder } from '@alfa-client/command-shared';
 import { createEmptyStateResource } from '@alfa-client/tech-shared';
 import { MemoizedSelector, createFeatureSelector, createSelector } from '@ngrx/store';
 import { isUndefined } from 'lodash-es';
+import { CommandOrder } from '../command.model';
 import { COMMAND_FEATURE_KEY, CommandState } from './command.reducer';
 
 const getCommandState: MemoizedSelector<object, CommandState> =
diff --git a/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts b/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts
index 89623c8f67..73c60da704 100644
--- a/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts
+++ b/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts
@@ -36,7 +36,7 @@ describe('CommandResourceService', () => {
     config = {
       resource: configStateResource$,
       getLinkRel,
-      editLinkRel,
+      edit: { linkRel: editLinkRel },
       delete: { order: deleteOrder, linkRel: deleteLinkRel },
     };
     repository = mock(ResourceRepository);
diff --git a/alfa-client/libs/command-shared/src/lib/command-resource.service.ts b/alfa-client/libs/command-shared/src/lib/command-resource.service.ts
index 1c9adb7ba7..0eb9f03aa4 100644
--- a/alfa-client/libs/command-shared/src/lib/command-resource.service.ts
+++ b/alfa-client/libs/command-shared/src/lib/command-resource.service.ts
@@ -27,6 +27,10 @@ export class CommandResourceService<B extends Resource, T extends Resource> exte
     super(config, repository);
   }
 
+  doSave(resource: T, toSave: unknown): Observable<T> {
+    throw new Error('Method not implemented.');
+  }
+
   public delete(): Observable<StateResource<CommandResource>> {
     this.verifyDeleteLinkRel();
     return this.commandService.createCommandByProps(this.buildDeleteCommandProps());
diff --git a/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts
index 85677d8969..8d4f98c231 100644
--- a/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts
@@ -1,5 +1,5 @@
+import { EMPTY_STRING } from '../lib/tech.util';
 import { createAriaLabelForIconButton } from './assistive-technologies.util';
-import { EMPTY_STRING } from '@alfa-client/tech-shared';
 
 describe('createAriaLabelForIconButton', () => {
   const tooltip = 'Tooltip text';
diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts b/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts
index 10b94e399d..b28c779d60 100644
--- a/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts
@@ -21,8 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { CatchHttpError } from '@alfa-client/tech-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
+import { CatchHttpError } from '../decorator/catch-http-error.decorator';
 import { HttpErrorHandler } from '../error/error.handler';
 import {
   catchHttpErrorHandleErrorResponse,
diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts b/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts
index 3b4e3082a7..b458fd3d70 100644
--- a/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts
+++ b/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts
@@ -21,8 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { HttpErrorHandler } from '@alfa-client/tech-shared';
 import { finalize } from 'rxjs/operators';
+import { HttpErrorHandler } from '../error/error.handler';
 import {
   disableInterceptorDefaultHandling,
   enableInterceptorDefaultHandling,
diff --git a/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts b/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts
index a7dcd4c44c..b7bc5aa087 100644
--- a/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts
+++ b/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts
@@ -29,9 +29,9 @@ import {
   HttpXsrfTokenExtractor,
 } from '@angular/common/http';
 import { Injectable } from '@angular/core';
-import { addRequestHeader, isNotNull } from '@alfa-client/tech-shared';
 import { Observable } from 'rxjs';
-import { existRequestHeader, isChangingDataRequest } from '../http.util';
+import { addRequestHeader, existRequestHeader, isChangingDataRequest } from '../http.util';
+import { isNotNull } from '../tech.util';
 
 @Injectable()
 export class HttpXsrfInterceptor implements HttpInterceptor {
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.spec.ts
index 81dbaf1226..4776a77377 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.spec.ts
@@ -1,9 +1,13 @@
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
-import { Observable, of } from 'rxjs';
+import { fakeAsync, tick } from '@angular/core/testing';
 import { Resource } from '@ngxp/rest';
-import { createDummyResource } from 'libs/tech-shared/test/resource';
+import { createProblemDetail } from 'libs/tech-shared/test/error';
+import { Observable, of, throwError } from 'rxjs';
+import { singleCold, singleHot } from '../../../test//marbles';
+import { createDummyResource } from '../../../test/resource';
+import { HttpError, ProblemDetail } from '../tech.model';
 import { ApiResourceService } from './api-resource.service';
-import { LinkRelationName, ResourceServiceConfig } from './resource.model';
+import { LinkRelationName, ResourceServiceConfig, SaveResourceData } from './resource.model';
 import { ResourceRepository } from './resource.repository';
 import { StateResource, createStateResource } from './resource.util';
 
@@ -18,12 +22,14 @@ describe('ApiResourceService', () => {
 
   const editLinkRel: string = 'dummyEditLinkRel';
   const getLinkRel: LinkRelationName = 'dummyGetLinkRel';
+  const deleteLinkRel: LinkRelationName = 'dummyDeleteLinkRel';
 
   beforeEach(() => {
     config = {
       resource: configStateResource$,
       getLinkRel,
-      editLinkRel,
+      edit: { linkRel: editLinkRel },
+      delete: { linkRel: deleteLinkRel },
     };
     repository = mock(ResourceRepository);
 
@@ -33,4 +39,97 @@ describe('ApiResourceService', () => {
   it('should be created', () => {
     expect(service).toBeTruthy();
   });
+
+  describe('save', () => {
+    const dummyToSave: unknown = {};
+    const loadedResource: Resource = createDummyResource();
+
+    const resourceWithEditLinkRel: Resource = createDummyResource([editLinkRel]);
+
+    it('should throw error if edit link not exists', () => {
+      service.stateResource.next(createStateResource(createDummyResource()));
+
+      expect(() => service.save(dummyToSave)).toThrowError(
+        'No edit link exists on current stateresource.',
+      );
+    });
+
+    it('should call repository', fakeAsync(() => {
+      service.stateResource.next(createStateResource(resourceWithEditLinkRel));
+      repository.save.mockReturnValue(of(loadedResource));
+
+      service.save(dummyToSave).subscribe();
+      tick();
+
+      const expectedSaveResourceData: SaveResourceData<Resource> = {
+        resource: resourceWithEditLinkRel,
+        linkRel: editLinkRel,
+        toSave: dummyToSave,
+      };
+      expect(repository.save).toHaveBeenCalledWith(expectedSaveResourceData);
+    }));
+
+    it('should return saved object', () => {
+      service.stateResource.next(createStateResource(resourceWithEditLinkRel));
+      repository.save.mockReturnValue(singleHot(loadedResource));
+
+      const saved: Observable<StateResource<Resource | HttpError>> = service.save(dummyToSave);
+
+      expect(saved).toBeObservable(singleCold(createStateResource(loadedResource)));
+    });
+
+    it('should call handleError', () => {
+      service.stateResource.next(createStateResource(createDummyResource([config.edit.linkRel])));
+      const errorResponse: ProblemDetail = createProblemDetail();
+      repository.save.mockReturnValue(throwError(() => errorResponse));
+      service.handleError = jest.fn();
+
+      service.save(<any>{}).subscribe();
+
+      expect(service.handleError).toHaveBeenCalledWith(errorResponse);
+    });
+
+    it('should update state resource subject', fakeAsync(() => {
+      service.stateResource.next(createStateResource(resourceWithEditLinkRel));
+      repository.save.mockReturnValue(of(loadedResource));
+
+      service.save(dummyToSave).subscribe();
+      tick();
+
+      expect(service.stateResource.value).toEqual(createStateResource(loadedResource));
+    }));
+  });
+
+  describe('delete', () => {
+    const resourceWithDeleteLinkRel: Resource = createDummyResource([deleteLinkRel]);
+    const stateResourceWithDeleteLink: StateResource<Resource> =
+      createStateResource(resourceWithDeleteLinkRel);
+
+    beforeEach(() => {
+      service.stateResource.next(stateResourceWithDeleteLink);
+    });
+
+    it('should throw error if delete linkRel not exists on current stateresource', () => {
+      service.stateResource.next(createStateResource(createDummyResource()));
+
+      expect(() => service.delete()).toThrowError(
+        'No delete link exists on current stateresource.',
+      );
+    });
+
+    it('should call repository', () => {
+      service.delete();
+
+      expect(repository.delete).toHaveBeenCalledWith(resourceWithDeleteLinkRel, deleteLinkRel);
+    });
+
+    it('should return value', () => {
+      const deleteResource: Resource = createDummyResource();
+      repository.delete.mockReturnValue(singleHot(deleteResource));
+
+      const deletedResource: Observable<Resource> = service.delete();
+
+      expect(deletedResource).toBeObservable(singleCold(deleteResource));
+    });
+  });
 });
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.ts
index e744c170f1..2f328bcfd4 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/api-resource.service.ts
@@ -1,4 +1,5 @@
 import { Resource } from '@ngxp/rest';
+import { Observable } from 'rxjs';
 import { ResourceServiceConfig } from './resource.model';
 import { ResourceRepository } from './resource.repository';
 import { ResourceService } from './resource.service';
@@ -13,4 +14,17 @@ export class ApiResourceService<B extends Resource, T extends Resource> extends
   ) {
     super(config, repository);
   }
+
+  doSave(resource: T, toSave: unknown): Observable<T> {
+    return <Observable<T>>this.repository.save({
+      resource,
+      linkRel: this.config.edit.linkRel,
+      toSave,
+    });
+  }
+
+  public delete(): Observable<Resource> {
+    this.verifyDeleteLinkRel();
+    return this.repository.delete(this.getResource(), this.config.delete.linkRel);
+  }
 }
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.model.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.model.ts
index 3617275710..e7e4b3264d 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.model.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.model.ts
@@ -5,7 +5,7 @@ import { StateResource } from './resource.util';
 export interface ListResourceServiceConfig<B> {
   baseResource: Observable<StateResource<B>>;
   listLinkRel: LinkRelationName;
-  createLinkRel: LinkRelationName;
+  createLinkRel?: LinkRelationName;
 }
 
 export interface CreateResourceData<T> {
@@ -26,6 +26,6 @@ export declare type LinkRelationName = string;
 export interface ResourceServiceConfig<B> {
   resource: Observable<StateResource<B>>;
   getLinkRel: LinkRelationName;
-  editLinkRel: LinkRelationName;
-  delete?: { order: string; linkRel: string };
+  delete?: { linkRel: LinkRelationName; order?: string };
+  edit?: { linkRel: LinkRelationName; order?: string };
 }
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts
index 2e6894ecb1..e5a9f28f28 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts
@@ -22,25 +22,19 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 
-import {
-  containsLoading,
-  createErrorStateResource,
-  EMPTY_ARRAY,
-  getSuccessfullyLoaded,
-  StateResource,
-} from '@alfa-client/tech-shared';
 import { Resource } from '@ngxp/rest';
-import {
-  createDummyListResource,
-  createDummyResource,
-  toResource,
-} from 'libs/tech-shared/test/resource';
 import { DummyListLinkRel } from '../../../test/dummy';
 import { createApiError } from '../../../test/error';
+import { createDummyListResource, createDummyResource, toResource } from '../../../test/resource';
+import { EMPTY_ARRAY } from '../tech.util';
 import {
+  StateResource,
+  containsLoading,
   createEmptyStateResource,
+  createErrorStateResource,
   createStateResource,
   getEmbeddedResources,
+  getSuccessfullyLoaded,
   isInvalidResourceCombination,
   isLoaded,
   isLoadingRequired,
-- 
GitLab