feat(clientes-maestro): importar y exportar clientes del archivo maestro
- Tabla ClienteMaestro (27 campos, unique numCliente) - Importador Excel: 1535 clientes del Reporte maestro - API: listar/filtros/exportar/detalle/importar - Frontend: tabla paginada, filtros, exportar Excel - Dark mode completo, 52 tests verdes
This commit is contained in:
134
api-gateway/src/controllers/cliente-maestro.controller.test.ts
Normal file
134
api-gateway/src/controllers/cliente-maestro.controller.test.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { Request, Response } from 'express'
|
||||
|
||||
// ---------- Servicio mockeado ----------
|
||||
const servicioMock = vi.hoisted(() => ({
|
||||
listar: vi.fn(),
|
||||
obtener: vi.fn(),
|
||||
contar: vi.fn(),
|
||||
exportar: vi.fn(),
|
||||
importarDesdeExcel: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('../services/cliente-maestro.service.js', () => servicioMock)
|
||||
|
||||
import {
|
||||
listarEndpoint,
|
||||
exportarEndpoint,
|
||||
obtenerEndpoint,
|
||||
importarEndpoint,
|
||||
} from './cliente-maestro.controller.js'
|
||||
|
||||
function reqFake(overrides: Partial<Request> = {}): Request {
|
||||
return {
|
||||
body: {},
|
||||
params: {},
|
||||
query: {},
|
||||
usuarioToken: { sub: 'u-1', username: 'admin', rol: 'admin' },
|
||||
...overrides,
|
||||
} as Request
|
||||
}
|
||||
|
||||
function resFake() {
|
||||
const json = vi.fn()
|
||||
const end = vi.fn()
|
||||
const status = vi.fn().mockReturnValue({ json, end })
|
||||
return { res: { json, status, end } as unknown as Response, status, json, end }
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
// ── GET /api/clientes-maestro ────────────────────────────────────────
|
||||
|
||||
describe('listarEndpoint', () => {
|
||||
it('200 con datos paginados', async () => {
|
||||
servicioMock.listar.mockResolvedValue({
|
||||
datos: [{ id: '1', numCliente: 'C001' }],
|
||||
total: 1,
|
||||
pagina: 1,
|
||||
limite: 50,
|
||||
})
|
||||
const { res, json } = resFake()
|
||||
await listarEndpoint(reqFake(), res)
|
||||
expect(json).toHaveBeenCalledWith({
|
||||
datos: [{ id: '1', numCliente: 'C001' }],
|
||||
total: 1,
|
||||
pagina: 1,
|
||||
limite: 50,
|
||||
})
|
||||
})
|
||||
|
||||
it('pasa filtros de query al servicio', async () => {
|
||||
servicioMock.listar.mockResolvedValue({ datos: [], total: 0, pagina: 1, limite: 50 })
|
||||
const { res } = resFake()
|
||||
await listarEndpoint(
|
||||
reqFake({ query: { busqueda: 'Juan', desarrollo: 'SENDA', estatus: 'VENDIDO', pagina: '2', limite: '25' } }),
|
||||
res,
|
||||
)
|
||||
expect(servicioMock.listar).toHaveBeenCalledWith({
|
||||
busqueda: 'Juan',
|
||||
desarrollo: 'SENDA',
|
||||
estatus: 'VENDIDO',
|
||||
pagina: 2,
|
||||
limite: 25,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// ── GET /api/clientes-maestro/exportar ───────────────────────────────
|
||||
|
||||
describe('exportarEndpoint', () => {
|
||||
it('200 con array de datos', async () => {
|
||||
servicioMock.exportar.mockResolvedValue([{ id: '1', numCliente: 'C001' }])
|
||||
const { res, json } = resFake()
|
||||
await exportarEndpoint(reqFake(), res)
|
||||
expect(json).toHaveBeenCalledWith([{ id: '1', numCliente: 'C001' }])
|
||||
})
|
||||
})
|
||||
|
||||
// ── GET /api/clientes-maestro/:numCliente ────────────────────────────
|
||||
|
||||
describe('obtenerEndpoint', () => {
|
||||
it('200 con el cliente', async () => {
|
||||
servicioMock.obtener.mockResolvedValue({ id: '1', numCliente: 'C001', nombre: 'Juan' })
|
||||
const { res, json } = resFake()
|
||||
await obtenerEndpoint(reqFake({ params: { numCliente: 'C001' } }), res)
|
||||
expect(json).toHaveBeenCalledWith({ id: '1', numCliente: 'C001', nombre: 'Juan' })
|
||||
})
|
||||
|
||||
it('404 si no existe', async () => {
|
||||
servicioMock.obtener.mockResolvedValue(null)
|
||||
const { res } = resFake()
|
||||
await expect(
|
||||
obtenerEndpoint(reqFake({ params: { numCliente: 'NOPE' } }), res),
|
||||
).rejects.toThrow('Cliente no encontrado')
|
||||
})
|
||||
|
||||
it('400 si numCliente vacío', async () => {
|
||||
const { res } = resFake()
|
||||
await expect(obtenerEndpoint(reqFake({ params: { numCliente: '' } }), res)).rejects.toThrow('numCliente requerido')
|
||||
})
|
||||
})
|
||||
|
||||
// ── POST /api/clientes-maestro/importar ──────────────────────────────
|
||||
|
||||
describe('importarEndpoint', () => {
|
||||
it('200 con resultado de importación', async () => {
|
||||
servicioMock.importarDesdeExcel.mockResolvedValue({ insertados: 5, actualizados: 2, errores: 1 })
|
||||
const { res, json } = resFake()
|
||||
await importarEndpoint(reqFake({ body: [{ numCliente: 'C001', nombre: 'Juan' }] }), res)
|
||||
expect(json).toHaveBeenCalledWith({ insertados: 5, actualizados: 2, errores: 1 })
|
||||
})
|
||||
|
||||
it('400 si body no es array', async () => {
|
||||
const { res } = resFake()
|
||||
await expect(importarEndpoint(reqFake({ body: {} }), res)).rejects.toThrow('Se esperaba un array')
|
||||
})
|
||||
|
||||
it('400 si array vacío', async () => {
|
||||
const { res } = resFake()
|
||||
await expect(importarEndpoint(reqFake({ body: [] }), res)).rejects.toThrow('Se esperaba un array')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user