From b4883c4a20a90fe0e54f47e5a0571df284de772b Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Thu, 13 Jun 2024 14:50:23 +0200
Subject: [PATCH] OZG-5812 show message if cannot export - add tests

---
 alfa-client/libs/test-utils/src/lib/helper.ts | 13 +++++
 .../vorgang-detail-more-menu.component.html   |  1 -
 ...vorgang-detail-more-menu.component.spec.ts | 21 +++-----
 .../vorgang-export-container.component.html   |  4 +-
 ...vorgang-export-container.component.spec.ts | 51 +++++++++++++++++--
 .../vorgang-export-container.component.ts     | 16 +++---
 6 files changed, 78 insertions(+), 28 deletions(-)

diff --git a/alfa-client/libs/test-utils/src/lib/helper.ts b/alfa-client/libs/test-utils/src/lib/helper.ts
index a4fcbd913f..ed3e6fa137 100644
--- a/alfa-client/libs/test-utils/src/lib/helper.ts
+++ b/alfa-client/libs/test-utils/src/lib/helper.ts
@@ -74,6 +74,19 @@ function getDebugElementFromFixtureByDirective(
   return fixture.debugElement.query(By.directive(query));
 }
 
+function getAllDebugElementsFromFixtureByDirective(
+  fixture: ComponentFixture<any>,
+  query: Type<any>,
+): DebugElement[] {
+  return fixture.debugElement.queryAll(By.directive(query));
+}
+
 export function getMockComponent<T>(fixture: ComponentFixture<unknown>, component: Type<T>): T {
   return <T>getDebugElementFromFixtureByDirective(fixture, component).componentInstance;
 }
