import { describe, test, expect, beforeEach, afterEach } from 'bun:test'; import { GroupSyncService } from '../../../src/services/group-sync'; const ORIGINAL_FETCH = globalThis.fetch; describe('GroupSyncService - fetchGroupMembersFromAPI (parsing y fallbacks)', () => { const envBackup = { ...process.env }; beforeEach(() => { process.env = { ...envBackup, NODE_ENV: 'development', // evitar early-return de test EVOLUTION_API_URL: 'http://evolution.test', EVOLUTION_API_INSTANCE: 'instance-1', EVOLUTION_API_KEY: 'apikey' }; }); afterEach(() => { process.env = envBackup; globalThis.fetch = ORIGINAL_FETCH; }); test('parsea /group/participants con múltiples formas de payload y roles', async () => { globalThis.fetch = async (url: RequestInfo | URL) => { if (String(url).includes('/group/participants/')) { const body = { participants: [ { id: '553198296801@s.whatsapp.net', admin: 'superadmin' }, { id: '1234567890@s.whatsapp.net', admin: 'admin' }, { id: '1111111111@s.whatsapp.net', admin: null }, '2222222222@s.whatsapp.net', { jid: '3333333333@s.whatsapp.net', role: 'member' }, { user: { id: '4444444444@s.whatsapp.net' }, isAdmin: true } ] }; return new Response(JSON.stringify(body), { status: 200, headers: { 'Content-Type': 'application/json' } }); } return new Response('not found', { status: 404 }); }; const out = await (GroupSyncService as any).fetchGroupMembersFromAPI('123@g.us'); // Debe mapear a IDs normalizados (solo dígitos) y detectar admin correctamente const ids = out.map((x: any) => x.userId).sort(); expect(ids).toEqual(['1111111111','1234567890','2222222222','3333333333','4444444444','553198296801'].sort()); const adminMap = new Map(out.map((x: any) => [x.userId, x.isAdmin])); expect(adminMap.get('553198296801')).toBe(true); expect(adminMap.get('1234567890')).toBe(true); expect(adminMap.get('1111111111')).toBe(false); expect(adminMap.get('2222222222')).toBe(false); expect(adminMap.get('3333333333')).toBe(false); expect(adminMap.get('4444444444')).toBe(true); }); test('fallback a fetchAllGroups cuando /group/participants no trae participants', async () => { globalThis.fetch = async (url: RequestInfo | URL) => { const u = String(url); if (u.includes('/group/participants/')) { // OK pero sin campo participants return new Response(JSON.stringify({ ok: true }), { status: 200 }); } if (u.includes('/group/fetchAllGroups/')) { const wrapped = { response: [ { id: '123@g.us', participants: [{ id: '9999999999@s.whatsapp.net', admin: 'admin' }] } ] }; return new Response(JSON.stringify(wrapped), { status: 200, headers: { 'Content-Type': 'application/json' } }); } return new Response('not found', { status: 404 }); }; const out = await (GroupSyncService as any).fetchGroupMembersFromAPI('123@g.us'); expect(out).toEqual([{ userId: '9999999999', isAdmin: true }]); }); test('fallback devuelve snapshot vacío si el grupo no está presente', async () => { globalThis.fetch = async (url: RequestInfo | URL) => { const u = String(url); if (u.includes('/group/participants/')) { return new Response(JSON.stringify({ ok: true }), { status: 200 }); } if (u.includes('/group/fetchAllGroups/')) { const wrapped = { response: [ { id: 'other@g.us', participants: [{ id: '9999999999@s.whatsapp.net', admin: 'admin' }] } ] }; return new Response(JSON.stringify(wrapped), { status: 200 }); } return new Response('not found', { status: 404 }); }; const out = await (GroupSyncService as any).fetchGroupMembersFromAPI('123@g.us'); expect(out).toEqual([]); }); });