test(catalog): cover global availability behavior

This commit is contained in:
2026-08-25 09:03:32 -03:00
parent 5273459b64
commit 72c80465e8
5 changed files with 98 additions and 11 deletions

View File

@@ -0,0 +1,59 @@
import { describe, expect, it } from 'vitest';
import { CatalogAvailability } from './catalog.interface';
import {
allowsCatalogAction,
combineCatalogAvailability,
createCatalogAvailability,
maximumCatalogQuantity,
} from './catalog-availability';
describe('catalog availability', () => {
it('represents hidden items without irrelevant actions or quantities', () => {
const availability = createCatalogAvailability(0);
expect(availability).toEqual({
state: 'hidden',
reasons: [
{
code: 'out_of_stock',
message: 'Este producto no tiene stock disponible.',
},
],
});
expect(allowsCatalogAction(availability, 'buy_now')).toBe(false);
expect(maximumCatalogQuantity(availability)).toBe(0);
});
it('intersects product and variant actions and quantities', () => {
const product: CatalogAvailability = {
state: 'visible',
maximum_quantity: 3,
allowed_actions: ['select_variant', 'change_quantity'],
reasons: [{ code: 'limited', message: 'Corregí la selección.' }],
};
const variant: CatalogAvailability = {
state: 'visible',
maximum_quantity: 2,
allowed_actions: ['change_quantity', 'add_to_cart'],
reasons: [],
};
expect(combineCatalogAvailability(product, variant)).toEqual({
state: 'visible',
maximum_quantity: 2,
allowed_actions: ['change_quantity'],
reasons: [{ code: 'limited', message: 'Corregí la selección.' }],
});
});
it('lets a hidden decision win composition', () => {
const availability = combineCatalogAvailability(
createCatalogAvailability(5),
createCatalogAvailability(0),
);
expect(availability.state).toBe('hidden');
expect(allowsCatalogAction(availability, 'add_to_cart')).toBe(false);
});
});

View File

@@ -193,6 +193,21 @@ describe('ProductDetailPageComponent', () => {
expect(fixture.componentInstance['selectedVariantMax']()).toBe(4);
});
it('stops presenting a product that becomes hidden during an availability refresh', async () => {
catalogServiceStub.getCatalogItem.mockReturnValue(
throwError(() => new HttpErrorResponse({ status: 404 })),
);
await configureTestingModule();
const fixture = TestBed.createComponent(ProductDetailPageComponent);
fixture.detectChanges();
TestBed.inject(CatalogAvailabilityService).notifyAvailabilityChanged();
fixture.detectChanges();
expect(fixture.componentInstance['product']()).toBeNull();
expect(fixture.nativeElement.textContent).toContain('Este producto ya no está disponible.');
});
it('shows error message if the resolver cannot load the product', async () => {
resolveProductError(PRODUCT_DETAIL_ERROR_MESSAGE);
await configureTestingModule();

View File

@@ -59,6 +59,20 @@ describe('ProductListComponent', () => {
) {
const getVariantOptions = vi.fn().mockReturnValue(
of({
variants: [
{
id: 401,
precio: '10000.00',
availability: createCatalogAvailability(1),
values: { tipo: '1', sector: '2', fila: '3', asiento: '4' },
},
{
id: 402,
precio: '12000.00',
availability: createCatalogAvailability(1),
values: { tipo: '1', sector: '2', fila: '3', asiento: '5' },
},
],
selectors: ['tipo', 'sector', 'fila', 'asiento'].map((key, index) => ({
key,
label: key,
@@ -76,7 +90,12 @@ describe('ProductListComponent', () => {
await TestBed.configureTestingModule({
imports: [ProductListComponent],
providers: [
{ provide: CatalogService, useValue: { getVariantOptions } },
{
provide: CatalogService,
useValue: {
withoutLoading: () => ({ getVariantOptions }),
},
},
{ provide: CartService, useValue: {} },
],
}).compileComponents();

View File

@@ -59,21 +59,15 @@ describe('ProductVerticalWithCartCardComponent', () => {
it('shows the backend availability message with the reusable tooltip', async () => {
const fixture = await createComponent();
fixture.componentRef.setInput('availability', {
subject: 'product',
state: 'visible',
maximum_quantity: 0,
restrictions: [
reasons: [
{
code: 'user_quota_reached',
message: 'Alcanzaste el cupo máximo permitido para este producto.',
},
],
capabilities: {
display: true,
select_variant: false,
change_quantity: false,
add_to_cart: false,
buy_now: false,
},
allowed_actions: [],
});
fixture.detectChanges();

View File

@@ -92,7 +92,7 @@ describe('VariantSelectorComponent', () => {
{
id: 2,
values: { talle: 'M' },
availability: { capabilities: { display: true, select_variant: false } },
availability: { state: 'visible', maximum_quantity: 0, allowed_actions: [], reasons: [] },
},
]);
fixture.detectChanges();