feat(cart): notify catalog availability changes
This commit is contained in:
@@ -7,11 +7,13 @@ import { CartService } from './cart.service';
|
|||||||
import { TenantService } from '../tenant.service';
|
import { TenantService } from '../tenant.service';
|
||||||
import { Cart } from './cart.interface';
|
import { Cart } from './cart.interface';
|
||||||
import { LOADING_MODE } from '../global-loading/loading-mode';
|
import { LOADING_MODE } from '../global-loading/loading-mode';
|
||||||
|
import { CatalogAvailabilityService } from '../catalog/catalog-availability.service';
|
||||||
|
|
||||||
describe('CartService', () => {
|
describe('CartService', () => {
|
||||||
let service: CartService;
|
let service: CartService;
|
||||||
let httpMock: HttpTestingController;
|
let httpMock: HttpTestingController;
|
||||||
let tenantServiceMock: any;
|
let tenantServiceMock: any;
|
||||||
|
let catalogAvailabilityService: CatalogAvailabilityService;
|
||||||
|
|
||||||
const mockCart: Cart = {
|
const mockCart: Cart = {
|
||||||
id: 123,
|
id: 123,
|
||||||
@@ -53,6 +55,7 @@ describe('CartService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
service = TestBed.inject(CartService);
|
service = TestBed.inject(CartService);
|
||||||
|
catalogAvailabilityService = TestBed.inject(CatalogAvailabilityService);
|
||||||
httpMock = TestBed.inject(HttpTestingController);
|
httpMock = TestBed.inject(HttpTestingController);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,6 +104,9 @@ describe('CartService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should add item and update signal', () => {
|
it('should add item and update signal', () => {
|
||||||
|
const availabilityChanged = vi.fn();
|
||||||
|
catalogAvailabilityService.availabilityChanged$.subscribe(availabilityChanged);
|
||||||
|
|
||||||
service.addItem(5, 10, 2).subscribe((res) => {
|
service.addItem(5, 10, 2).subscribe((res) => {
|
||||||
expect(res.data).toEqual(mockCart);
|
expect(res.data).toEqual(mockCart);
|
||||||
expect(service.cart()).toEqual(mockCart);
|
expect(service.cart()).toEqual(mockCart);
|
||||||
@@ -115,9 +121,13 @@ describe('CartService', () => {
|
|||||||
});
|
});
|
||||||
expect(req.request.withCredentials).toBe(true);
|
expect(req.request.withCredentials).toBe(true);
|
||||||
req.flush({ data: mockCart });
|
req.flush({ data: mockCart });
|
||||||
|
expect(availabilityChanged).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update item quantity and update signal', () => {
|
it('should update item quantity and update signal', () => {
|
||||||
|
const availabilityChanged = vi.fn();
|
||||||
|
catalogAvailabilityService.availabilityChanged$.subscribe(availabilityChanged);
|
||||||
|
|
||||||
const updatedCart = { ...mockCart, subtotal: '30.00' };
|
const updatedCart = { ...mockCart, subtotal: '30.00' };
|
||||||
updatedCart.items[0].cantidad = 3;
|
updatedCart.items[0].cantidad = 3;
|
||||||
|
|
||||||
@@ -131,9 +141,13 @@ describe('CartService', () => {
|
|||||||
expect(req.request.body).toEqual({ cantidad: 3 });
|
expect(req.request.body).toEqual({ cantidad: 3 });
|
||||||
expect(req.request.withCredentials).toBe(true);
|
expect(req.request.withCredentials).toBe(true);
|
||||||
req.flush({ data: updatedCart });
|
req.flush({ data: updatedCart });
|
||||||
|
expect(availabilityChanged).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove item and update signal', () => {
|
it('should remove item and update signal', () => {
|
||||||
|
const availabilityChanged = vi.fn();
|
||||||
|
catalogAvailabilityService.availabilityChanged$.subscribe(availabilityChanged);
|
||||||
|
|
||||||
const emptyCart: Cart = {
|
const emptyCart: Cart = {
|
||||||
id: 123,
|
id: 123,
|
||||||
tenant_codigo: 'acme',
|
tenant_codigo: 'acme',
|
||||||
@@ -151,5 +165,18 @@ describe('CartService', () => {
|
|||||||
expect(req.request.method).toBe('DELETE');
|
expect(req.request.method).toBe('DELETE');
|
||||||
expect(req.request.withCredentials).toBe(true);
|
expect(req.request.withCredentials).toBe(true);
|
||||||
req.flush({ data: emptyCart });
|
req.flush({ data: emptyCart });
|
||||||
|
expect(availabilityChanged).toHaveBeenCalledOnce();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not notify an availability change when a cart mutation fails', () => {
|
||||||
|
const availabilityChanged = vi.fn();
|
||||||
|
catalogAvailabilityService.availabilityChanged$.subscribe(availabilityChanged);
|
||||||
|
|
||||||
|
service.removeItem(10).subscribe({ error: vi.fn() });
|
||||||
|
|
||||||
|
const req = httpMock.expectOne('http://api.test/tenants/acme/cart/items/10');
|
||||||
|
req.flush({ message: 'Error' }, { status: 500, statusText: 'Server Error' });
|
||||||
|
|
||||||
|
expect(availabilityChanged).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { catchError, map, Observable, tap } from 'rxjs';
|
|||||||
|
|
||||||
import { ApiResponse } from '../api-response.interface';
|
import { ApiResponse } from '../api-response.interface';
|
||||||
import { BaseApiService } from '../base-api.service';
|
import { BaseApiService } from '../base-api.service';
|
||||||
|
import { CatalogAvailabilityService } from '../catalog/catalog-availability.service';
|
||||||
import { TenantService } from '../tenant.service';
|
import { TenantService } from '../tenant.service';
|
||||||
import { Cart } from './cart.interface';
|
import { Cart } from './cart.interface';
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ import { Cart } from './cart.interface';
|
|||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class CartService extends BaseApiService {
|
export class CartService extends BaseApiService {
|
||||||
|
private readonly catalogAvailabilityService = inject(CatalogAvailabilityService);
|
||||||
private readonly tenantService = inject(TenantService);
|
private readonly tenantService = inject(TenantService);
|
||||||
|
|
||||||
private readonly cartState = signal<Cart | null>(null);
|
private readonly cartState = signal<Cart | null>(null);
|
||||||
@@ -60,6 +62,7 @@ export class CartService extends BaseApiService {
|
|||||||
.pipe(
|
.pipe(
|
||||||
tap((response) => {
|
tap((response) => {
|
||||||
this.cartState.set(response.data);
|
this.cartState.set(response.data);
|
||||||
|
this.catalogAvailabilityService.notifyAvailabilityChanged();
|
||||||
this.isUpdatingState.set(false);
|
this.isUpdatingState.set(false);
|
||||||
}),
|
}),
|
||||||
catchError((error) => {
|
catchError((error) => {
|
||||||
@@ -93,6 +96,7 @@ export class CartService extends BaseApiService {
|
|||||||
.pipe(
|
.pipe(
|
||||||
tap((response) => {
|
tap((response) => {
|
||||||
this.cartState.set(response.data);
|
this.cartState.set(response.data);
|
||||||
|
this.catalogAvailabilityService.notifyAvailabilityChanged();
|
||||||
this.isUpdatingState.set(false);
|
this.isUpdatingState.set(false);
|
||||||
}),
|
}),
|
||||||
catchError((error) => {
|
catchError((error) => {
|
||||||
@@ -111,6 +115,7 @@ export class CartService extends BaseApiService {
|
|||||||
.pipe(
|
.pipe(
|
||||||
tap((response) => {
|
tap((response) => {
|
||||||
this.cartState.set(response.data);
|
this.cartState.set(response.data);
|
||||||
|
this.catalogAvailabilityService.notifyAvailabilityChanged();
|
||||||
this.isUpdatingState.set(false);
|
this.isUpdatingState.set(false);
|
||||||
}),
|
}),
|
||||||
catchError((error) => {
|
catchError((error) => {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class CatalogAvailabilityService {
|
||||||
|
private readonly availabilityChangedSubject = new Subject<void>();
|
||||||
|
|
||||||
|
readonly availabilityChanged$: Observable<void> = this.availabilityChangedSubject.asObservable();
|
||||||
|
|
||||||
|
notifyAvailabilityChanged(): void {
|
||||||
|
this.availabilityChangedSubject.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user