Skip to content

Commit

Permalink
fix: error message in the checkout after basket has expired
Browse files Browse the repository at this point in the history
  • Loading branch information
SGrueber committed Jul 15, 2024
1 parent bc6b628 commit c3d4b79
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { RouterTestingModule } from '@angular/router/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { Action, Store } from '@ngrx/store';
import { cold, hot } from 'jasmine-marbles';
import { Observable, noop, of, throwError } from 'rxjs';
import { Observable, noop, of, throwError, toArray } from 'rxjs';
import { anything, instance, mock, verify, when } from 'ts-mockito';

import { BasketValidation } from 'ish-core/models/basket-validation/basket-validation.model';
Expand Down Expand Up @@ -50,6 +50,8 @@ describe('Basket Validation Effects', () => {
RouterTestingModule.withRoutes([
{ path: 'checkout', children: [{ path: 'address', children: [] }] },
{ path: 'checkout', children: [{ path: 'review', children: [] }] },
{ path: 'basket', children: [] },
{ path: '**', children: [] },
]),
],
providers: [
Expand Down Expand Up @@ -404,5 +406,51 @@ describe('Basket Validation Effects', () => {

expect(effects.validateBasketAndContinueCheckout$).toBeObservable(expected$);
});

describe('handleBasketNotFoundError$', () => {
it('should navigate to (empty) /basket after ContinueCheckoutFail if basket expired or could not be found', done => {
const action = continueCheckoutFail({
error: makeHttpError({ message: 'invalid', code: 'basket.not_found.error' }),
});
actions$ = of(action);

effects.handleBasketNotFoundError$.pipe(toArray()).subscribe({
next: actions => {
expect(actions).toMatchInlineSnapshot(`
[Basket API] Load Basket Fail:
error: {"name":"HttpErrorResponse","message":"invalid","code":"bask...
`);

expect(location.path()).toMatchInlineSnapshot(`"/basket?error=true"`);

done();
},
error: fail,
complete: noop,
});
});

it('should navigate to (empty) /basket after StartCheckoutFail if basket expired or could not be found', done => {
const action = startCheckoutFail({
error: makeHttpError({ message: 'invalid', code: 'basket.not_found.error' }),
});
actions$ = of(action);

effects.handleBasketNotFoundError$.pipe(toArray()).subscribe({
next: actions => {
expect(actions).toMatchInlineSnapshot(`
[Basket API] Load Basket Fail:
error: {"name":"HttpErrorResponse","message":"invalid","code":"bask...
`);

expect(location.path()).toMatchInlineSnapshot(`"/basket?error=true"`);

done();
},
error: fail,
complete: noop,
});
});
});
});
});
17 changes: 17 additions & 0 deletions src/app/core/store/customer/basket/basket-validation.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
continueCheckoutWithIssues,
loadBasketEligiblePaymentMethods,
loadBasketEligibleShippingMethods,
loadBasketFail,
startCheckout,
startCheckoutFail,
startCheckoutSuccess,
Expand Down Expand Up @@ -194,6 +195,22 @@ export class BasketValidationEffects {
)
);

// if the basket is expired or doesn't exist - clear the basket and go to cart page
handleBasketNotFoundError$ = createEffect(() =>
this.actions$.pipe(
ofType(startCheckoutFail, continueCheckoutFail),
mapToPayloadProperty('error'),
filter(error => error?.code === 'basket.not_found.error' || error?.errors[0]?.code === 'basket.not_found.error'),
concatMap(error =>
from(
this.router.navigate([this.validationSteps[CheckoutStepType.BeforeCheckout].route], {
queryParams: { error: true },
})
).pipe(map(() => loadBasketFail({ error })))
)
)
);

private extractScopes(elements: BasketFeedbackView[]): string[] {
return elements
?.filter(el => !!el.parameters?.scopes?.length)
Expand Down
8 changes: 7 additions & 1 deletion src/app/core/store/customer/basket/basket.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,13 @@ export const basketReducer = createReducer(
validationResults: initialValidationResults,
})
),

