[SI-1680] total commit

Signed-off-by: Peter Buschmann <peter.buschmann@pta.de>
diff --git a/projects/grid-failure-information-app/src/app/app.component.spec.ts b/projects/grid-failure-information-app/src/app/app.component.spec.ts
index 29a8796..3d142e9 100644
--- a/projects/grid-failure-information-app/src/app/app.component.spec.ts
+++ b/projects/grid-failure-information-app/src/app/app.component.spec.ts
@@ -120,4 +120,11 @@
     (component as any)._registerEvents();
     expect(component.isLoginPage).toBeTruthy();
   });
+
+  it('should process forward urls correctly', () => {
+    const spy1 = spyOn(component.router, 'navigate');
+    const spy2 = spyOn(component as any, '_getParametersFromUrl').and.returnValue('fwId');
+    (component as any)._processDirectLinkToGridFailureDetail();
+    expect(spy1).toHaveBeenCalled();
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/app.component.ts b/projects/grid-failure-information-app/src/app/app.component.ts
index 89a46bd..e131344 100644
--- a/projects/grid-failure-information-app/src/app/app.component.ts
+++ b/projects/grid-failure-information-app/src/app/app.component.ts
@@ -56,7 +56,7 @@
     this._extractTokenFromParameters();
     this.appSandbox.setupPreConfig();
     this._registerEvents();
-    this._processDirectLinkToGridFailureDetailDetail();
+    this._processDirectLinkToGridFailureDetail();
   }
 
   /**
@@ -102,7 +102,7 @@
     });
   }
 
-  private _processDirectLinkToGridFailureDetailDetail() {
+  private _processDirectLinkToGridFailureDetail() {
     const fwdId = this._getParametersFromUrl('fwdId');
     if (fwdId) {
       this.router.navigate(['/grid-failures/', fwdId]);
diff --git a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts
index 584b417..37f8b75 100644
--- a/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/distribution-group/distribution-group-members/distribution-group-members.component.spec.ts
@@ -39,6 +39,13 @@
     expect(spy).toHaveBeenCalled();
   });
 
+  it('should not call delete function for other (not delete) event', () => {
+    const spy: any = spyOn(sandbox, 'deleteDistributionGroupMember');
+    component.ngOnInit();
+    component.gridOptions.context.eventSubject.next({ type: 'test', data: new DistributionGroupMember() });
+    expect(spy).not.toHaveBeenCalled();
+  });
+
   it('should clear search input', () => {
     component.searchInput = { nativeElement: { value: 'x' } };
     component.clearSearchInput();
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.spec.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.spec.ts
index ba3def5..fb9f5a5 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.spec.ts
@@ -25,7 +25,7 @@
     value: {
       failureBegin: 'test1',
       failureEndPlanned: 'test2',
-      failureEndResupplied: 'test3',
+      failureEndResupplied: 'test3 ',
     },
     controls: {
       postcode: { value: null },
@@ -48,6 +48,7 @@
       setViewStateForReqProps() {},
       setSelectedStation() {},
       resetFailureLocationValues() {},
+      deleteGridFailureStation() {},
       gridFailureDetailsFormState$: of({ ...INITIAL_STATE, gridFailureDetailsFormResponse } as any),
       currentFormState: INITIAL_STATE,
       disableStationAttributes: false,
@@ -63,8 +64,7 @@
     expect(component).toBeTruthy();
   });
 
-  it('should end subscriptions in Sandbox before the component going away ', () => {
-    let component = new GridFailureDetailsComponent(gridFailureSandbox, appState);
+  it('should end subscriptions in Sandbox before the component going away', () => {
     let spy = spyOn(gridFailureSandbox, 'endSubscriptions');
 
     component['_subscription'] = { unsubscribe: () => {} } as any;
@@ -132,20 +132,68 @@
     expect(component.mapInteractionMode).toBeFalsy();
   });
 
-  it('checks if _initialFailureLocationState works fine for MS', () => {
+  it('should set this.failureLocationView to Globals.FAILURE_LOCATION_NS if housenumber and coordinates exists', () => {
     component.failureLocationView === Globals.FAILURE_LOCATION_MAP;
-    //MS
+    gridFailureSandbox.gridFailureStations$ = of([new models.FailureStation()]);
     component.gridFailureDetailsSandbox.gridFailureDetailsFormState$ = of(INITIAL_STATE, {
       ...component.gridFailureDetailsSandbox.currentFormState,
       controls: {
-        housenumber: { value: 44 } as any,
+        housenumber: { value: 1 } as any,
         radius: { value: null } as any,
         latitude: { value: 11 } as any,
         longitude: { value: 12 } as any,
       } as any,
     });
     (component as any)._initialFailureLocationState();
-    expect(component.mapInteractionMode).toBeFalsy();
+    expect(component.failureLocationView).toEqual(Globals.FAILURE_LOCATION_NS);
+  });
+
+  it('should set this.failureLocationView to Globals.FAILURE_LOCATION_MS if no housenumber exists', () => {
+    component.failureLocationView === Globals.FAILURE_LOCATION_MAP;
+    gridFailureSandbox.gridFailureStations$ = of([new models.FailureStation()]);
+    component.gridFailureDetailsSandbox.gridFailureDetailsFormState$ = of(INITIAL_STATE, {
+      ...component.gridFailureDetailsSandbox.currentFormState,
+      controls: {
+        housenumber: { value: null } as any,
+        radius: { value: null } as any,
+        latitude: { value: 11 } as any,
+        longitude: { value: 12 } as any,
+      } as any,
+    });
+    (component as any)._initialFailureLocationState();
+    expect(component.failureLocationView).toEqual(Globals.FAILURE_LOCATION_MS);
+  });
+
+  it('should set this.failureLocationView to Globals.FAILURE_LOCATION_MAP if nsData and msData not exists', () => {
+    component.failureLocationView === Globals.FAILURE_LOCATION_MAP;
+    gridFailureSandbox.gridFailureStations$ = of([]);
+    component.gridFailureDetailsSandbox.gridFailureDetailsFormState$ = of(INITIAL_STATE, {
+      ...component.gridFailureDetailsSandbox.currentFormState,
+      controls: {
+        housenumber: { value: null } as any,
+        radius: { value: null } as any,
+        latitude: { value: 11 } as any,
+        longitude: { value: 12 } as any,
+      } as any,
+    });
+    (component as any)._initialFailureLocationState();
+    expect(component.failureLocationView).toEqual(Globals.FAILURE_LOCATION_MAP);
+  });
+
+  it('should set this.failureLocationView to Globals.FAILURE_LOCATION_NS if housenumber and coordinates exists XXX', () => {
+    component.failureLocationView === Globals.FAILURE_LOCATION_MAP;
+    gridFailureSandbox.gridFailureStations$ = of([new models.FailureStation()]);
+    component.gridFailureDetailsSandbox.gridFailureDetailsFormState$ = of(INITIAL_STATE, {
+      ...component.gridFailureDetailsSandbox.currentFormState,
+      controls: {
+        housenumber: { value: null } as any,
+        radius: { value: null } as any,
+        latitude: { value: null } as any,
+        longitude: { value: null } as any,
+      } as any,
+    });
+    (component as any)._initialFailureLocationState();
+    expect(component.failureLocationView).toEqual(Globals.FAILURE_LOCATION_NS);
   });
 
   it('should clear search input', () => {
@@ -175,6 +223,12 @@
     expect(spy).toHaveBeenCalled();
   });
 
+  it('should not reset selected station if value exists', () => {
+    const spy = spyOn(gridFailureSandbox, 'setSelectedStation');
+    component.resetSelectedStation('x');
+    expect(spy).not.toHaveBeenCalled();
+  });
+
   it('should resize map via forceResize$.next(true)', () => {
     const spy = spyOn(component.mapOptions.forceResize$, 'next');
     component.resizeSetMap();
@@ -186,4 +240,11 @@
     component.changeMode();
     expect(spy).toHaveBeenCalledWith({ eventType: component['_modeEnum'].currentVersionMode });
   });
+
+  it('should not call deleteGridFailureStation function for other (not delete) event', () => {
+    const spy: any = spyOn(gridFailureSandbox, 'deleteGridFailureStation');
+    component.ngOnInit();
+    component.gridOptions.context.eventSubject.next({ type: 'test', data: new models.FailureStation() });
+    expect(spy).not.toHaveBeenCalled();
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.ts
index 0d87ecc..9b1f4f8 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.component.ts
@@ -191,6 +191,7 @@
         }
       });
   }
+
   ngOnDestroy() {
     this.gridFailureDetailsSandbox.gridFailureStations = [];
     this.gridFailureDetailsSandbox.endSubscriptions();
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
index fd67e06..eb282ff 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.spec.ts
@@ -27,9 +27,9 @@
 import { UtilService } from '@grid-failure-information-app/shared/utility/utility.service';
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
 import { ActionsSubject, Store, Action } from '@ngrx/store';
-import { DisableAction, EnableAction } from 'ngrx-forms';
+import { DisableAction, EnableAction, SetValueAction, box, SetUserDefinedPropertyAction } from 'ngrx-forms';
 import { of } from 'rxjs';
-import { INITIAL_STATE } from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer';
+import { INITIAL_STATE, FORM_ID, GAS_BRANCH_ID_KEY } from '@grid-failure-information-app/shared/store/reducers/grid-failures/grid-failure-details-form.reducer';
 import * as distributionGroupActions from '@grid-failure-information-app/shared/store/actions/distribution-groups.action';
 
 describe('GridFailureDetailsSandbox', () => {
@@ -61,7 +61,7 @@
     service.gridFailurePublicationChannels$ = of([new PublicationChannel()]);
   }));
 
-  it('should create GridFailureDetailsSandbox service', () => {
+  it('should create GridFailureDetailsSandbox service ', () => {
     expect(service).toBeTruthy();
   });
 
@@ -72,6 +72,15 @@
     expect(spy).toHaveBeenCalled();
   });
 
+  it('should not calculatePolygon via init() if no stations are provided', () => {
+    const spy = spyOn(service as any, '_setBranchIds');
+    const spy2 = spyOn(service as any, '_calculatePolygon');
+    service.gridFailureStations$ = of([]);
+    service.init();
+    expect(spy).toHaveBeenCalled();
+    expect(spy2).not.toHaveBeenCalled();
+  });
+
   it('should dispatch loadGridFailure Action via loadGridFailure(id)', () => {
     service.loadGridFailure('id');
     expect(appState.dispatch).toHaveBeenCalledWith(gridFailureActions.loadGridFailureDetail({ payload: 'id' }));
@@ -116,6 +125,21 @@
     expect(appState.dispatch).toHaveBeenCalledWith(gridFailureActions.loadGridFailureVersions({ payload: 'id' }));
   });
 
+  it('should set oldVersion true if versionNumber < maxVersionNumber', () => {
+    service['gridFailureId'] = 'id';
+    service.maxVersionNumber = 2;
+    service.loadGridFailureVersion('1');
+    expect(service.oldVersion).toBeTruthy();
+  });
+
+  it('should dispatch loadGridFailureDetail action if versionNumber ===  maxVersionNumber', () => {
+    service['gridFailureId'] = 'id';
+    service.maxVersionNumber = 1;
+    service.loadGridFailureVersion('1');
+    expect(dispatchSpy).toHaveBeenCalledTimes(2);
+    expect(dispatchSpy.calls.all()[0].args[0].type).toEqual('[GridFailure Details] Load');
+  });
+
   it('should dispatch loadGridFailureVersion Action via loadGridFailureVersion(VsNo)', () => {
     service['gridFailureId'] = 'id';
     service.maxVersionNumber = 0;
@@ -209,89 +233,6 @@
     expect(appState.dispatch).toHaveBeenCalled();
   });
 
-  it('should dispatch action in response to controlId = gridFailureDetailsForm.postcode', () => {
-    let formState: any = {
-      id: 'gridFailureDetailsForm',
-      value: {
-        statusIntern: StateEnum.CREATED,
-        postcode: '00000',
-      },
-      userDefinedProperties: { controlId: 'gridFailureDetailsForm.postcode' },
-      controls: {
-        postcode: { id: 'gridFailureDetailsForm.postcode' },
-      },
-    };
-
-    service.gridFailureDetailsFormState$ = of({ ...INITIAL_STATE, formState });
-    service.registerEvents();
-    expect(appState.dispatch).toHaveBeenCalled();
-  });
-
-  it('should dispatch action in response to controlId = gridFailureDetailsForm.city', () => {
-    let formState: any = {
-      value: {
-        statusIntern: StateEnum.CREATED,
-        postcode: '00000',
-        city: 'S',
-      },
-      userDefinedProperties: { controlId: 'gridFailureDetailsForm.city' },
-      controls: {
-        postcode: { id: 'gridFailureDetailsForm.postcode' },
-        city: { id: 'gridFailureDetailsForm.city' },
-      },
-    };
-
-    service.gridFailureDetailsFormState$ = of({ ...INITIAL_STATE, formState });
-    service.registerEvents();
-    expect(appState.dispatch).toHaveBeenCalled();
-  });
-
-  it('should dispatch action in response to controlId = gridFailureDetailsForm.district', () => {
-    let formState: any = {
-      id: 'gridFailureDetailsForm',
-      value: {
-        statusIntern: StateEnum.CREATED,
-        postcode: '00000',
-        city: 'X',
-        district: 'Y',
-      },
-      userDefinedProperties: { controlId: 'gridFailureDetailsForm.district' },
-      controls: {
-        postcode: { id: 'gridFailureDetailsForm.postcode' },
-        city: { id: 'gridFailureDetailsForm.city' },
-        district: { id: 'gridFailureDetailsForm.district' },
-      },
-    };
-
-    service.gridFailureDetailsFormState$ = of({ ...INITIAL_STATE, formState });
-    service.registerEvents();
-    expect(appState.dispatch).toHaveBeenCalled();
-  });
-
-  it('should dispatch action in response to controlId = gridFailureDetailsForm.street', () => {
-    let formState: any = {
-      id: 'gridFailureDetailsForm',
-      value: {
-        statusIntern: StateEnum.CREATED,
-        postcode: '00000',
-        city: 'X',
-        district: 'Y',
-        street: 'Z',
-      },
-      userDefinedProperties: { controlId: 'gridFailureDetailsForm.street' },
-      controls: {
-        postcode: { id: 'gridFailureDetailsForm.postcode' },
-        city: { id: 'gridFailureDetailsForm.city' },
-        district: { id: 'gridFailureDetailsForm.district' },
-        street: { id: 'gridFailureDetailsForm.street' },
-      },
-    };
-
-    service.gridFailureDetailsFormState$ = of({ ...INITIAL_STATE, formState });
-    service.registerEvents();
-    expect(appState.dispatch).toHaveBeenCalled();
-  });
-
   it('should show qualify button state is applied', () => {
     const state = StateEnum.CREATED;
     (service as any)._showButtonsByState(state);
@@ -486,6 +427,12 @@
     });
   });
 
+  it('should not process searchForAddressPostalcodes further if text$ is undefined', () => {
+    let text$;
+    const result = service.searchForAddressPostalcodes(text$ as any);
+    expect(result).toBeFalsy();
+  });
+
   it('should trigger searchForAddressPostalcodes and check if the right value was returned if length is under 2', () => {
     const text$ = of('h');
     const result = service.searchForAddressPostalcodes(text$);
@@ -576,6 +523,28 @@
     expect(service.noBranchId).toBe(null);
   });
 
+  it('should setNoBranch id', () => {
+    const branch: FailureBranch = new FailureBranch();
+    branch.id = '123';
+    branch.name = 'OS';
+    branch.description = 'ohne Sparte';
+    const branches: FailureBranch[] = [branch];
+    service.gridFailureBranches$ = of(branches);
+    (service as any)._setBranchIds();
+    expect(service.noBranchId).toBe('123');
+  });
+
+  it('should set gasBranch id', () => {
+    const branch: FailureBranch = new FailureBranch();
+    branch.id = '123';
+    branch.name = 'G';
+    branch.description = 'Gas';
+    const branches: FailureBranch[] = [branch];
+    service.gridFailureBranches$ = of(branches);
+    (service as any)._setBranchIds();
+    expect(appState.dispatch).toHaveBeenCalledWith(new SetUserDefinedPropertyAction(FORM_ID, GAS_BRANCH_ID_KEY, '123'));
+  });
+
   it('should call resetFailureLocationValues and dispatch an setValueAction', () => {
     const gfdetail = new GridFailure();
     gfdetail.id = 'id';
@@ -605,6 +574,12 @@
     expect(appState.dispatch).toHaveBeenCalledWith(new DisableAction(INITIAL_STATE.controls.radiusId.id));
   });
 
+  it('should not call call saveFailureLocationSpecificParts if part is empty', () => {
+    let part: string = '';
+    service.setViewStateForReqProps(part);
+    expect(appState.dispatch).not.toHaveBeenCalled();
+  });
+
   it('should delete gridFailure station', () => {
     let station = new FailureStation();
     station.id = 'xx';
@@ -724,4 +699,178 @@
     service.setPublicationChannels('SMS', false);
     expect(appState.dispatch).toHaveBeenCalledWith(gridFailureActions.deletePublicationChannelAssignment({ gridFailureId: 'x1', channel: 'SMS' }));
   });
+
+  it('should dispatch setValueAction for distributionGroupUuids if _assignedDistributionGroups exist', () => {
+    const gfdetail = new GridFailure();
+    gfdetail.id = 'id';
+
+    service.currentFormState = INITIAL_STATE;
+    (service.currentFormState as any).isValid = true;
+    (service.currentFormState as any).value = gfdetail;
+    (service.currentFormState as any).userDefinedProperties = { controlId: '' };
+
+    service['_assignedDistributionGroups'] = [new DistributionGroup({ id: 'x' })];
+
+    service.saveGridFailure();
+    expect(appState.dispatch).toHaveBeenCalledWith(new SetValueAction(INITIAL_STATE.controls.distributionGroupUuids.id, box(['x'])));
+  });
+
+  it('should dispatch action in response to controlId = gridFailureDetailsForm.postcode', () => {
+    let formState: any = {
+      id: 'gridFailureDetailsForm',
+      value: {
+        statusIntern: StateEnum.CREATED,
+        postcode: '00000',
+        branch: 'G',
+      },
+      userDefinedProperties: { controlId: 'gridFailureDetailsForm.postcode' },
+      controls: {
+        postcode: { id: 'gridFailureDetailsForm.postcode' },
+        __formBranch: { id: 'test' },
+      },
+    };
+    (service as any)._handleUserDefinedProperties(formState);
+    expect(appState.dispatch).toHaveBeenCalledWith(
+      gridFailureActions.loadAddressCommunities({ branch: formState.value.branch, postcode: formState.value.postcode })
+    );
+  });
+
+  it('should dispatch action in response to controlId = gridFailureDetailsForm.city', () => {
+    let formState: any = {
+      value: {
+        statusIntern: StateEnum.CREATED,
+        postcode: '00000',
+        branch: 'G',
+        city: 'S',
+      },
+      userDefinedProperties: { controlId: 'gridFailureDetailsForm.city' },
+      controls: {
+        postcode: { id: 'gridFailureDetailsForm.postcode' },
+        __formBranch: { id: 'test' },
+        city: { id: 'gridFailureDetailsForm.city' },
+      },
+    };
+    (service as any)._handleUserDefinedProperties(formState);
+    expect(appState.dispatch).toHaveBeenCalledWith(
+      gridFailureActions.loadAddressDistricts({
+        branch: formState.value.branch,
+        postcode: formState.value.postcode,
+        community: formState.value.city,
+      })
+    );
+  });
+
+  it('should dispatch action in response to controlId = gridFailureDetailsForm.district', () => {
+    let formState: any = {
+      id: 'gridFailureDetailsForm',
+      value: {
+        statusIntern: StateEnum.CREATED,
+        branch: 'G',
+        postcode: '00000',
+        city: 'X',
+        district: 'Y',
+      },
+      userDefinedProperties: { controlId: 'gridFailureDetailsForm.district' },
+      controls: {
+        __formBranch: { id: 'test' },
+        postcode: { id: 'gridFailureDetailsForm.postcode' },
+        city: { id: 'gridFailureDetailsForm.city' },
+        district: { id: 'gridFailureDetailsForm.district' },
+      },
+    };
+    (service as any)._handleUserDefinedProperties(formState);
+    expect(appState.dispatch).toHaveBeenCalledWith(
+      gridFailureActions.loadAddressStreets({
+        branch: formState.value.branch,
+        postcode: formState.value.postcode,
+        community: formState.value.city,
+        district: formState.value.district,
+      })
+    );
+  });
+
+  it('should dispatch action in response to controlId = gridFailureDetailsForm.street', () => {
+    let formState: any = {
+      id: 'gridFailureDetailsForm',
+      value: {
+        statusIntern: StateEnum.CREATED,
+        branch: 'G',
+        postcode: '00000',
+        city: 'X',
+        district: 'Y',
+        street: 'Z',
+      },
+      userDefinedProperties: { controlId: 'gridFailureDetailsForm.street' },
+      controls: {
+        __formBranch: { id: 'test' },
+        postcode: { id: 'gridFailureDetailsForm.postcode' },
+        city: { id: 'gridFailureDetailsForm.city' },
+        district: { id: 'gridFailureDetailsForm.district' },
+        street: { id: 'gridFailureDetailsForm.street' },
+      },
+    };
+    (service as any)._handleUserDefinedProperties(formState);
+    expect(appState.dispatch).toHaveBeenCalledWith(
+      gridFailureActions.loadAddressHouseNumbers({
+        branch: formState.value.branch,
+        postcode: formState.value.postcode,
+        community: formState.value.city,
+        street: formState.value.street,
+      })
+    );
+  });
+
+  it('should dispatch action in response to controlId = gridFailureDetailsForm.housenumber', () => {
+    const spy: any = spyOn(service, 'setLatLong');
+    let formState: any = {
+      id: 'gridFailureDetailsForm',
+      value: {
+        statusIntern: StateEnum.CREATED,
+        branch: 'G',
+        postcode: '00000',
+        city: 'X',
+        district: 'Y',
+        street: 'Z',
+        housenumber: '1a',
+      },
+      userDefinedProperties: { controlId: 'gridFailureDetailsForm.housenumber' },
+      controls: {
+        __formBranch: { id: 'test' },
+        postcode: { id: 'gridFailureDetailsForm.postcode' },
+        city: { id: 'gridFailureDetailsForm.city' },
+        district: { id: 'gridFailureDetailsForm.district' },
+        street: { id: 'gridFailureDetailsForm.street' },
+        housenumber: { id: 'gridFailureDetailsForm.housenumber' },
+      },
+    };
+    (service as any)._handleUserDefinedProperties(formState);
+    expect(spy).toHaveBeenCalledWith(formState.controls.housenumber.value);
+  });
+
+  it('should dispatch action in response to controlId = gridFailureDetailsForm', () => {
+    const spy: any = spyOn(service, 'loadInitialAddressData');
+    let formState: any = {
+      id: 'gridFailureDetailsForm',
+      value: {
+        statusIntern: StateEnum.CREATED,
+        branch: 'G',
+        postcode: '00000',
+        city: 'X',
+        district: 'Y',
+        street: 'Z',
+        housenumber: '1a',
+      },
+      userDefinedProperties: { controlId: 'gridFailureDetailsForm' },
+      controls: {
+        __formBranch: { id: 'test' },
+        postcode: { id: 'gridFailureDetailsForm.postcode' },
+        city: { id: 'gridFailureDetailsForm.city' },
+        district: { id: 'gridFailureDetailsForm.district' },
+        street: { id: 'gridFailureDetailsForm.street' },
+        housenumber: { id: 'gridFailureDetailsForm.housenumber' },
+      },
+    };
+    (service as any)._handleUserDefinedProperties(formState);
+    expect(spy).toHaveBeenCalledWith(formState);
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
index 097f62d..f5051c8 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-details.sandbox.ts
@@ -358,55 +358,7 @@
       this.currentFormState = formState;
       this._showButtonsByState(formState.value.statusIntern);
       this._setDynamicRequired();
-
-      switch (formState.userDefinedProperties[DEPENDENT_FIELD_KEY]) {
-        case formState.controls.__formBranch.id:
-        case formState.id:
-          this.loadInitialAddressData(formState);
-          break;
-
-        case formState.controls.postcode.id:
-          this.appState$.dispatch(gridFailureActions.loadAddressCommunities({ branch: formState.value.branch, postcode: formState.value.postcode }));
-          break;
-
-        case formState.controls.city.id:
-          this.appState$.dispatch(
-            gridFailureActions.loadAddressDistricts({
-              branch: formState.value.branch,
-              postcode: formState.value.postcode,
-              community: formState.value.city,
-            })
-          );
-          break;
-
-        case formState.controls.district.id:
-          this.appState$.dispatch(
-            gridFailureActions.loadAddressStreets({
-              branch: formState.value.branch,
-              postcode: formState.value.postcode,
-              community: formState.value.city,
-              district: formState.value.district,
-            })
-          );
-          break;
-
-        case formState.controls.street.id:
-          this.appState$.dispatch(
-            gridFailureActions.loadAddressHouseNumbers({
-              branch: formState.value.branch,
-              postcode: formState.value.postcode,
-              community: formState.value.city,
-              street: formState.value.street,
-            })
-          );
-          break;
-        case formState.controls.housenumber.id:
-          this.setLatLong(formState.controls.housenumber.value);
-          break;
-
-        default:
-          break;
-      }
+      this._handleUserDefinedProperties(formState);
     });
 
     this.actionsSubject
@@ -803,4 +755,55 @@
         break;
     }
   }
+
+  private _handleUserDefinedProperties(formState: FormGroupState<models.GridFailure>) {
+    switch (formState.userDefinedProperties[DEPENDENT_FIELD_KEY]) {
+      case formState.controls.__formBranch.id:
+      case formState.id:
+        this.loadInitialAddressData(formState);
+        break;
+
+      case formState.controls.postcode.id:
+        this.appState$.dispatch(gridFailureActions.loadAddressCommunities({ branch: formState.value.branch, postcode: formState.value.postcode }));
+        break;
+
+      case formState.controls.city.id:
+        this.appState$.dispatch(
+          gridFailureActions.loadAddressDistricts({
+            branch: formState.value.branch,
+            postcode: formState.value.postcode,
+            community: formState.value.city,
+          })
+        );
+        break;
+
+      case formState.controls.district.id:
+        this.appState$.dispatch(
+          gridFailureActions.loadAddressStreets({
+            branch: formState.value.branch,
+            postcode: formState.value.postcode,
+            community: formState.value.city,
+            district: formState.value.district,
+          })
+        );
+        break;
+
+      case formState.controls.street.id:
+        this.appState$.dispatch(
+          gridFailureActions.loadAddressHouseNumbers({
+            branch: formState.value.branch,
+            postcode: formState.value.postcode,
+            community: formState.value.city,
+            street: formState.value.street,
+          })
+        );
+        break;
+      case formState.controls.housenumber.id:
+        this.setLatLong(formState.controls.housenumber.value);
+        break;
+
+      default:
+        break;
+    }
+  }
 }
diff --git a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.spec.ts b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.spec.ts
index 8ac6fad..d7f233b 100644
--- a/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.spec.ts
+++ b/projects/grid-failure-information-app/src/app/pages/grid-failure/grid-failure-details/grid-failure-distribution-groups/grid-failure-distribution-groups.component.spec.ts
@@ -44,6 +44,13 @@
     expect(spy).toHaveBeenCalled();
   });
 
+  it('should not call delete function for other (not delete) event', () => {
+    const spy: any = spyOn(sandbox, 'deleteDistributionGroupAssignment');
+    component.ngOnInit();
+    component.gridOptions.context.eventSubject.next({ type: 'test', data: new DistributionGroup() });
+    expect(spy).not.toHaveBeenCalled();
+  });
+
   it('should clear selected distribution group', () => {
     component.selectedGroup = new DistributionGroup({ id: 'x' });
     component.clearSelectedGroup();
diff --git a/projects/grid-failure-information-app/src/app/shared/filters/ag-grid/set-filter/set-filter.component.spec.ts b/projects/grid-failure-information-app/src/app/shared/filters/ag-grid/set-filter/set-filter.component.spec.ts
index 5c82842..6fb5a07 100644
--- a/projects/grid-failure-information-app/src/app/shared/filters/ag-grid/set-filter/set-filter.component.spec.ts
+++ b/projects/grid-failure-information-app/src/app/shared/filters/ag-grid/set-filter/set-filter.component.spec.ts
@@ -12,6 +12,7 @@
  ********************************************************************************/
 import { SetFilterComponent } from '@grid-failure-information-app/shared/filters/ag-grid/set-filter/set-filter.component';
 import { IFilterParams, RowNode } from 'ag-grid-community';
+import { ALL_NGRX_FORMS_ACTION_TYPES } from 'ngrx-forms';
 
 describe('SetFilterComponent', () => {
   let component: SetFilterComponent;
@@ -36,6 +37,27 @@
     expect(filteredItem).toEqual({ AAA: {}, checked: true });
   });
 
+  it('should set selectAllChecked false is an non-empty filter text is provided', () => {
+    component.setItems = [
+      { AAA: {}, checked: true },
+      { BBB: {}, checked: true },
+    ];
+    const compAnonym = component as any;
+    compAnonym._params = { filterChangedCallback() {} };
+    component.filterText = 'Test';
+    component.filterCheckboxList('X');
+    expect(component.selectAllChecked).toBeFalsy();
+  });
+
+  it('should setItems in response to filteredItems', () => {
+    component.setItems = [{ BBB: {}, checked: false }];
+    component['_filteredItem'] = [{ BBB: {}, checked: true }];
+    const compAnonym = component as any;
+    compAnonym._params = { filterChangedCallback() {} };
+    component.filterCheckboxList('B');
+    expect(component.setItems['BBB']).toEqual(component['_filteredItem']['BBB']);
+  });
+
   it('should return isFilterActive', () => {
     component.setItems = [{ checked: true }, { checked: true }];
     expect(component.isFilterActive()).toBeFalsy();
@@ -74,6 +96,15 @@
     expect(component.setItems.null.checked).toBeFalsy();
   });
 
+  it('should set selectAllChecked false if filterText is empty', () => {
+    component['_params'] = { filterChangedCallback() {} } as any;
+    component.setItems = { null: { checked: false } };
+    component.filterText = '';
+    const event = { target: { id: 'null', checked: true } } as any;
+    component.notifyFilter(event);
+    expect(component.selectAllChecked).toBeFalsy();
+  });
+
   it('should selectAll via selectAll with given event', () => {
     component['_params'] = { filterChangedCallback() {} } as any;
     component.setItems = { null: { checked: false } };
@@ -96,53 +127,61 @@
     expect(returnValue).toBeFalsy();
   });
 
+  it('should not pass filter for itemKey null', () => {
+    const params = { node: '' } as any;
+    component['_valueGetter'] = () => params.node;
+    component.setItems = { null: { checked: false } };
+    const returnValue = component.doesFilterPass(params);
+    expect(returnValue).toBeFalsy();
+  });
+
   it('should return true after calling doesFilterPass(..) with filter 50 and node value 50 ', () => {
     component['_valueGetter'] = () => 50;
-    component.setItems = { 50: {checked:true}};
+    component.setItems = { 50: { checked: true } };
     const returnValue = component.doesFilterPass({} as any);
     expect(returnValue).toBeTruthy();
   });
 
   it('should return false after calling doesFilterPass(..) with filter 50 and node value 666 ', () => {
     component['_valueGetter'] = () => 666;
-    component.setItems = { 50: {checked:true}};
+    component.setItems = { 50: { checked: true } };
     const returnValue = component.doesFilterPass({} as any);
     expect(returnValue).toBeFalsy();
   });
 
   it('should return false after calling doesFilterPass(..) with filter "oncle" and node value "tom" ', () => {
     component['_valueGetter'] = () => 'tom';
-    component.setItems = { oncle: {checked:true}};
+    component.setItems = { oncle: { checked: true } };
     const returnValue = component.doesFilterPass({} as any);
     expect(returnValue).toBeFalsy();
   });
 
   it('should return true after calling doesFilterPass(..) with filter "oncle" and node value "oncle" ', () => {
     component['_valueGetter'] = () => 'oncle';
-    component.setItems = { oncle: {checked:true}};
+    component.setItems = { oncle: { checked: true } };
     const returnValue = component.doesFilterPass({} as any);
     expect(returnValue).toBeTruthy();
   });
 
   it('should return true after calling doesFilterPass(..) with filter "oncle" and node value "oncle tom" ', () => {
     component['_valueGetter'] = () => 'oncle tom';
-    component.setItems = { oncle: {checked:true}};
+    component.setItems = { oncle: { checked: true } };
     const returnValue = component.doesFilterPass({} as any);
     expect(returnValue).toBeTruthy();
   });
 
   it('should set params via agInit()', () => {
-    const params : any = {
+    const params: any = {
       node: 'x',
       colDef: {
-        colId: 'testColId'
+        colId: 'testColId',
       },
       rowModel: {
         nodeManager: {
-          allNodesMap:  {
-            0:  {id: '0'},
-            1:  {id: '1'},
-          }
+          allNodesMap: {
+            0: { id: '0' },
+            1: { id: '1' },
+          },
         },
       },
       doesRowPassOtherFilter() {},
@@ -160,8 +199,16 @@
         gridOptionsWrapper: { gridOptions: { onGridSizeChanged: () => {}, onRowDataChanged: () => {} } },
       },
     } as any;
-    component["_valueGetter"] = ()=>{return {id: '0'}};
+    component['_valueGetter'] = () => {
+      return { id: '0' };
+    };
     component.agInit(params);
     expect(component['_params']).toEqual(params as any);
   });
+
+  it('should setFilterItems via afterGuiAttached', () => {
+    const spy = spyOn(component as any, '_setFilterItems');
+    component.afterGuiAttached('x');
+    expect(spy).toHaveBeenCalled();
+  });
 });
