From 4ca9969cc841c089797a5b882fb16c1bbaadb1d3 Mon Sep 17 00:00:00 2001 From: kpawelczak <42094017+kpawelczak@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:54:26 +0200 Subject: [PATCH] fix: PostProduct review error is now normalized (#17810) --- .../assets/src/translations/en/product.ts | 2 + .../actions/product-references.action.ts | 2 +- .../store/actions/product-reviews.action.ts | 6 +-- .../effects/product-references.effect.ts | 14 ++++--- .../effects/product-reviews.effect.spec.ts | 38 ++++++++++--------- .../store/effects/product-reviews.effect.ts | 36 ++++++++++++++---- 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/projects/assets/src/translations/en/product.ts b/projects/assets/src/translations/en/product.ts index a22582bfd6d..3e324c5b76a 100644 --- a/projects/assets/src/translations/en/product.ts +++ b/projects/assets/src/translations/en/product.ts @@ -80,6 +80,8 @@ export const product = { less: 'Show Less Reviews', thankYouForReview: 'Thank you for the review! Note that reviews may require review before appearing here.', + postReviewFail: + 'Something went wrong while posting your review. Please try again later.', }, productCarousel: { carouselLabel: 'Carousel, {{title}}', diff --git a/projects/core/src/product/store/actions/product-references.action.ts b/projects/core/src/product/store/actions/product-references.action.ts index a823d671b1f..78feecbdfca 100644 --- a/projects/core/src/product/store/actions/product-references.action.ts +++ b/projects/core/src/product/store/actions/product-references.action.ts @@ -28,7 +28,7 @@ export class LoadProductReferences implements Action { export class LoadProductReferencesFail implements Action { readonly type = LOAD_PRODUCT_REFERENCES_FAIL; - constructor(public payload: ErrorModel) {} + constructor(public payload?: ErrorModel) {} } export class LoadProductReferencesSuccess implements Action { diff --git a/projects/core/src/product/store/actions/product-reviews.action.ts b/projects/core/src/product/store/actions/product-reviews.action.ts index a40d3851578..a2cd3e0234b 100644 --- a/projects/core/src/product/store/actions/product-reviews.action.ts +++ b/projects/core/src/product/store/actions/product-reviews.action.ts @@ -5,7 +5,7 @@ */ import { Action } from '@ngrx/store'; -import { ErrorModel } from '../../../model/misc.model'; +import { ErrorModel, HttpErrorModel } from '../../../model/misc.model'; import { Review } from '../../../model/product.model'; export const LOAD_PRODUCT_REVIEWS = '[Product] Load Product Reviews Data'; @@ -25,7 +25,7 @@ export class LoadProductReviews implements Action { export class LoadProductReviewsFail implements Action { readonly type = LOAD_PRODUCT_REVIEWS_FAIL; - constructor(public payload: ErrorModel) {} + constructor(public payload?: ErrorModel) {} } export class LoadProductReviewsSuccess implements Action { @@ -40,7 +40,7 @@ export class PostProductReview implements Action { export class PostProductReviewFail implements Action { readonly type = POST_PRODUCT_REVIEW_FAIL; - constructor(public payload: string) {} + constructor(public payload?: HttpErrorModel) {} } export class PostProductReviewSuccess implements Action { diff --git a/projects/core/src/product/store/effects/product-references.effect.ts b/projects/core/src/product/store/effects/product-references.effect.ts index 630a755d639..01f026fa708 100644 --- a/projects/core/src/product/store/effects/product-references.effect.ts +++ b/projects/core/src/product/store/effects/product-references.effect.ts @@ -4,16 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { Observable, of } from 'rxjs'; import { catchError, map, mergeMap } from 'rxjs/operators'; -import { ErrorModel } from '../../../model/misc.model'; import { ProductReferencesConnector } from '../../connectors/references/product-references.connector'; import { ProductActions } from '../actions/index'; +import { normalizeHttpError } from '../../../util/normalize-http-error'; +import { LoggerService } from '../../../logger'; @Injectable() export class ProductReferencesEffects { + protected logger = inject(LoggerService); loadProductReferences$: Observable< | ProductActions.LoadProductReferencesSuccess | ProductActions.LoadProductReferencesFail @@ -31,11 +33,11 @@ export class ProductReferencesEffects { list: data, }); }), - catchError((_error) => + catchError((error) => of( - new ProductActions.LoadProductReferencesFail({ - message: payload.productCode, - } as ErrorModel) + new ProductActions.LoadProductReferencesFail( + normalizeHttpError(error, this.logger) + ) ) ) ); diff --git a/projects/core/src/product/store/effects/product-reviews.effect.spec.ts b/projects/core/src/product/store/effects/product-reviews.effect.spec.ts index b2f0cc81c6c..ec8ac6a5bd9 100644 --- a/projects/core/src/product/store/effects/product-reviews.effect.spec.ts +++ b/projects/core/src/product/store/effects/product-reviews.effect.spec.ts @@ -9,12 +9,12 @@ import { import { cold, hot } from 'jasmine-marbles'; import { Observable, of } from 'rxjs'; import { Review } from '../../../model/product.model'; -import { defaultOccProductConfig } from '../../../occ/adapters/product/default-occ-product-config'; -import { OccConfig } from '../../../occ/config/occ-config'; import { ProductActions } from '../actions/index'; import * as fromEffects from '../effects/product-reviews.effect'; -import { ProductReviewsConnector } from '../../connectors/index'; +import { defaultOccProductConfig } from '../../../occ/adapters/product/default-occ-product-config'; import createSpy = jasmine.createSpy; +import { OccConfig } from '../../../occ/config/occ-config'; +import { ProductReviewsConnector } from '../../connectors/reviews/product-reviews.connector'; const reviewData: Review[] = [ { @@ -27,21 +27,13 @@ const reviewData: Review[] = [ }, ]; -const MockOccModuleConfig: OccConfig = { - backend: { - occ: { - baseUrl: '', - prefix: '', - }, - }, -}; +class GlobalMessageServiceMock { + add(_message: GlobalMessage): void {} +} class MockProductReviewsConnector { get = createSpy('getList').and.returnValue(of(reviewData)); -} - -class GlobalMessageServiceMock { - add(_message: GlobalMessage): void {} + add = createSpy('addReview').and.returnValue(of({})); } describe('Product reviews effect', () => { @@ -56,7 +48,6 @@ describe('Product reviews effect', () => { provide: ProductReviewsConnector, useClass: MockProductReviewsConnector, }, - { provide: OccConfig, useValue: MockOccModuleConfig }, { provide: OccConfig, useValue: defaultOccProductConfig }, fromEffects.ProductReviewsEffects, provideMockActions(() => actions$), @@ -68,7 +59,7 @@ describe('Product reviews effect', () => { }); describe('loadProductReviews$', () => { - it('should return specified product reviews', () => { + it('should return specified product reviews on success', () => { const productCode = '12345'; const action = new ProductActions.LoadProductReviews(productCode); const completion = new ProductActions.LoadProductReviewsSuccess({ @@ -82,4 +73,17 @@ describe('Product reviews effect', () => { expect(effects.loadProductReviews$).toBeObservable(expected); }); }); + + describe('postProductReview', () => { + it('should post a product review and return success action on success', () => { + const reviewPayload = { productCode: '12345', review: {} }; + const action = new ProductActions.PostProductReview(reviewPayload); + const completion = new ProductActions.PostProductReviewSuccess({}); + + actions$ = hot('-a', { a: action }); + const expected = cold('-b', { b: completion }); + + expect(effects.postProductReview).toBeObservable(expected); + }); + }); }); diff --git a/projects/core/src/product/store/effects/product-reviews.effect.ts b/projects/core/src/product/store/effects/product-reviews.effect.ts index c9aad4da941..81b1cfdd3bf 100644 --- a/projects/core/src/product/store/effects/product-reviews.effect.ts +++ b/projects/core/src/product/store/effects/product-reviews.effect.ts @@ -4,20 +4,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { Observable, of } from 'rxjs'; import { catchError, map, mergeMap, tap } from 'rxjs/operators'; -import { ErrorModel } from '../../../model/misc.model'; import { ProductReviewsConnector } from '../../connectors/reviews/product-reviews.connector'; import { ProductActions } from '../actions/index'; import { GlobalMessageService, GlobalMessageType, } from '../../../global-message/index'; +import { normalizeHttpError } from '../../../util/normalize-http-error'; +import { LoggerService } from '../../../logger'; @Injectable() export class ProductReviewsEffects { + protected logger = inject(LoggerService); loadProductReviews$: Observable< | ProductActions.LoadProductReviewsSuccess | ProductActions.LoadProductReviewsFail @@ -33,11 +35,11 @@ export class ProductReviewsEffects { list: data, }); }), - catchError((_error) => + catchError((error) => of( - new ProductActions.LoadProductReviewsFail({ - message: productCode, - } as ErrorModel) + new ProductActions.LoadProductReviewsFail( + normalizeHttpError(error, this.logger) + ) ) ) ); @@ -61,8 +63,12 @@ export class ProductReviewsEffects { reviewResponse ); }), - catchError((_error) => - of(new ProductActions.PostProductReviewFail(payload.productCode)) + catchError((error) => + of( + new ProductActions.PostProductReviewFail( + normalizeHttpError(error, this.logger) + ) + ) ) ); }) @@ -83,6 +89,20 @@ export class ProductReviewsEffects { { dispatch: false } ); + showGlobalMessageOnPostProductReviewFail$ = createEffect( + () => + this.actions$.pipe( + ofType(ProductActions.POST_PRODUCT_REVIEW_FAIL), + tap(() => { + this.globalMessageService.add( + { key: 'productReview.postReviewFail' }, + GlobalMessageType.MSG_TYPE_ERROR + ); + }) + ), + { dispatch: false } + ); + constructor( private actions$: Actions, private productReviewsConnector: ProductReviewsConnector,