Files
FRASA-CAS/api-gateway/src/controllers/mi-dia.controller.test.ts
Consult AS Technology 64b01246d6 feat(mejoras): 25 mejoras UX en todos los módulos + purga Monday
Backend: mi-dia siempre local, vocabulario canónico, AplicacionPago con usuario
Mi día: modal español real, cita desde modal, score falso eliminado
Cotizador: barra sticky, persistencia local con folio
Alta Clientes: redirect eliminado, foto conectada, asesor desde sesión, refs dinámicas
Cobranza: contrato Mora arreglado, link a Plan, abono próximo pago, WhatsApp
Landing: contactos locales, ModalContacto eliminado, ModoTrabajo eliminado
Dashboards: MiTablero unificado, funnel con descartados, drill-down, rango fechas
Chat FRASA: corpus 5 desarrollos, 6 herramientas, historial conversaciones

69 archivos, 7 apps construidas
2026-09-11 06:52:37 +00:00

153 lines
5.2 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Request, Response } from 'express'
import { AppError } from '../utils/errors.js'
// ---------- Prisma y Monday mockeados (los tests no tocan BD ni red) ----------
const prismaMock = vi.hoisted(() => ({
usuario: {
findUnique: vi.fn(),
findMany: vi.fn(),
},
leadCaptura: {
findMany: vi.fn(),
},
cliente: {
findMany: vi.fn(),
},
actividadLocal: {
findMany: vi.fn(),
},
}))
const mondayMock = vi.hoisted(() => ({
getUsuariosWorkspace: vi.fn(),
getLeads: vi.fn(),
getOportunidades: vi.fn(),
getActividades: vi.fn(),
getApartados: vi.fn(),
getUltimosCambios: vi.fn(),
}))
vi.mock('../services/prisma.js', () => ({ prisma: prismaMock }))
vi.mock('../services/monday.service.js', () => ({ mondayService: mondayMock }))
import { resumenMiDiaEndpoint } from './mi-dia.controller.js'
const usuarioFake = {
id: 'u-1',
nombre: 'Martin Zavala',
rol: 'vendedor',
activo: true,
mondayUserId: 123,
}
function capturaFake(parcial: Record<string, unknown> & { leadId: string }) {
return {
id: `row-${parcial.leadId}`,
nombreLead: `Persona ${parcial.leadId}`,
telefono: null,
email: null,
origen: null,
desarrollo: null,
modelo: null,
board: 'LEADS',
etapa: 'NUEVO',
motivo: null,
submotivo: null,
datosJson: null,
fechaLimite: null,
mondayItemId: null,
pendienteSync: false,
usuarioId: 'u-1',
createdAt: new Date('2026-09-03T10:00:00'),
updatedAt: new Date('2026-09-04T10:00:00'),
...parcial,
}
}
function resFake() {
const json = vi.fn()
const status = vi.fn().mockReturnValue({ json })
return { res: { json, status } as unknown as Response, status, json }
}
const reqFake = { usuarioToken: { sub: 'u-1' } } as unknown as Request
beforeEach(() => {
vi.clearAllMocks()
prismaMock.usuario.findUnique.mockResolvedValue(usuarioFake)
prismaMock.usuario.findMany.mockResolvedValue([])
prismaMock.leadCaptura.findMany.mockResolvedValue([])
prismaMock.cliente.findMany.mockResolvedValue([])
prismaMock.actividadLocal.findMany.mockResolvedValue([])
mondayMock.getUsuariosWorkspace.mockResolvedValue([])
mondayMock.getLeads.mockResolvedValue([])
mondayMock.getOportunidades.mockResolvedValue([])
mondayMock.getActividades.mockResolvedValue([])
mondayMock.getApartados.mockResolvedValue([])
mondayMock.getUltimosCambios.mockResolvedValue(new Map())
})
describe('resumenMiDiaEndpoint (siempre local, Monday purgado)', () => {
it('responde 100% desde LeadCaptura: Monday no se llama nunca', async () => {
prismaMock.leadCaptura.findMany.mockResolvedValue([
capturaFake({ leadId: 'loc_l1', board: 'LEADS', etapa: 'NUEVO', pendienteSync: true }),
capturaFake({ leadId: 'loc_o1', board: 'OPORTUNIDADES', etapa: 'Afluencia', pendienteSync: true }),
])
const { res, json } = resFake()
await resumenMiDiaEndpoint(reqFake, res)
expect(mondayMock.getLeads).not.toHaveBeenCalled()
expect(mondayMock.getOportunidades).not.toHaveBeenCalled()
expect(mondayMock.getApartados).not.toHaveBeenCalled()
expect(mondayMock.getUsuariosWorkspace).not.toHaveBeenCalled()
const resumen = json.mock.calls[0]?.[0] as Record<string, unknown>
expect((resumen['misLeads'] as unknown[]).length).toBe(1) // solo leads, no oportunidades
expect((resumen['misOportunidades'] as { items: unknown[] }).items).toHaveLength(1)
expect(resumen['misActividadesHoy']).toEqual([])
expect(resumen['conteos']).toMatchObject({ actividadesAbiertas: 0 })
})
it('las capturas locales llegan con pendienteSync (badge ⏳ del front)', async () => {
prismaMock.leadCaptura.findMany.mockResolvedValue([
capturaFake({ leadId: 'loc_l1', board: 'LEADS', pendienteSync: true }),
])
const { res, json } = resFake()
await resumenMiDiaEndpoint(reqFake, res)
const resumen = json.mock.calls[0]?.[0] as Record<string, unknown>
expect((resumen['misLeads'] as { id: string; pendienteSync?: boolean }[]).map((l) => l.id)).toEqual(['loc_l1'])
expect((resumen['misLeads'] as { pendienteSync?: boolean }[])[0]?.pendienteSync).toBe(true)
})
it('sin capturas: listas vacías y sin flags de sync', async () => {
const { res, json } = resFake()
await resumenMiDiaEndpoint(reqFake, res)
const resumen = json.mock.calls[0]?.[0] as Record<string, unknown>
expect(resumen['misLeads']).toEqual([])
expect(JSON.stringify(resumen)).not.toContain('pendienteSync')
})
it('los usuarios del equipo solo se consultan para roles coordinador/admin/corporativo', async () => {
await resumenMiDiaEndpoint(reqFake, resFake().res)
expect(prismaMock.usuario.findMany).not.toHaveBeenCalled()
prismaMock.usuario.findUnique.mockResolvedValue({ ...usuarioFake, rol: 'coordinador' })
await resumenMiDiaEndpoint(reqFake, resFake().res)
expect(prismaMock.usuario.findMany).toHaveBeenCalledWith({
where: { activo: true },
select: { id: true, nombre: true, rol: true, activo: true },
})
})
it('un error de BD se propaga (no se traga nada)', async () => {
prismaMock.leadCaptura.findMany.mockRejectedValue(new AppError(500, 'bug'))
await expect(resumenMiDiaEndpoint(reqFake, resFake().res)).rejects.toThrow('bug')
})
})