feat: add CatalogService and ProductDetailPageComponent with initial unit tests
This commit is contained in:
@@ -35,14 +35,9 @@ export class CatalogService {
|
||||
);
|
||||
}
|
||||
|
||||
getProducto(id: number, defaultVariantId?: number): Observable<ProductDetail> {
|
||||
const params =
|
||||
defaultVariantId === undefined
|
||||
? undefined
|
||||
: new HttpParams({ fromObject: { default_variant: defaultVariantId } });
|
||||
|
||||
getProducto(id: number): Observable<ProductDetail> {
|
||||
return this.http
|
||||
.get<ApiResponse<ProductDetail>>(`${this.tenantApiUrl}/productos/${id}`, { params })
|
||||
.get<ApiResponse<ProductDetail>>(`${this.tenantApiUrl}/productos/${id}`)
|
||||
.pipe(map((response) => response.data));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ describe('ProductDetailPageComponent', () => {
|
||||
};
|
||||
|
||||
let paramMapSubject: BehaviorSubject<any>;
|
||||
let queryParamMapSubject: BehaviorSubject<any>;
|
||||
let catalogServiceStub: any;
|
||||
let routerStub: any;
|
||||
|
||||
@@ -49,7 +48,6 @@ describe('ProductDetailPageComponent', () => {
|
||||
beforeEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
paramMapSubject = new BehaviorSubject(convertToParamMap({ id: '1' }));
|
||||
queryParamMapSubject = new BehaviorSubject(convertToParamMap({}));
|
||||
catalogServiceStub = {
|
||||
getProducto: vi.fn().mockReturnValue(of(mockProduct))
|
||||
};
|
||||
@@ -65,8 +63,7 @@ describe('ProductDetailPageComponent', () => {
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
paramMap: paramMapSubject.asObservable(),
|
||||
queryParamMap: queryParamMapSubject.asObservable()
|
||||
paramMap: paramMapSubject.asObservable()
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -88,7 +85,7 @@ describe('ProductDetailPageComponent', () => {
|
||||
|
||||
const element = fixture.nativeElement as HTMLElement;
|
||||
|
||||
expect(catalogServiceStub.getProducto).toHaveBeenCalledWith(1, undefined);
|
||||
expect(catalogServiceStub.getProducto).toHaveBeenCalledWith(1);
|
||||
|
||||
expect(element.querySelector('app-product-carousel')).not.toBeNull();
|
||||
expect(element.querySelector('.product-detail__title')?.textContent).toContain('Auriculares Bluetooth');
|
||||
@@ -108,25 +105,6 @@ describe('ProductDetailPageComponent', () => {
|
||||
expect(element.textContent).toContain('No pudimos cargar los detalles del producto.');
|
||||
});
|
||||
|
||||
it('passes default_variant from the query params when loading the product', async () => {
|
||||
queryParamMapSubject.next(convertToParamMap({ default_variant: '123' }));
|
||||
|
||||
await configureTestingModule();
|
||||
const fixture = TestBed.createComponent(ProductDetailPageComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(catalogServiceStub.getProducto).toHaveBeenCalledWith(1, 123);
|
||||
});
|
||||
|
||||
it('ignores an invalid default_variant query param', async () => {
|
||||
queryParamMapSubject.next(convertToParamMap({ default_variant: 'abc' }));
|
||||
|
||||
await configureTestingModule();
|
||||
const fixture = TestBed.createComponent(ProductDetailPageComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(catalogServiceStub.getProducto).toHaveBeenCalledWith(1, undefined);
|
||||
});
|
||||
|
||||
it('should use default variant images if present', async () => {
|
||||
const detailProduct: ProductDetail = {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { combineLatest, Subscription } from 'rxjs';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { CatalogService } from '../../../../core/services/catalog/catalog.service';
|
||||
import {
|
||||
@@ -97,17 +97,15 @@ export class ProductDetailPageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.routeSub = combineLatest([this.route.paramMap, this.route.queryParamMap]).subscribe(
|
||||
([params, queryParams]) => {
|
||||
const id = this.parseIntegerParam(params.get('id'));
|
||||
if (id === null) {
|
||||
this.error.set('ID de producto inválido');
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadProduct(id, this.parseIntegerParam(queryParams.get('default_variant')) ?? undefined);
|
||||
this.routeSub = this.route.paramMap.subscribe((params) => {
|
||||
const id = this.parseIntegerParam(params.get('id'));
|
||||
if (id === null) {
|
||||
this.error.set('ID de producto inválido');
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
this.loadProduct(id);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -117,13 +115,13 @@ export class ProductDetailPageComponent implements OnInit, OnDestroy {
|
||||
this.clearMeasurementTimer();
|
||||
}
|
||||
|
||||
private loadProduct(id: number, defaultVariantId?: number): void {
|
||||
private loadProduct(id: number): void {
|
||||
this.loading.set(true);
|
||||
this.error.set(null);
|
||||
this.product.set(null);
|
||||
|
||||
this.productSub?.unsubscribe();
|
||||
this.productSub = this.catalogService.getProducto(id, defaultVariantId).subscribe({
|
||||
this.productSub = this.catalogService.getProducto(id).subscribe({
|
||||
next: (prod) => {
|
||||
this.product.set(prod);
|
||||
this.quantity.set(1);
|
||||
|
||||
Reference in New Issue
Block a user