- POST /api/auth/cambiar-password (bcrypt 12, política ≥8+1 número) + modal en las 6 apps con auth - PWA: manifest + íconos de marca en las 7 apps (sin service worker a propósito, documentado); instalable en celular - Dashboards: 'Mi tablero' para vendedor (sus KPIs y funnel) y sección Equipo para coordinador/corporativo/admin - mi-dia: equipo.porVendedor gana leadsNuevosSemana - Tests: api 271, cotizador 88, alta 88, cobranza 81, agente-ia 19, dashboards 15, mi-dia 11, landing 4
37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { esRolConEquipo, funnelMisLeads, type LeadMiDia } from './mi-tablero'
|
|
|
|
function lead(id: string, estado: string): LeadMiDia {
|
|
return { id, nombre: `Lead ${id}`, telefono: '', email: '', estado, origen: 'Web', updatedAt: '' }
|
|
}
|
|
|
|
describe('esRolConEquipo', () => {
|
|
it('coordinador, corporativo y admin ven equipo; vendedor no', () => {
|
|
expect(esRolConEquipo('coordinador')).toBe(true)
|
|
expect(esRolConEquipo('corporativo')).toBe(true)
|
|
expect(esRolConEquipo('admin')).toBe(true)
|
|
expect(esRolConEquipo('vendedor')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('funnelMisLeads', () => {
|
|
it('agrupa por estado normalizado y ordena de mayor a menor', () => {
|
|
const funnel = funnelMisLeads([
|
|
lead('1', 'NUEVO'),
|
|
lead('2', 'nuevo'),
|
|
lead('3', ' Contactado '),
|
|
lead('4', 'CITA'),
|
|
])
|
|
expect(funnel).toEqual([
|
|
{ etapa: 'NUEVO', valor: 2 },
|
|
{ etapa: 'CITA', valor: 1 },
|
|
{ etapa: 'CONTACTADO', valor: 1 },
|
|
])
|
|
})
|
|
|
|
it('lista vacía → funnel vacío; estado vacío → SIN ESTADO', () => {
|
|
expect(funnelMisLeads([])).toEqual([])
|
|
expect(funnelMisLeads([lead('1', ' ')])).toEqual([{ etapa: 'SIN ESTADO', valor: 1 }])
|
|
})
|
|
})
|