+
+export function getMockComponents<T>(fixture: ComponentFixture<unknown>, component: Type<T>): T[] {
+  return getAllDebugElementsFromFixtureByDirective(fixture, component).map(
+    (debugElement) => <T>debugElement.componentInstance,
+  );
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html
index 6ca2dbaa35..f85e710ee2 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html
@@ -9,7 +9,6 @@
 </button>
 <ozgcloud-menu #moreMenu data-test-id="more-menu">
   <ozgcloud-menu-item
-    *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.EXPORT"
     data-test-id="vorgang-exportieren-button"
     headline="Vorgang exportieren"
     text="Alle Informationen und Anhänge des Vorgangs zur Archivierung im DMS."
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts
index ccc2742029..7b41960423 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts
@@ -2,6 +2,7 @@ import {
   getElementFromDomRoot,
   getElementFromFixture,
   getMockComponent,
+  getMockComponents,
 } from '@alfa-client/test-utils';
 import { MenuItemComponent, OzgcloudIconComponent, UiModule } from '@alfa-client/ui';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
@@ -122,7 +123,7 @@ describe('VorgangDetailMoreMenuComponent', () => {
       fixture.detectChanges();
     });
 
-    it('should be visible if link exists', () => {
+    it('should be visible', () => {
       component.vorgangWithEingang = vorgangWithEingang;
       fixture.detectChanges();
       getElementFromFixture(fixture, moreMenuButton).click();
@@ -132,16 +133,6 @@ describe('VorgangDetailMoreMenuComponent', () => {
       expect(element).toBeInTheDocument();
     });
 
-    it('should NOT be visible if link is missing', () => {
-      component.vorgangWithEingang = createVorgangWithEingangResource();
-      fixture.detectChanges();
-      getElementFromFixture(fixture, moreMenuButton).click();
-
-      const element = getElementFromDomRoot(fixture, exportMenuItem);
-
-      expect(element).not.toBeInTheDocument();
-    });
-
     describe('input property', () => {
       beforeEach(() => {
         component.vorgangWithEingang = vorgangWithEingang;
@@ -236,7 +227,7 @@ describe('VorgangDetailMoreMenuComponent', () => {
       it('should contains headline', () => {
         getElementFromFixture(fixture, moreMenuButton).click();
 
-        const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent);
+        const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1];
 
         expect(menuItem.headline).toBe('Vorgang automatisiert vorprüfen');
       });
@@ -244,7 +235,7 @@ describe('VorgangDetailMoreMenuComponent', () => {
       it('should contains text', () => {
         getElementFromFixture(fixture, moreMenuButton).click();
 
-        const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent);
+        const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1];
 
         expect(menuItem.text).toBe(
           'Eine Vorprüfung wird durchgeführt. Das Ergebnis wird als Kommentar hinzugefügt.',
@@ -254,7 +245,7 @@ describe('VorgangDetailMoreMenuComponent', () => {
       it('should contains icon', () => {
         getElementFromFixture(fixture, moreMenuButton).click();
 
-        const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent);
+        const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1];
 
         expect(menuItem.icon).toBe('vorgang_vorpruefen');
       });
@@ -262,7 +253,7 @@ describe('VorgangDetailMoreMenuComponent', () => {
       it('should contains iconSizeBig', () => {
         getElementFromFixture(fixture, moreMenuButton).click();
 
-        const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent);
+        const menuItem: MenuItemComponent = getMockComponents(fixture, MenuItemComponent)[1];
 
         expect(menuItem.iconSizeBig).toBeTruthy();
       });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html
index a92d333788..b3ce1c48f2 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html
@@ -1,13 +1,13 @@
 <ng-container>
   <ozgcloud-button-with-spinner
-    *ngIf="isClosedStatus"
+    *ngIf="canExport"
     dataTestId="export-vorgang"
     [showSpinner]="(exportStateResource$ | async)?.loading"
     (clickEmitter)="export()"
     text="Herunterladen"
     icon="save_alt"
   />
-  <div *ngIf="!isClosedStatus" class="flex gap-2 items-start">
+  <div *ngIf="!canExport" class="flex gap-2 items-start" data-test-id="cannot-export-vorgang">
     <ods-exclamate-icon />
     <div>
       <p class="text-error font-medium text-sm">Vorgang exportieren nicht möglich.</p>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts
index 23b7002028..f9164132fc 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts
@@ -1,8 +1,11 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { StateResource, createStateResource } from '@alfa-client/tech-shared';
-import { dispatchEventFromFixture, mock } from '@alfa-client/test-utils';
+import { getElementFromFixture, mock } from '@alfa-client/test-utils';
 import { OzgcloudButtonWithSpinnerComponent } from '@alfa-client/ui';
-import { VorgangService } from '@alfa-client/vorgang-shared';
+import { VorgangService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ExclamateIconComponent } from '@ods/system';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
 import { VorgangExportContainerComponent } from './vorgang-export-container.component';
@@ -13,14 +16,20 @@ describe('VorgangExportContainerComponent', () => {
 
   const vorgangExportStateResource: StateResource<boolean> = createStateResource(false);
   const vorgangService = mock(VorgangService);
+  const vorgangResourceWithLink = createVorgangWithEingangResource([
+    VorgangWithEingangLinkRel.EXPORT,
+  ]);
+  const vorgangResource = createVorgangWithEingangResource();
 
   const buttonWithSpinner: string = '[dataTestId="export-vorgang"]';
+  const cannotExportMessage: string = getDataTestIdOf('cannot-export-vorgang');
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [
         VorgangExportContainerComponent,
         MockComponent(OzgcloudButtonWithSpinnerComponent),
+        MockComponent(ExclamateIconComponent),
       ],
       providers: [
         {
@@ -60,9 +69,43 @@ describe('VorgangExportContainerComponent', () => {
 
   describe('export', () => {
     it('should call vorgangService.export', () => {
-      dispatchEventFromFixture(fixture, buttonWithSpinner, 'clickEmitter');
+      component.export();
 
       expect(vorgangService.export).toHaveBeenCalled();
     });
   });
+
+  describe('canExport', () => {
+    it('should be true', () => {
+      component.vorgangWithEingang = vorgangResourceWithLink;
+
+      expect(component.canExport).toBe(true);
+    });
+
+    it('should be false', () => {
+      component.vorgangWithEingang = vorgangResource;
+
+      expect(component.canExport).toBe(false);
+    });
+  });
+
+  describe('show export button or message', () => {
+    it('should show button, if canExport is true', () => {
+      component.canExport = true;
+      fixture.detectChanges();
+
+      const element = getElementFromFixture(fixture, buttonWithSpinner);
+
+      expect(element).toBeInstanceOf(HTMLElement);
+    });
+
+    it('should show message, if canExport is false', () => {
+      component.canExport = false;
+      fixture.detectChanges();
+
+      const element = getElementFromFixture(fixture, cannotExportMessage);
+
+      expect(element).toBeInstanceOf(HTMLElement);
+    });
+  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts
index 5de3081506..a6d201ed49 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts
@@ -1,6 +1,11 @@
 import { StateResource } from '@alfa-client/tech-shared';
-import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import {
+  VorgangService,
+  VorgangWithEingangLinkRel,
+  VorgangWithEingangResource,
+} from '@alfa-client/vorgang-shared';
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { hasLink } from '@ngxp/rest';
 import { Observable, tap } from 'rxjs';
 
 @Component({
@@ -9,11 +14,14 @@ import { Observable, tap } from 'rxjs';
   styleUrls: ['./vorgang-export-container.component.scss'],
 })
 export class VorgangExportContainerComponent implements OnInit {
-  @Input() vorgangWithEingang: VorgangWithEingangResource;
+  @Input() set vorgangWithEingang(vorgang: VorgangWithEingangResource) {
+    this.canExport = hasLink(vorgang, VorgangWithEingangLinkRel.EXPORT);
+  }
 
   @Output() public closeMenu: EventEmitter<void> = new EventEmitter();
 
   public exportStateResource$: Observable<StateResource<boolean>>;
+  public canExport: boolean = false;
 
   constructor(private vorgangService: VorgangService) {}
 
@@ -30,8 +38,4 @@ export class VorgangExportContainerComponent implements OnInit {
   public export(): void {
     this.vorgangService.export(this.vorgangWithEingang);
   }
-
-  public get isClosedStatus() {
-    return this.vorgangWithEingang.status === 'ABGESCHLOSSEN';
-  }
 }
-- 
GitLab