From b0e33385b416ab626e1c7d3a4a4e3c8b6ce75608 Mon Sep 17 00:00:00 2001 From: brobert Date: Mon, 10 Nov 2025 16:08:43 +0100 Subject: [PATCH] =?UTF-8?q?test:=20a=C3=B1ade=20prueba=20de=20fallback=20d?= =?UTF-8?q?el=20locator=20y=20actualiza=20la=20documentaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: aider (openrouter/openai/gpt-5) --- docs/2025-11-01-plan-refactor-tecnico.md | 5 +- tests/unit/locator.fallback.test.ts | 75 ++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/unit/locator.fallback.test.ts diff --git a/docs/2025-11-01-plan-refactor-tecnico.md b/docs/2025-11-01-plan-refactor-tecnico.md index ddc26fe..43a8de8 100644 --- a/docs/2025-11-01-plan-refactor-tecnico.md +++ b/docs/2025-11-01-plan-refactor-tecnico.md @@ -92,6 +92,7 @@ Resultados esperados después del refactor: disminución drástica de duplicados - Lote 5.5-b completado: GroupSyncService modularizado (api.ts, repo.ts, cache.ts, reconcile.ts) y desacople de Onboarding A3 (publishGroupCoveragePrompt); umbral aplicado; tests y typecheck limpios; commits: 1b0d2ec, 0ce3ecb, 2f24806. - Lote 5.5-d completado: WebhookServer modularizado (/metrics, /health y bootstrap a src/http; handleMessageUpsert extraído a src/http/webhook-handler.ts); sin cambios funcionales; tests verdes; commits: 46bec52, 7189756, e430fc1. - Lote 6.0-6.2 completados: DB Locator mínimo, conexión en bootstrap con setDb y ruta única de DB (centralización y reexport en web); sin cambios funcionales; tests y typecheck limpios; commits: 9222242, 6196dba, 2669d42. + - Lote 6.3 completado: adopción piloto con fallback en ResponseQueue y TaskService; añadido smoke test de fallback (tests/unit/locator.fallback.test.ts); tests y typecheck limpios; commit relevante: 77ad9d7. ## Estado actual (2025-11-10) @@ -104,7 +105,7 @@ Resultados esperados después del refactor: disminución drástica de duplicados - Lote 4 — ICS central y rutas homogéneas: Completado. - Lote 5 — Svelte: dividir componentes grandes: Completado. - Lote 5.5 — Refactor de servicios grandes (god classes): Completado. - - Lote 6 — DB Locator / DI ligera: En curso (PRs 6.0, 6.1 y 6.2 completados). + - Lote 6 — DB Locator / DI ligera: En curso (PRs 6.0, 6.1, 6.2 y 6.3 completados). - Lote 7 — Cobertura en módulos flojos: Pendiente. ## Fase 2 — Plan de refactor por lotes (PRs pequeñas y seguras) @@ -340,7 +341,7 @@ Cada lote incluye objetivo, cambios, métricas y comprobaciones. Mantener tests - bunx tsc -p tsconfig.core.json --noEmit - bun test --coverage - PR 6.3 — Adopción piloto con fallback (2 servicios) + PR 6.3 — Adopción piloto con fallback (2 servicios) — Completado - Archivos a modificar: - src/services/response-queue.ts — usar (ResponseQueue as any).dbInstance ?? getDb(). - src/tasks/service.ts — usar (TaskService as any).dbInstance ?? getDb(). diff --git a/tests/unit/locator.fallback.test.ts b/tests/unit/locator.fallback.test.ts new file mode 100644 index 0000000..11412b8 --- /dev/null +++ b/tests/unit/locator.fallback.test.ts @@ -0,0 +1,75 @@ +import { describe, it, expect, beforeAll, afterAll } from 'bun:test'; +import { Database } from 'bun:sqlite'; +import { initializeDatabase } from '../../src/db'; +import { setDb, getDb } from '../../src/db/locator'; +import { TaskService } from '../../src/tasks/service'; +import { ResponseQueue } from '../../src/services/response-queue'; + +describe('Locator fallback - servicios usan getDb() cuando no hay dbInstance', () => { + let memdb: Database; + let prevDb: Database | null = null; + let hadPrev = false; + let originalEnv: NodeJS.ProcessEnv; + let originalTaskDb: any; + let originalQueueDb: any; + + beforeAll(() => { + originalEnv = { ...process.env }; + process.env.NODE_ENV = 'test'; + process.env.CHATBOT_PHONE_NUMBER = '999999'; + + // Capturar DB previa del locator (si la hubiera) + try { + prevDb = getDb(); + hadPrev = true; + } catch { + prevDb = null; + hadPrev = false; + } + + // Crear DB de pruebas y configurarla en el locator global + memdb = new Database(':memory:'); + initializeDatabase(memdb); + setDb(memdb); + + // Forzar fallback deshabilitando las instancias estáticas + originalTaskDb = (TaskService as any).dbInstance; + (TaskService as any).dbInstance = undefined; + + originalQueueDb = (ResponseQueue as any).dbInstance; + (ResponseQueue as any).dbInstance = undefined; + }); + + afterAll(() => { + // Restaurar instancias estáticas + try { (TaskService as any).dbInstance = originalTaskDb; } catch {} + try { (ResponseQueue as any).dbInstance = originalQueueDb; } catch {} + + // Restaurar locator previo si existía; si no, dejamos memdb viva sin cerrar + if (hadPrev && prevDb) { + try { setDb(prevDb); } catch {} + try { memdb.close(); } catch {} + } + + process.env = originalEnv; + }); + + it('TaskService.createTask y countAllActive funcionan vía locator', () => { + const createdBy = '34600123456'; + const taskId = TaskService.createTask( + { description: 'Locator smoke', due_date: null, group_id: null, created_by: createdBy }, + [] + ); + expect(typeof taskId).toBe('number'); + expect(taskId).toBeGreaterThan(0); + + const cnt = TaskService.countAllActive(); + expect(cnt).toBe(1); + }); + + it('ResponseQueue.add persiste en DB vía locator', async () => { + await ResponseQueue.add([{ recipient: '321', message: 'hola locator' }]); + const row = memdb.query(`SELECT COUNT(*) AS c FROM response_queue`).get() as any; + expect(Number(row?.c || 0)).toBe(1); + }); +});