test(fin): cobertura de catálogos, conceptos y emisor
Backend: los 8 endpoints de catálogo responden 200 con las semillas exactas y filtran por búsqueda; tax-regimes acota por tipo de persona; ninguna ruta de catálogo acepta escritura (405); sync_catalogs es idempotente. CRUD de conceptos, conflicto 409 por clave ProdServ repetida en la misma empresa, la misma clave permitida en otra empresa, la baja lógica liberándola, aislamiento multi-tenant, upsert del emisor sin duplicar filas y RFC inválido rechazado. También que una partida con concept_id hereda la descripción y que las facturas sin claves del SAT siguen listándose y generando PDF. El fixture de pruebas siembra los catálogos con la misma función que usa la migración, sobre el schema sat mapeado a SQLite. Frontend: prueba del cacheo del cliente de catálogos. RFC dummy XAXX010101000 en todas las pruebas: sin datos reales. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
62
frontend/src/lib/api/fin/catalogs.test.ts
Normal file
62
frontend/src/lib/api/fin/catalogs.test.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const get = vi.fn();
|
||||
|
||||
// El cliente de catálogos solo usa `api.get`; se sustituye para contar peticiones.
|
||||
vi.mock('$lib/api', () => ({ api: { get } }));
|
||||
|
||||
const { satCatalogsAPI, clearCatalogCache } = await import('./catalogs');
|
||||
|
||||
const COMPANY_ID = 1;
|
||||
const PAYMENT_FORMS = [
|
||||
{ id: 1, code: '01', description: 'Efectivo', is_active: true },
|
||||
{ id: 2, code: '03', description: 'Transferencia electrónica de fondos', is_active: true }
|
||||
];
|
||||
|
||||
describe('satCatalogsAPI — cacheo en memoria', () => {
|
||||
beforeEach(() => {
|
||||
clearCatalogCache();
|
||||
get.mockReset();
|
||||
get.mockResolvedValue({ data: PAYMENT_FORMS, status: 200 });
|
||||
});
|
||||
|
||||
it('consulta el backend la primera vez y reusa el cache después', async () => {
|
||||
const first = await satCatalogsAPI.paymentForms(COMPANY_ID);
|
||||
const second = await satCatalogsAPI.paymentForms(COMPANY_ID);
|
||||
|
||||
expect(first).toEqual(PAYMENT_FORMS);
|
||||
expect(second).toBe(first); // misma referencia: vino del cache
|
||||
expect(get).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('cachea por separado cada combinación de parámetros', async () => {
|
||||
await satCatalogsAPI.paymentForms(COMPANY_ID);
|
||||
await satCatalogsAPI.paymentForms(COMPANY_ID, { search: 'transferencia' });
|
||||
await satCatalogsAPI.paymentForms(COMPANY_ID, { search: 'transferencia' });
|
||||
|
||||
expect(get).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('no comparte cache entre compañías', async () => {
|
||||
await satCatalogsAPI.paymentForms(COMPANY_ID);
|
||||
await satCatalogsAPI.paymentForms(2);
|
||||
|
||||
expect(get).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('clearCatalogCache obliga a volver a consultar', async () => {
|
||||
await satCatalogsAPI.paymentForms(COMPANY_ID);
|
||||
clearCatalogCache();
|
||||
await satCatalogsAPI.paymentForms(COMPANY_ID);
|
||||
|
||||
expect(get).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('propaga el error del backend y no lo cachea', async () => {
|
||||
get.mockResolvedValueOnce({ error: 'Falla del servidor', status: 500 });
|
||||
await expect(satCatalogsAPI.taxRegimes(COMPANY_ID)).rejects.toThrow('Falla del servidor');
|
||||
|
||||
await satCatalogsAPI.taxRegimes(COMPANY_ID);
|
||||
expect(get).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user