Skip to content

Commit

Permalink
feat(cart): create cart automatically for add cart item (#2493)
Browse files Browse the repository at this point in the history
  • Loading branch information
griest024 committed Jun 29, 2023
1 parent cc3db71 commit 88e5ef9
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 20 deletions.
57 changes: 45 additions & 12 deletions libs/cart/state/src/effects/cart-item.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import {
Observable,
of,
throwError,
} from 'rxjs';
import { TestScheduler } from 'rxjs/testing';

Expand All @@ -24,6 +25,7 @@ import {
import {
DaffCartItemServiceInterface,
DaffCartItemDriver,
DaffCartDriverResolveService,
} from '@daffodil/cart/driver';
import { DaffTestingCartDriverModule } from '@daffodil/cart/driver/testing';
import {
Expand Down Expand Up @@ -82,8 +84,11 @@ describe('@daffodil/cart/state | DaffCartItemEffects', () => {
let driverUpdateSpy: jasmine.Spy;
let driverDeleteSpy: jasmine.Spy;
let getCartIdSpy: jasmine.Spy;
let cartResolverSpy: jasmine.SpyObj<DaffCartDriverResolveService>;

beforeEach(() => {
cartResolverSpy = jasmine.createSpyObj('DaffCartDriverResolveService', ['getCartIdOrFail']);

TestBed.configureTestingModule({
imports: [
DaffTestingCartDriverModule.forRoot(),
Expand All @@ -98,6 +103,10 @@ describe('@daffodil/cart/state | DaffCartItemEffects', () => {
provide: DaffCartItemStateDebounceTime,
useValue: 4000,
},
{
provide: DaffCartDriverResolveService,
useValue: cartResolverSpy,
},
],
});

Expand Down Expand Up @@ -216,28 +225,52 @@ describe('@daffodil/cart/state | DaffCartItemEffects', () => {
mockCart.items = [];
});

describe('and the call to CartItemService is successful', () => {
describe('and the cart ID retrieval succeeds', () => {
beforeEach(() => {
mockCart.items.push(mockCartItem);
driverAddSpy.and.returnValue(of(mockCart));
const cartItemAddSuccessAction = new DaffCartItemAddSuccess(mockCart);
actions$ = hot('--a', { a: cartItemAddAction });
expected = cold('--b', { b: cartItemAddSuccessAction });
cartResolverSpy.getCartIdOrFail.and.returnValue(of(mockCart.id));
});

it('should dispatch a CartItemAddSuccess action', () => {
expect(effects.add$).toBeObservable(expected);
describe('and the call to CartItemService is successful', () => {
beforeEach(() => {
mockCart.items.push(mockCartItem);
driverAddSpy.and.returnValue(of(mockCart));
const cartItemAddSuccessAction = new DaffCartItemAddSuccess(mockCart);
actions$ = hot('--a', { a: cartItemAddAction });
expected = cold('--b', { b: cartItemAddSuccessAction });
});

it('should dispatch a CartItemAddSuccess action', () => {
expect(effects.add$).toBeObservable(expected);
});
});

describe('and the call to CartItemService fails', () => {
beforeEach(() => {
const error: DaffStateError = { code: 'code', recoverable: false, message: 'Failed to add cart item' };
const response = cold('#', {}, error);
driverAddSpy.and.returnValue(response);
const cartItemAddFailureAction = new DaffCartItemAddFailure(error);
actions$ = hot('--a', { a: cartItemAddAction });
expected = cold('--b', { b: cartItemAddFailureAction });
});

it('should dispatch a CartItemAddFailure action', () => {
expect(effects.add$).toBeObservable(expected);
});
});
});

describe('and the call to CartItemService fails', () => {
describe('and the cart ID retrieval fails', () => {
beforeEach(() => {
const error: DaffStateError = { code: 'code', recoverable: false, message: 'Failed to add cart item' };
const response = cold('#', {}, error);
driverAddSpy.and.returnValue(response);
const cartItemAddFailureAction = new DaffCartItemAddFailure(error);
actions$ = hot('--a', { a: cartItemAddAction });
expected = cold('--b', { b: cartItemAddFailureAction });
expected = cold('--(b|)', { b: cartItemAddFailureAction });
cartResolverSpy.getCartIdOrFail.and.returnValue(throwError(() => error));
});

it('should not try to add the item', () => {
expect(driverAddSpy).not.toHaveBeenCalled();
});

it('should dispatch a CartItemAddFailure action', () => {
Expand Down
35 changes: 27 additions & 8 deletions libs/cart/state/src/effects/cart-item.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
debounceTime,
mergeMap,
take,
concatMap,
} from 'rxjs/operators';

import {
Expand All @@ -31,8 +32,10 @@ import {
DAFF_CART_ERROR_MATCHER,
} from '@daffodil/cart';
import {
DaffCartDriverResolveService,
DaffCartItemDriver,
DaffCartItemServiceInterface,
daffCartDriverHandleCartNotFound,
} from '@daffodil/cart/driver';
import { ErrorTransformer } from '@daffodil/core/state';

Expand All @@ -50,13 +53,13 @@ import {
DaffCartItemList,
DaffCartItemListSuccess,
DaffCartItemListFailure,
DaffCartItemAdd,
DaffCartItemAddSuccess,
DaffCartItemAddFailure,
DaffCartItemStateReset,
DaffCartItemDeleteOutOfStock,
DaffCartItemDeleteOutOfStockSuccess,
DaffCartItemDeleteOutOfStockFailure,
DaffCartItemActions,
} from '../actions/public_api';
import { DaffCartItemStateDebounceTime } from '../injection-tokens/cart-item-state-debounce-time';
import { DaffStatefulCartItem } from '../models/public_api';
Expand All @@ -69,12 +72,13 @@ export class DaffCartItemEffects<
V extends DaffCart,
> {
constructor(
private actions$: Actions,
private actions$: Actions<DaffCartItemActions<T, U, V>>,
@Inject(DAFF_CART_ERROR_MATCHER) private errorMatcher: ErrorTransformer,
@Inject(DaffCartItemDriver) private driver: DaffCartItemServiceInterface<T, U, V>,
private storage: DaffCartStorageService,
@Inject(DaffCartItemStateDebounceTime) private cartItemStateDebounceTime: number,
private store: Store,
private cartResolver: DaffCartDriverResolveService,
) {}


Expand All @@ -99,18 +103,33 @@ export class DaffCartItemEffects<
),
));

private addCartItem$(
cartId: DaffCart['id'],
input: U,
) {
return this.driver.add(
cartId,
input,
).pipe(
map((resp: V) => new DaffCartItemAddSuccess(resp)),
catchError(error => of(new DaffCartItemAddFailure(this.errorMatcher(error)))),
);
}

add$ = createEffect(() => this.actions$.pipe(
ofType(DaffCartItemActionTypes.CartItemAddAction),
switchMap((action: DaffCartItemAdd<U>) =>
this.driver.add(
this.storage.getCartId(),
concatMap((action) => combineLatest([
of(action),
this.cartResolver.getCartIdOrFail(),
])),
mergeMap(([action, id]) =>
this.addCartItem$(
id,
action.input,
).pipe(
map((resp: V) => new DaffCartItemAddSuccess(resp)),
catchError(error => of(new DaffCartItemAddFailure(this.errorMatcher(error)))),
),
),
daffCartDriverHandleCartNotFound(this.storage),
catchError(error => of(new DaffCartItemAddFailure(this.errorMatcher(error)))),
));


Expand Down

0 comments on commit 88e5ef9

Please sign in to comment.