From 4c7a7a1a4c0e1948ac2bb57d19285b66a10de79b Mon Sep 17 00:00:00 2001 From: Henry Taeschner Date: Sat, 2 Mar 2024 09:34:19 +0100 Subject: [PATCH] fix: added exceptionKey handling --- .../app-search/app-search.component.html | 9 + .../app-search/app-search.component.spec.ts | 5 +- .../app-search/app-search.component.ts | 4 +- .../product-search.component.html | 201 +++++++++--------- .../product-search.component.spec.ts | 74 ++++++- .../product-search.component.ts | 14 +- 6 files changed, 191 insertions(+), 116 deletions(-) diff --git a/src/app/product-store/app-search/app-search.component.html b/src/app/product-store/app-search/app-search.component.html index 99840be..2a0c069 100644 --- a/src/app/product-store/app-search/app-search.component.html +++ b/src/app/product-store/app-search/app-search.component.html @@ -57,7 +57,16 @@ +
+ +
{ beforeEach(() => { fixture = TestBed.createComponent(AppSearchComponent) component = fixture.componentInstance - fixture.detectChanges() - apiMfeServiceSpy.searchMicrofrontends.and.returnValue(of({} as MicrofrontendPageResult)) - apiMsServiceSpy.searchMicroservice.and.returnValue(of({} as MicroservicePageResult)) + // fixture.detectChanges() + fixture.componentInstance.ngOnInit() // solved ExpressionChangedAfterItHasBeenCheckedError }) afterEach(() => { diff --git a/src/app/product-store/app-search/app-search.component.ts b/src/app/product-store/app-search/app-search.component.ts index 09dcffe..80791e4 100644 --- a/src/app/product-store/app-search/app-search.component.ts +++ b/src/app/product-store/app-search/app-search.component.ts @@ -34,7 +34,7 @@ export type ChangeMode = 'VIEW' | 'CREATE' | 'EDIT' | 'COPY' export class AppSearchComponent implements OnInit, OnDestroy { private readonly destroy$ = new Subject() private readonly debug = true // to be removed after finalization - public exceptionKey = '' + public exceptionKey: string | undefined public loading = true public actions$: Observable | undefined @@ -180,7 +180,7 @@ export class AppSearchComponent implements OnInit, OnDestroy { public searchApps(): void { this.searchInProgress = true - this.exceptionKey = '' + this.exceptionKey = undefined switch (this.appSearchCriteriaGroup.controls['appType'].value) { case 'ALL': this.apps$ = combineLatest([this.searchMfes(), this.searchMss()]).pipe( diff --git a/src/app/product-store/product-search/product-search.component.html b/src/app/product-store/product-search/product-search.component.html index 3cfa56a..c2f11b8 100644 --- a/src/app/product-store/product-search/product-search.component.html +++ b/src/app/product-store/product-search/product-search.component.html @@ -28,120 +28,119 @@ -
+
- - - - - - -
-
-
- -
+ + + + + +
+
+
+
-
-
-
- {{ limitText(product.displayName, 100) }} -
-
- {{ limitText(product.name, 100) }} -
+
+
+
+
+ {{ limitText(product.displayName, 100) }} +
+
+ {{ limitText(product.name, 100) }}
- - -
-
-
- +
+ + +
+
+
+ +
+
+
+ {{ limitText(product.displayName, 20) }}
-
-
- {{ limitText(product.displayName, 20) }} -
-
- {{ limitText(product.name, 25) }} -
+
+ {{ limitText(product.name, 25) }}
- - - +
+ + diff --git a/src/app/product-store/product-search/product-search.component.spec.ts b/src/app/product-store/product-search/product-search.component.spec.ts index b705aee..e824238 100644 --- a/src/app/product-store/product-search/product-search.component.spec.ts +++ b/src/app/product-store/product-search/product-search.component.spec.ts @@ -3,9 +3,10 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing' import { HttpClientTestingModule } from '@angular/common/http/testing' import { RouterTestingModule } from '@angular/router/testing' import { Router } from '@angular/router' -import { of } from 'rxjs' +import { of, throwError } from 'rxjs' import { DataViewModule } from 'primeng/dataview' import { TranslateTestingModule } from 'ngx-translate-testing' +import { Product, ProductPageResult, ProductsAPIService } from 'src/app/shared/generated' import { ProductSearchComponent } from './product-search.component' @@ -14,7 +15,16 @@ describe('ProductSearchComponent', () => { let fixture: ComponentFixture let router: Router + const product: Product = { + id: 'id', + name: 'name', + basePath: 'basePath', + displayName: 'displayName' + } const translateServiceSpy = jasmine.createSpyObj('TranslateService', ['get']) + const apiProductServiceSpy = { + searchProducts: jasmine.createSpy('searchProducts').and.returnValue(of({ stream: [] })) + } beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -28,15 +38,21 @@ describe('ProductSearchComponent', () => { en: require('src/assets/i18n/en.json') }).withDefaultLanguage('en') ], + providers: [{ provide: ProductsAPIService, useValue: apiProductServiceSpy }], schemas: [NO_ERRORS_SCHEMA] }).compileComponents() })) - beforeEach(() => { + beforeEach(async () => { fixture = TestBed.createComponent(ProductSearchComponent) component = fixture.componentInstance router = TestBed.inject(Router) - fixture.detectChanges() + //fixture.detectChanges() + fixture.componentInstance.ngOnInit() // solved ExpressionChangedAfterItHasBeenCheckedError + }) + + afterEach(() => { + apiProductServiceSpy.searchProducts.calls.reset(), translateServiceSpy.get.calls.reset() }) it('should create', () => { @@ -93,13 +109,57 @@ describe('ProductSearchComponent', () => { expect(component.sortOrder).toEqual(1) }) - it('should call loadProducts onSearch', () => { - translateServiceSpy.get.and.returnValue(of({ 'ACTIONS.CREATE.LABEL': 'Create' })) - spyOn(component, 'searchProducts') + it('should search products - successful found', (done) => { + apiProductServiceSpy.searchProducts.and.returnValue(of({ stream: [product] } as ProductPageResult)) + + component.onSearch() + + component.products$.subscribe({ + next: (result) => { + if (result.stream) { + expect(result.stream.length).toBe(1) + result.stream.forEach((product) => { + expect(product.id).toEqual('id') + }) + } + done() + }, + error: done.fail + }) + }) + + it('should search products - successful not found', (done) => { + apiProductServiceSpy.searchProducts.and.returnValue(of({ stream: [] } as ProductPageResult)) + + component.onSearch() + + component.products$.subscribe({ + next: (result) => { + if (result.stream) { + expect(result.stream.length).toBe(0) + } + done() + }, + error: done.fail + }) + }) + + it('should search products - failed', (done) => { + const err = { status: 403 } + apiProductServiceSpy.searchProducts.and.returnValue(throwError(() => err)) component.onSearch() - expect(component.searchProducts).toHaveBeenCalled() + component.products$.subscribe({ + next: (result) => { + if (result.stream) { + expect(result.stream.length).toBe(0) + expect(component.exceptionKey).toEqual('EXCEPTIONS.HTTP_STATUS_403.PRODUCTS') + } + done() + }, + error: done.fail + }) }) it('should reset productSearchCriteriaGroup onSearchReset', () => { diff --git a/src/app/product-store/product-search/product-search.component.ts b/src/app/product-store/product-search/product-search.component.ts index f40ba78..6793dd3 100644 --- a/src/app/product-store/product-search/product-search.component.ts +++ b/src/app/product-store/product-search/product-search.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { FormControl, FormGroup } from '@angular/forms' -import { Observable, finalize, map } from 'rxjs' +import { finalize, map, of, Observable, catchError } from 'rxjs' import { TranslateService } from '@ngx-translate/core' import { DataView } from 'primeng/dataview' @@ -19,6 +19,8 @@ export interface ProductSearchCriteria { styleUrls: ['./product-search.component.scss'] }) export class ProductSearchComponent implements OnInit { + public exceptionKey: string | undefined + public searchInProgress = false public products$!: Observable public productSearchCriteriaGroup!: FormGroup public actions$: Observable | undefined @@ -26,7 +28,6 @@ export class ProductSearchComponent implements OnInit { public filter: string | undefined public sortField = 'name' public sortOrder = 1 - public searchInProgress = false public limitText = limitText public dataViewControlsTranslations: DataViewControlTranslations = {} @@ -56,7 +57,14 @@ export class ProductSearchComponent implements OnInit { .searchProducts({ productSearchCriteria: { name: this.productSearchCriteriaGroup.controls['productName'].value, pageSize: 1000 } }) - .pipe(finalize(() => (this.searchInProgress = false))) + .pipe( + catchError((err) => { + this.exceptionKey = 'EXCEPTIONS.HTTP_STATUS_' + err.status + '.PRODUCTS' + console.error('searchProducts():', err) + return of({ stream: [] } as ProductPageResult) + }), + finalize(() => (this.searchInProgress = false)) + ) } private prepareDialogTranslations(): void {