feat(modo-local): fallback completo sin Monday + cola de sincronización
- Circuit breaker saludMonday (3 fallos → modo local; ping cada 60s)
- Endpoint GET /api/sistema/estado {mondayOk, pendientesSync}
- LeadCaptura extendida (board, etapa, origen, motivo, pendienteSync)
- Tablas Unidad (espejo inventario, 288 seed) + SyncPendiente
- crmLocal: crearLead, afluencia, cambio etapa, descarte, conversión, apartar
- Ruteo en controllers: fallback local ante 502 o Monday caído
- Mi día local: resumen completo desde SQLite + unión con Monday
- Fallbacks: unidades, contactos, reportes, prefill, buscador
- Sync worker cada 2min + handlers 15 tipos (con DependenciaPendienteError)
- Gate automatizaciones: skip si !mondayOk
- Banner 'Modo local' en 5 apps + badge pendiente en mi-dia
- 597 API tests + 263 front tests verdes
Env MODO_LOCAL_FORZADO=true para testing sin Monday.
This commit is contained in:
73
api-gateway/src/services/salud-monday.service.test.ts
Normal file
73
api-gateway/src/services/salud-monday.service.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { FALLOS_PARA_CAER, SaludMondayService } from './salud-monday.service.js'
|
||||
|
||||
describe('SaludMondayService', () => {
|
||||
afterEach(() => {
|
||||
delete process.env.MODO_LOCAL_FORZADO
|
||||
})
|
||||
|
||||
it('arranca disponible (optimista)', () => {
|
||||
const salud = new SaludMondayService()
|
||||
expect(salud.ok()).toBe(true)
|
||||
expect(salud.estaDisponible()).toBe(true)
|
||||
})
|
||||
|
||||
it('cae tras FALLOS_PARA_CAER fallos consecutivos', () => {
|
||||
const salud = new SaludMondayService()
|
||||
for (let i = 0; i < FALLOS_PARA_CAER - 1; i++) salud.registrarFallo()
|
||||
expect(salud.estaDisponible()).toBe(true) // aún aguanta
|
||||
salud.registrarFallo()
|
||||
expect(salud.ok()).toBe(false)
|
||||
expect(salud.estaDisponible()).toBe(false)
|
||||
})
|
||||
|
||||
it('un éxito resetea el contador de fallos', () => {
|
||||
const salud = new SaludMondayService()
|
||||
salud.registrarFallo()
|
||||
salud.registrarFallo()
|
||||
salud.registrarExito()
|
||||
salud.registrarFallo()
|
||||
salud.registrarFallo()
|
||||
expect(salud.estaDisponible()).toBe(true) // nunca llegó a 3 seguidos
|
||||
})
|
||||
|
||||
it('un éxito recupera el flag una vez caído', () => {
|
||||
const salud = new SaludMondayService()
|
||||
for (let i = 0; i < FALLOS_PARA_CAER; i++) salud.registrarFallo()
|
||||
expect(salud.ok()).toBe(false)
|
||||
salud.registrarExito()
|
||||
expect(salud.estaDisponible()).toBe(true)
|
||||
})
|
||||
|
||||
it('MODO_LOCAL_FORZADO=true fuerza modo local aunque Monday esté sano', () => {
|
||||
const salud = new SaludMondayService()
|
||||
process.env.MODO_LOCAL_FORZADO = 'true'
|
||||
expect(salud.ok()).toBe(true) // el flag crudo no cambia
|
||||
expect(salud.estaDisponible()).toBe(false)
|
||||
process.env.MODO_LOCAL_FORZADO = 'false'
|
||||
expect(salud.estaDisponible()).toBe(true)
|
||||
})
|
||||
|
||||
it('sondear() con ping exitoso recupera el flag y devuelve true', async () => {
|
||||
const salud = new SaludMondayService()
|
||||
for (let i = 0; i < FALLOS_PARA_CAER; i++) salud.registrarFallo()
|
||||
salud.registrarPing(async () => true)
|
||||
await expect(salud.sondear()).resolves.toBe(true)
|
||||
expect(salud.estaDisponible()).toBe(true)
|
||||
})
|
||||
|
||||
it('sondear() con ping fallido deja el flag caído', async () => {
|
||||
const salud = new SaludMondayService()
|
||||
for (let i = 0; i < FALLOS_PARA_CAER; i++) salud.registrarFallo()
|
||||
salud.registrarPing(async () => false)
|
||||
await expect(salud.sondear()).resolves.toBe(false)
|
||||
expect(salud.ok()).toBe(false)
|
||||
})
|
||||
|
||||
it('sondear() sin ping registrado devuelve el flag actual', async () => {
|
||||
const salud = new SaludMondayService()
|
||||
await expect(salud.sondear()).resolves.toBe(true)
|
||||
for (let i = 0; i < FALLOS_PARA_CAER; i++) salud.registrarFallo()
|
||||
await expect(salud.sondear()).resolves.toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user