feat(cotizador): historial, compartir WhatsApp, folio+QR, comparador de unidades, alertas de inventario
- Mis cotizaciones (guardar con cliente, retomar, nueva) asociadas al vendedor del token - Compartir: resumen copiable + deep link wa.me; PDF con folio, vigencia y QR - GET /api/cotizaciones/:id/publico (público, datos mínimos sin PII del cliente) - Comparador lado a lado de 2 unidades (mismo o distinto desarrollo) - POST /api/cotizaciones/alertas-inventario: avisa al vendedor si una unidad cotizada cambia de estatus (dedup; wire con syncs documentado) - Fix: labels de propuesta mapeados a los reales del board Oportunidades - Tests: api 201, cotizador 82
This commit is contained in:
@@ -70,6 +70,30 @@ describe('authMiddleware (AUTH_ENABLED=true)', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('deja pasar GET /cotizaciones/:id/publico sin token (destino del QR)', () => {
|
||||
vi.clearAllMocks()
|
||||
authMiddleware(
|
||||
reqFake({ method: 'GET', path: '/cotizaciones/abc-123/publico' }),
|
||||
resFake().res,
|
||||
next,
|
||||
)
|
||||
expect(next).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('el patrón público no abre otras rutas de cotizaciones', () => {
|
||||
const casos: Partial<Request>[] = [
|
||||
{ method: 'GET', path: '/cotizaciones/abc-123' },
|
||||
{ method: 'GET', path: '/cotizaciones/mias' },
|
||||
{ method: 'POST', path: '/cotizaciones/abc-123/publico' },
|
||||
{ method: 'GET', path: '/cotizaciones/abc-123/publico/extra' },
|
||||
]
|
||||
for (const c of casos) {
|
||||
const { res, status } = resFake()
|
||||
authMiddleware(reqFake(c), res, next)
|
||||
expect(status).toHaveBeenCalledWith(401)
|
||||
}
|
||||
})
|
||||
|
||||
it('protege POST /webhooks/monday con otro método no aplica: GET /webhooks/monday pide token', () => {
|
||||
const { res, status } = resFake()
|
||||
authMiddleware(reqFake({ method: 'GET', path: '/webhooks/monday' }), res, next)
|
||||
|
||||
Reference in New Issue
Block a user