import { describe, test, expect, beforeEach, afterEach } from 'bun:test'; import type { Database as SqliteDatabase } from 'bun:sqlite'; import { makeMemDb, injectAllServices, resetServices } from '../../helpers/db'; import { GroupSyncService } from '../../../src/services/group-sync'; import { IdentityService } from '../../../src/services/identity'; import { Metrics } from '../../../src/services/metrics'; describe('GroupSyncService - alias_coverage_ratio', () => { const envBackup = { ...process.env }; let db: SqliteDatabase; beforeEach(() => { process.env = { ...envBackup, NODE_ENV: 'test', METRICS_ENABLED: 'true' }; Metrics.reset(); db = makeMemDb(); injectAllServices(db); (GroupSyncService as any).dbInstance = db; (IdentityService as any).dbInstance = db; // Crear grupo activo requerido por FK db.prepare(`INSERT INTO groups (id, community_id, name, active) VALUES (?, ?, ?, 1)`) .run('g1@g.us', 'comm-1', 'G1'); }); afterEach(() => { resetServices(); try { db.close(); } catch {} Metrics.reset(); process.env = envBackup; try { (IdentityService as any).inMemoryAliases?.clear?.(); } catch {} }); test('calcula cobertura en función de dígitos y alias resolubles', () => { // Sembrar un alias resoluble: aliasB -> 222 IdentityService.upsertAlias('aliasB', '222', 'test'); // Reconciliar miembros: 111 (dígitos), aliasA (no resoluble), aliasB (resoluble a 222) GroupSyncService.reconcileGroupMembers('g1@g.us', [ { userId: '111', isAdmin: false }, { userId: 'aliasA', isAdmin: false }, { userId: 'aliasB', isAdmin: false }, ], '2025-01-01 00:00:00.000'); const json = JSON.parse(Metrics.render('json')); const key = 'group_id="g1@g.us"'; const ratio = json?.labeledGauges?.alias_coverage_ratio?.[key]; expect(typeof ratio).toBe('number'); // 2 resolubles (111 y aliasB) de 3 totales -> 0.666... expect(ratio).toBeGreaterThan(0.66 - 1e-6); expect(ratio).toBeLessThan(0.67 + 1e-6); }); });