on(
loadBasketFail,
(state): BasketState => ({
...state,
basket: undefined,
})
),
on(
resetBasketErrors,
(state): BasketState => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ <h1 class="d-flex flex-wrap align-items-baseline">
<div>
<!-- Error message -->
<ish-error-message *ngIf="error?.message" [error]="error" />

<ish-basket-error-message [error]="error" />

<!-- Basket Info messages -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<!-- Error Message -->
<div *ngIf="error" class="col-md-12">
<ish-error-message [error]="error" [toast]="false" />
<ish-basket-error-message [error]="error" />
</div>

<div *ngIf="nextDisabled && !error" class="col-md-12">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CheckoutFacade } from 'ish-core/facades/checkout.facade';
import { makeHttpError } from 'ish-core/utils/dev/api-service-utils';
import { BasketMockData } from 'ish-core/utils/dev/basket-mock-data';
import { BasketCostSummaryComponent } from 'ish-shared/components/basket/basket-cost-summary/basket-cost-summary.component';
import { BasketErrorMessageComponent } from 'ish-shared/components/basket/basket-error-message/basket-error-message.component';
import { BasketItemsSummaryComponent } from 'ish-shared/components/basket/basket-items-summary/basket-items-summary.component';
import { BasketValidationResultsComponent } from 'ish-shared/components/basket/basket-validation-results/basket-validation-results.component';
import { BasketInvoiceAddressWidgetComponent } from 'ish-shared/components/checkout/basket-invoice-address-widget/basket-invoice-address-widget.component';
Expand All @@ -29,6 +30,7 @@ describe('Checkout Address Component', () => {
declarations: [
CheckoutAddressComponent,
MockComponent(BasketCostSummaryComponent),
MockComponent(BasketErrorMessageComponent),
MockComponent(BasketInvoiceAddressWidgetComponent),
MockComponent(BasketItemsSummaryComponent),
MockComponent(BasketShippingAddressWidgetComponent),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<div class="col-md-12">
<!-- Messages -->
<ish-error-message [error]="error" [toast]="false" />
<ish-basket-error-message [error]="error" />
<ish-basket-validation-results />

<div *ngIf="redirectStatus" role="alert" class="alert alert-danger">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { makeHttpError } from 'ish-core/utils/dev/api-service-utils';
import { BasketMockData } from 'ish-core/utils/dev/basket-mock-data';
import { BasketAddressSummaryComponent } from 'ish-shared/components/basket/basket-address-summary/basket-address-summary.component';
import { BasketCostSummaryComponent } from 'ish-shared/components/basket/basket-cost-summary/basket-cost-summary.component';
import { BasketErrorMessageComponent } from 'ish-shared/components/basket/basket-error-message/basket-error-message.component';
import { BasketItemsSummaryComponent } from 'ish-shared/components/basket/basket-items-summary/basket-items-summary.component';
import { BasketPromotionCodeComponent } from 'ish-shared/components/basket/basket-promotion-code/basket-promotion-code.component';
import { BasketValidationResultsComponent } from 'ish-shared/components/basket/basket-validation-results/basket-validation-results.component';
Expand All @@ -38,6 +39,7 @@ describe('Checkout Payment Component', () => {
CheckoutPaymentComponent,
MockComponent(BasketAddressSummaryComponent),
MockComponent(BasketCostSummaryComponent),
MockComponent(BasketErrorMessageComponent),
MockComponent(BasketItemsSummaryComponent),
MockComponent(BasketPromotionCodeComponent),
MockComponent(BasketValidationResultsComponent),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ <h1 class="d-flex flex-wrap align-items-baseline">
<!-- Error Message-->
<div class="col-md-12">
<ish-error-message [error]="error" [toast]="false" />
<ish-basket-error-message [error]="error" />
<div *ngIf="multipleBuckets" role="alert" class="alert alert-danger">
{{ 'checkout.shipping.no_methods.message' | translate }}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { findAllCustomElements } from 'ish-core/utils/dev/html-query-utils';
import { AddressComponent } from 'ish-shared/components/address/address/address.component';
import { BasketApprovalInfoComponent } from 'ish-shared/components/basket/basket-approval-info/basket-approval-info.component';
import { BasketCostSummaryComponent } from 'ish-shared/components/basket/basket-cost-summary/basket-cost-summary.component';
import { BasketErrorMessageComponent } from 'ish-shared/components/basket/basket-error-message/basket-error-message.component';
import { BasketMerchantMessageViewComponent } from 'ish-shared/components/basket/basket-merchant-message-view/basket-merchant-message-view.component';
import { BasketShippingMethodComponent } from 'ish-shared/components/basket/basket-shipping-method/basket-shipping-method.component';
import { BasketValidationResultsComponent } from 'ish-shared/components/basket/basket-validation-results/basket-validation-results.component';
Expand All @@ -40,6 +41,7 @@ describe('Checkout Review Component', () => {
MockComponent(AddressComponent),
MockComponent(BasketApprovalInfoComponent),
MockComponent(BasketCostSummaryComponent),
MockComponent(BasketErrorMessageComponent),
MockComponent(BasketMerchantMessageViewComponent),
MockComponent(BasketShippingMethodComponent),
MockComponent(BasketValidationResultsComponent),
Expand Down Expand Up @@ -113,6 +115,7 @@ describe('Checkout Review Component', () => {
[
"ish-modal-dialog-link",
"ish-error-message",
"ish-basket-error-message",
"ish-basket-validation-results",
"ish-basket-merchant-message-view",
"ish-info-box",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ <h1>{{ 'checkout.shipping.pagetitle' | translate }}</h1>
<div class="row">
<!-- Messages -->
<div class="col-md-12">
<ish-error-message [error]="basketError$ | async" [toast]="false" />
<ng-container *ngIf="basketError$ | async as error">
<ish-error-message [error]="error" [toast]="false" />
<ish-basket-error-message [error]="error" />
</ng-container>
<ish-basket-validation-results />
</div>
<!-- Shipping method form-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { makeHttpError } from 'ish-core/utils/dev/api-service-utils';
import { BasketMockData } from 'ish-core/utils/dev/basket-mock-data';
import { BasketAddressSummaryComponent } from 'ish-shared/components/basket/basket-address-summary/basket-address-summary.component';
import { BasketCostSummaryComponent } from 'ish-shared/components/basket/basket-cost-summary/basket-cost-summary.component';
import { BasketErrorMessageComponent } from 'ish-shared/components/basket/basket-error-message/basket-error-message.component';
import { BasketItemsSummaryComponent } from 'ish-shared/components/basket/basket-items-summary/basket-items-summary.component';
import { BasketMerchantMessageComponent } from 'ish-shared/components/basket/basket-merchant-message/basket-merchant-message.component';
import { BasketValidationResultsComponent } from 'ish-shared/components/basket/basket-validation-results/basket-validation-results.component';
Expand All @@ -33,6 +34,7 @@ describe('Checkout Shipping Page Component', () => {
CheckoutShippingPageComponent,
MockComponent(BasketAddressSummaryComponent),
MockComponent(BasketCostSummaryComponent),
MockComponent(BasketErrorMessageComponent),
MockComponent(BasketItemsSummaryComponent),
MockComponent(BasketMerchantMessageComponent),
MockComponent(BasketValidationResultsComponent),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div *ngIf="error && !toast" role="alert" class="alert alert-danger">
<div *ngIf="(error?.message || error?.code) && !toast" role="alert" class="alert alert-danger">
<span *ngIf="error.message; else translationMissing" [ishServerHtml]="error.message"></span>
<ng-template #translationMissing>
<span [ishServerHtml]="error.code | translate"></span>
Expand Down

0 comments on commit c3d4b79

Please sign in to comment.