import { describe, test, expect, beforeEach, afterEach, beforeAll, afterAll } from 'bun:test'; import { Database } from 'bun:sqlite'; import { initializeDatabase } from '../../../src/db'; import { GroupSyncService } from '../../../src/services/group-sync'; let memdb: Database; const envBackup = { ...process.env }; let originalFetchMembers: any; describe('GroupSyncService - syncMembersForActiveGroups (agregado por grupos)', () => { beforeAll(() => { memdb = new Database(':memory:'); memdb.exec('PRAGMA foreign_keys = ON;'); initializeDatabase(memdb); GroupSyncService.dbInstance = memdb as any; }); afterAll(() => { memdb.close(); }); beforeEach(() => { process.env = { ...envBackup, NODE_ENV: 'development' }; // evitar early return // Reset tablas memdb.exec('DELETE FROM group_members'); memdb.exec('DELETE FROM users'); memdb.exec('DELETE FROM groups'); // Grupo activo memdb.prepare(`INSERT INTO groups (id, community_id, name, active) VALUES (?, ?, ?, 1)`) .run('g1@g.us', 'community-1', 'Grupo 1'); // Refrescar caché de grupos activos GroupSyncService.refreshActiveGroupsCache(); // Stub método de red originalFetchMembers = (GroupSyncService as any).fetchGroupMembersFromAPI; }); afterEach(() => { (GroupSyncService as any).fetchGroupMembersFromAPI = originalFetchMembers; process.env = envBackup; }); test('primera pasada añade miembros y marca activos', async () => { (GroupSyncService as any).fetchGroupMembersFromAPI = async (_gid: string) => ([ { userId: '111', isAdmin: true }, { userId: '222', isAdmin: false }, ]); const res = await GroupSyncService.syncMembersForActiveGroups(); expect(res).toEqual({ groups: 1, added: 2, updated: 0, deactivated: 0 }); const rows = memdb.prepare(`SELECT user_id, is_admin, is_active FROM group_members ORDER BY user_id`).all() as any[]; expect(rows).toHaveLength(2); expect(rows[0]).toEqual({ user_id: '111', is_admin: 1, is_active: 1 }); expect(rows[1]).toEqual({ user_id: '222', is_admin: 0, is_active: 1 }); }); test('pasadas posteriores actualizan roles y desactivan ausentes', async () => { // Semilla inicial (GroupSyncService as any).fetchGroupMembersFromAPI = async (_gid: string) => ([ { userId: '111', isAdmin: true }, { userId: '222', isAdmin: false }, ]); await GroupSyncService.syncMembersForActiveGroups(); // Cambio: 111 pierde admin, 222 desaparece (GroupSyncService as any).fetchGroupMembersFromAPI = async (_gid: string) => ([ { userId: '111', isAdmin: false }, ]); const res2 = await GroupSyncService.syncMembersForActiveGroups(); expect(res2).toEqual({ groups: 1, added: 0, updated: 1, deactivated: 1 }); const rows = memdb.prepare(`SELECT user_id, is_admin, is_active FROM group_members ORDER BY user_id`).all() as any[]; const m111 = rows.find(r => r.user_id === '111'); const m222 = rows.find(r => r.user_id === '222'); expect(m111.is_admin).toBe(0); expect(m111.is_active).toBe(1); expect(m222.is_active).toBe(0); }); });