Skip to content

Commit

Permalink
fix: "Add Quote to Cart" behaviour changed to only route on success a…
Browse files Browse the repository at this point in the history
…nd hide the button on error (#51)

- includes reset quote error functionality

closes #51
  • Loading branch information
Sebastian-Haehnlein authored and shauke committed Feb 19, 2020
1 parent 788b6dd commit a70da64
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 21 deletions.
5 changes: 5 additions & 0 deletions src/app/extensions/quoting/facades/quoting.facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
DeleteQuote,
LoadQuotes,
RejectQuote,
ResetQuoteError,
getCurrentQuotes,
getQuoteError,
getQuoteLoading,
Expand Down Expand Up @@ -74,6 +75,10 @@ export class QuotingFacade {
this.store.dispatch(new AddQuoteToBasket({ quoteId }));
}

resetQuoteError() {
this.store.dispatch(new ResetQuoteError());
}

// QUOTE REQUEST
quoteRequest$ = this.store.pipe(select(getSelectedQuoteRequestWithProducts));
quoteRequestLoading$ = this.store.pipe(select(getQuoteRequestLoading));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Location } from '@angular/common';
import { ComponentFixture, TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Store, combineReducers } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core';
Expand All @@ -20,7 +20,6 @@ describe('Quote Edit Page Component', () => {
let fixture: ComponentFixture<QuoteEditPageComponent>;
let element: HTMLElement;
let store$: Store<{}>;
let location: Location;

beforeEach(async(() => {
TestBed.configureTestingModule({
Expand Down Expand Up @@ -58,10 +57,4 @@ describe('Quote Edit Page Component', () => {
fixture.detectChanges();
expect(element.querySelector('ish-loading')).toBeTruthy();
});

it('should navigate to basket when addToBasket is clicked', fakeAsync(() => {
component.addQuoteToBasket(undefined);
tick(50);
expect(location.path()).toBe('/basket');
}));
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';

import { AccountFacade } from 'ish-core/facades/account.facade';
Expand All @@ -20,7 +19,7 @@ export class QuoteEditPageComponent implements OnInit {
quoteError$: Observable<HttpError>;
user$: Observable<User>;

constructor(private quotingFacade: QuotingFacade, private accountFacade: AccountFacade, private router: Router) {}
constructor(private quotingFacade: QuotingFacade, private accountFacade: AccountFacade) {}

ngOnInit() {
this.quote$ = this.quotingFacade.quote$;
Expand All @@ -39,6 +38,5 @@ export class QuoteEditPageComponent implements OnInit {

addQuoteToBasket(quoteId: string) {
this.quotingFacade.addQuoteToBasket(quoteId);
this.router.navigate(['/basket']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ <h3>{{ 'quote.items.table.heading' | translate }}</h3>

<!-- ELSE ( if type === Quote ) -->
<ng-container *ngIf="quote.type === 'Quote'">
<ng-container *ngIf="quote.state === 'Responded' && isQuoteValid">
<ng-container *ngIf="quote.state === 'Responded' && isQuoteValid && showAddQuoteToCartButton">
<button type="submit" class="btn btn-primary float-right" name="add2cart" (click)="addToBasket()">
{{ 'quote.edit.button.add_quote_to_cart.label' | translate }}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { MockComponent, MockDirective } from 'ng-mocks';
import { anything, capture, spy, verify } from 'ts-mockito';
import { anything, capture, instance, mock, spy, verify } from 'ts-mockito';

import { ServerHtmlDirective } from 'ish-core/directives/server-html.directive';
import { User } from 'ish-core/models/user/user.model';
Expand All @@ -14,6 +14,7 @@ import { LoadingComponent } from 'ish-shared/components/common/loading/loading.c
import { RecentlyViewedComponent } from 'ish-shared/components/recently/recently-viewed/recently-viewed.component';
import { InputComponent } from 'ish-shared/forms/components/input/input.component';

import { QuotingFacade } from '../../../facades/quoting.facade';
import { QuoteRequest } from '../../../models/quote-request/quote-request.model';
import { Quote } from '../../../models/quote/quote.model';
import { QuoteStateComponent } from '../quote-state/quote-state.component';
Expand All @@ -24,8 +25,10 @@ describe('Quote Edit Component', () => {
let fixture: ComponentFixture<QuoteEditComponent>;
let component: QuoteEditComponent;
let element: HTMLElement;
let quotingFacade: QuotingFacade;

beforeEach(async(() => {
quotingFacade = mock(QuotingFacade);
TestBed.configureTestingModule({
declarations: [
DatePipe,
Expand All @@ -39,6 +42,7 @@ describe('Quote Edit Component', () => {
QuoteEditComponent,
],
imports: [ReactiveFormsModule, RouterTestingModule, TranslateModule.forRoot()],
providers: [{ provide: QuotingFacade, useFactory: () => instance(quotingFacade) }],
}).compileComponents();
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
} from '@angular/core';
Expand All @@ -16,6 +17,7 @@ import { HttpError } from 'ish-core/models/http-error/http-error.model';
import { LineItemUpdate } from 'ish-core/models/line-item-update/line-item-update.model';
import { User } from 'ish-core/models/user/user.model';

import { QuotingFacade } from '../../../facades/quoting.facade';
import { QuoteRequest } from '../../../models/quote-request/quote-request.model';
import { Quote } from '../../../models/quote/quote.model';

Expand Down Expand Up @@ -45,7 +47,7 @@ import { Quote } from '../../../models/quote/quote.model';
templateUrl: './quote-edit.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class QuoteEditComponent implements OnChanges {
export class QuoteEditComponent implements OnChanges, OnInit {
@Input() quote: Quote | QuoteRequest;
@Input() user: User;
@Input() error: HttpError;
Expand All @@ -68,15 +70,22 @@ export class QuoteEditComponent implements OnChanges {
validToDate: number;
saved = false;
displaySavedMessage$: Observable<boolean>;
showAddQuoteToCartButton = true;

constructor(private router: Router) {
constructor(private router: Router, private quotingFacade: QuotingFacade) {
this.form = new FormGroup({
displayName: new FormControl(undefined, [Validators.maxLength(255)]),
description: new FormControl(undefined, []),
});
}

ngOnInit() {
this.quotingFacade.resetQuoteError();
}

ngOnChanges(c: SimpleChanges) {
this.setShowAddQuoteToCartButton(c);

const quote = this.quote as Quote;

this.sellerComment = quote.sellerComment;
Expand All @@ -90,6 +99,12 @@ export class QuoteEditComponent implements OnChanges {
this.toggleSaveMessage();
}

private setShowAddQuoteToCartButton(c: SimpleChanges) {
if (c.error && c.error.currentValue && !c.error.firstChange) {
this.showAddQuoteToCartButton = false;
}
}

private toggleSaveMessage() {
if (!this.submitted && this.saved && !this.error && this.quote.state === 'New') {
this.displaySavedMessage$ = merge(of(true), timer(5000).pipe(mapTo(false)));
Expand Down
8 changes: 7 additions & 1 deletion src/app/extensions/quoting/store/quote/quote.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export enum QuoteActionTypes {
AddQuoteToBasket = '[Basket] Add Quote To Basket',
AddQuoteToBasketFail = '[Basket API] Add Quote To Basket Fail',
AddQuoteToBasketSuccess = '[Basket API] Add Quote To Basket Success',
ResetQuoteError = '[Quote] Reset Quote Error',
}

export class SelectQuote implements Action {
Expand Down Expand Up @@ -102,6 +103,10 @@ export class AddQuoteToBasketSuccess implements Action {
constructor(public payload: { link: Link }) {}
}

export class ResetQuoteError implements Action {
readonly type = QuoteActionTypes.ResetQuoteError;
}

export type QuoteAction =
| SelectQuote
| LoadQuotes
Expand All @@ -118,4 +123,5 @@ export type QuoteAction =
| CreateQuoteRequestFromQuoteSuccess
| AddQuoteToBasket
| AddQuoteToBasketFail
| AddQuoteToBasketSuccess;
| AddQuoteToBasketSuccess
| ResetQuoteError;
26 changes: 21 additions & 5 deletions src/app/extensions/quoting/store/quote/quote.effects.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Location } from '@angular/common';
import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { Store, combineReducers } from '@ngrx/store';
import { cold, hot } from 'jest-marbles';
import { of, throwError } from 'rxjs';
import { noop, of, throwError } from 'rxjs';
import { anyString, anything, instance, mock, verify, when } from 'ts-mockito';

import { FeatureToggleModule } from 'ish-core/feature-toggle.module';
Expand Down Expand Up @@ -39,10 +40,11 @@ describe('Quote Effects', () => {
let basketServiceMock: BasketService;
let effects: QuoteEffects;
let store$: Store<{}>;
let location: Location;

const customer = { customerNo: 'CID', type: 'SMBCustomer' } as Customer;

beforeEach(() => {
beforeEach(async(() => {
quoteServiceMock = mock(QuoteService);
basketServiceMock = mock(BasketService);

Expand All @@ -53,7 +55,10 @@ describe('Quote Effects', () => {
declarations: [DummyComponent],
imports: [
FeatureToggleModule,
RouterTestingModule.withRoutes([{ path: 'account/quote-request/:quoteRequestId', component: DummyComponent }]),
RouterTestingModule.withRoutes([
{ path: 'account/quote-request/:quoteRequestId', component: DummyComponent },
{ path: 'basket', component: DummyComponent },
]),
ngrxTesting({
reducers: {
quoting: combineReducers(quotingReducers),
Expand All @@ -74,11 +79,12 @@ describe('Quote Effects', () => {

effects = TestBed.get(QuoteEffects);
store$ = TestBed.get(Store);
location = TestBed.get(Location);

store$.dispatch(new ApplyConfiguration({ features: ['quoting'] }));
store$.dispatch(new LoginUserSuccess({ customer }));
store$.dispatch(new LoadCompanyUserSuccess({ user: { email: 'test' } as User }));
});
}));

describe('loadQuotes$', () => {
beforeEach(() => {
Expand Down Expand Up @@ -377,4 +383,14 @@ describe('Quote Effects', () => {
expect(effects.addQuoteToBasket$).toBeObservable(expected$);
});
});

describe('gotoBasketAfterAddQuoteToBasketSuccess$', () => {
it('should navigate to basket when success', fakeAsync(() => {
const action = new quoteActions.AddQuoteToBasketSuccess({ link: {} as Link });
actions$ = of(action);
effects.gotoBasketAfterAddQuoteToBasketSuccess$.subscribe(noop, fail, noop);
tick(1000);
expect(location.path()).toBe('/basket');
}));
});
});
11 changes: 11 additions & 0 deletions src/app/extensions/quoting/store/quote/quote.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,15 @@ export class QuoteEffects {
ofType(actions.QuoteActionTypes.AddQuoteToBasketSuccess, actions.QuoteActionTypes.AddQuoteToBasketFail),
mapTo(new UpdateBasket({ update: { calculated: true } }))
);

/**
* Triggers a navigation to the basket if quote successfully added to the basket.
*/
@Effect({ dispatch: false })
gotoBasketAfterAddQuoteToBasketSuccess$ = this.actions$.pipe(
ofType(actions.QuoteActionTypes.AddQuoteToBasketSuccess),
tap(() => {
this.router.navigate(['/basket']);
})
);
}
7 changes: 7 additions & 0 deletions src/app/extensions/quoting/store/quote/quote.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ export function quoteReducer(state = initialState, action: QuoteAction): QuoteSt
loading: false,
};
}

case QuoteActionTypes.ResetQuoteError: {
return {
...state,
error: undefined,
};
}
}

return state;
Expand Down

0 comments on commit a70da64

Please sign in to comment.