diff --git a/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/hist-grid-failure-stations.reducer.spec.ts b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/hist-grid-failure-stations.reducer.spec.ts
new file mode 100644
index 0000000..566fe11
--- /dev/null
+++ b/projects/grid-failure-information-app/src/app/shared/store/reducers/grid-failures/hist-grid-failure-stations.reducer.spec.ts
@@ -0,0 +1,85 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import {
+  HistGridFailureStationsReducer,
+  INITIAL_STATE,
+  getData,
+  getLoading,
+  getLoaded,
+  getFailed,
+  reducer,
+} from '@grid-failure-information-app/shared/store/reducers/grid-failures/hist-grid-failure-stations.reducer';
+import * as gridFailureActions from '@grid-failure-information-app/shared/store/actions/grid-failures.action';
+import { FailureStation } from '@grid-failure-information-app/shared/models';
+
+describe('HistGridFailureStationsReducer', () => {
+  it('should return the initial state', () => {
+    const action = { type: 'NOOP' } as any;
+    const result = reducer(undefined, action);
+
+    expect(result).toBe(INITIAL_STATE);
+  });
+
+  it('should trigger loading state', () => {
+    const action = gridFailureActions.loadHistGridFailureStations({ failureId: 'x', versionNumber: '1' });
+    const result = HistGridFailureStationsReducer(INITIAL_STATE, action);
+
+    expect(result).toEqual({
+      ...INITIAL_STATE,
+      loading: true,
+    });
+  });
+
+  it('should trigger loaded state', () => {
+    const items = { payload: [new FailureStation()] };
+    const action = gridFailureActions.loadHistGridFailureStationsSuccess(items);
+    const result = HistGridFailureStationsReducer(INITIAL_STATE, action);
+
+    expect(result.loaded).toBe(true);
+  });
+
+  it('should trigger failed state', () => {
+    const error = { payload: 'err_msg' };
+    const action = gridFailureActions.loadHistGridFailureStationsFail(error);
+    const result = HistGridFailureStationsReducer(INITIAL_STATE, action);
+
+    expect(result).toEqual({
+      ...INITIAL_STATE,
+      failed: true,
+    });
+  });
+
+  it('getData return state.data', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getData(state);
+    expect(result).toBe(state.data);
+  });
+
+  it('getLoading return state.loading', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getLoading(state);
+    expect(result).toBe(state.loading);
+  });
+
+  it('getLoaded return state.loaded', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getLoaded(state);
+    expect(result).toBe(state.loaded);
+  });
+
+  it('getFailed return state.failed', () => {
+    const state = { ...INITIAL_STATE };
+    const result = getFailed(state);
+    expect(result).toBe(state.failed);
+  });
+});