Files
basic-erp/apps/web/src/app/features/documents/document-folio.spec.ts
T

125 lines
5.4 KiB
TypeScript

import { provideHttpClient } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { type ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute, Router, convertToParamMap, provideRouter } from '@angular/router';
import { of } from 'rxjs';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { DocumentFormPage } from './document-form.page';
import { hasFolio } from './document-layouts';
import { DOCUMENT_SCREENS } from './document-screens';
const invoice = (over: Record<string, unknown> = {}) => ({
'odata.etag': 'W/"5"',
DocEntry: 8,
DocNum: 108,
CardCode: 'P1',
CardName: 'Proveedor Uno',
FederalTaxID: '76543210-K',
NumAtCard: 'REF-1',
FolioPrefixString: 'F001',
FolioNumber: 198837,
DocDate: '2026-09-11T00:00:00Z',
DocDueDate: '2026-09-20T00:00:00Z',
DiscountPercent: 0,
Comments: '',
DocumentStatus: 'bost_Open',
Cancelled: 'tNO',
DocumentLines: [{ LineNum: 0, ItemCode: 'A1', ItemDescription: 'Pieza', Quantity: 1, Price: 10, DiscountPercent: 0, TaxCode: 'IVA', LineTotal: 10, WarehouseCode: '01' }],
...over,
});
describe('folio y RUT en los formularios', () => {
let fixture: ComponentFixture<DocumentFormPage>;
let ctrl: HttpTestingController;
const el = () => fixture.nativeElement as HTMLElement;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const page = () => fixture.componentInstance as any;
const tick = async () => {
fixture.detectChanges();
await new Promise((r) => setTimeout(r));
fixture.detectChanges();
};
const labels = () => [...el().querySelectorAll('label')].map((l) => l.textContent?.trim());
async function open(resource: string, doc: Record<string, unknown> | null) {
const screen = DOCUMENT_SCREENS.find((s) => s.resource === resource)!;
const params = doc ? { docEntry: '8' } : {};
const route = {
snapshot: { data: { screen, title: 'Documento' }, paramMap: convertToParamMap(params) },
paramMap: of(convertToParamMap(params)),
};
await TestBed.configureTestingModule({
imports: [DocumentFormPage],
providers: [provideRouter([]), provideHttpClient(), provideHttpClientTesting(), { provide: ActivatedRoute, useValue: route }],
}).compileComponents();
ctrl = TestBed.inject(HttpTestingController);
vi.spyOn(TestBed.inject(Router), 'navigate').mockResolvedValue(true);
fixture = TestBed.createComponent(DocumentFormPage);
await tick();
ctrl.expectOne((r) => r.url === '/api/sl/SalesTaxCodes').flush({ value: [{ Code: 'IVA', Rate: 19 }] });
if (doc) ctrl.expectOne(`/api/sl/${resource}/8`).flush(doc);
await tick();
}
beforeEach(() => TestBed.resetTestingModule());
it('lo llevan facturas, boletas, notas de crédito, entregas y recepciones (ventas y compras)', () => {
const withFolio = DOCUMENT_SCREENS.filter((s) => hasFolio(s.layout)).map((s) => s.path);
expect(withFolio.sort()).toEqual(
[
'/ventas/facturas', '/ventas/boletas', '/ventas/facturas-reserva', '/ventas/boletas-reserva', '/ventas/notas-credito', '/ventas/entrega',
'/compras/facturas', '/compras/notas-credito', '/compras/recepcion',
].sort(),
);
});
it('una factura muestra folio, número de folio, referencia y RUT', async () => {
await open('PurchaseInvoices', invoice());
expect(labels()).toEqual(expect.arrayContaining(['Folio', 'Nº referencia', 'RUT']));
const inputs = [...el().querySelectorAll<HTMLInputElement>('input')].map((i) => i.value);
expect(inputs).toEqual(expect.arrayContaining(['F001', '198837', 'REF-1', '76543210-K']));
});
it('una orden muestra referencia y RUT pero no el folio', async () => {
await open('Orders', invoice());
expect(labels()).toEqual(expect.arrayContaining(['Nº referencia', 'RUT']));
expect(labels()).not.toContain('Folio');
});
it('cambiar el folio envía el número como número', async () => {
await open('Invoices', invoice());
page().setHeader('FolioPrefixString', 'F002');
page().setHeader('FolioNumber', '200100');
await tick();
(el().querySelector('.actions .btn.main') as HTMLElement).click();
await tick();
const req = ctrl.expectOne((r) => r.method === 'PATCH');
expect(req.request.body).toEqual({ FolioPrefixString: 'F002', FolioNumber: 200100 });
req.flush(null);
await tick();
ctrl.expectOne('/api/sl/Invoices/8').flush(invoice());
});
it('un folio que no es numérico no se envía', async () => {
await open('Invoices', invoice());
page().setHeader('FolioNumber', '12ab');
await tick();
(el().querySelector('.actions .btn.main') as HTMLElement).click();
await tick();
ctrl.expectNone((r) => r.method === 'PATCH');
expect(el().querySelector('.status')?.textContent).toContain('folio debe ser numérico');
});
it('un documento nuevo sin folio no lo envía', async () => {
await open('Invoices', null);
page().setHeader('CardCode', 'C1');
page().setLines([{ ItemCode: 'A1', Quantity: 1, Price: 50, LineTotal: 50 }]);
await tick();
(el().querySelector('.actions .btn.main') as HTMLElement).click();
await tick();
const body = ctrl.expectOne((r) => r.method === 'POST' && !r.url.includes('SeriesService')).request.body as Record<string, unknown>;
expect(body).not.toHaveProperty('FolioNumber');
expect(body).not.toHaveProperty('FolioPrefixString');
});
});