import { describe, it, expect, beforeEach, afterAll, mock } from 'bun:test'; import { GroupSyncService } from '../../../src/services/group-sync'; import { db } from '../../../src/db'; // Store original globals const originalFetch = globalThis.fetch; const originalConsoleError = console.error; describe('GroupSyncService', () => { let fetchMock: any; beforeEach(() => { db.exec('DELETE FROM groups'); GroupSyncService['lastSyncAttempt'] = 0; // Setup mock fetch fetchMock = mock(async () => ({ ok: true, json: async () => ({ status: 'success', response: [ { id: 'group1', subject: 'Group 1', linkedParent: 'test-community' }, { id: 'group2', subject: 'Group 2', linkedParent: 'other-community' }, { id: 'group3', subject: 'Group 3' } // No linkedParent ] }) })); globalThis.fetch = fetchMock; // Setup env vars process.env.WHATSAPP_COMMUNITY_ID = 'test-community'; process.env.EVOLUTION_API_URL = 'http://test-api'; process.env.EVOLUTION_API_INSTANCE = 'test-instance'; process.env.EVOLUTION_API_KEY = 'test-key'; }); afterAll(() => { globalThis.fetch = originalFetch; }); describe('syncGroups', () => { it('should skip sync if called too soon', async () => { GroupSyncService['lastSyncAttempt'] = Date.now() - 1000; const result = await GroupSyncService.syncGroups(); expect(result).toEqual({ added: 0, updated: 0 }); expect(fetchMock).not.toHaveBeenCalled(); }); it('should throw if WHATSAPP_COMMUNITY_ID is missing', async () => { const consoleErrorMock = mock(() => {}); console.error = consoleErrorMock; process.env.WHATSAPP_COMMUNITY_ID = ''; await expect(GroupSyncService.syncGroups()) .rejects.toThrow('WHATSAPP_COMMUNITY_ID is not set'); expect(consoleErrorMock).toHaveBeenCalledWith( 'Group sync failed:', expect.any(Error) ); // Restore original console.error console.error = originalConsoleError; }); it('should filter groups by community ID', async () => { const result = await GroupSyncService.syncGroups(); expect(result).toEqual({ added: 1, updated: 0 }); const groups = db.query('SELECT * FROM groups').all(); expect(groups).toEqual([ { id: 'group1', community_id: 'test-community', name: 'Group 1', active: 1, last_verified: expect.any(String) } ]); }); it('should update existing groups', async () => { // Add initial group db.exec( "INSERT INTO groups (id, community_id, name, active) VALUES ('group1', 'test-community', 'Old Name', 1)" ); const result = await GroupSyncService.syncGroups(); expect(result).toEqual({ added: 0, updated: 1 }); const group = db.query('SELECT * FROM groups WHERE id = ?').get('group1'); expect(group).toEqual({ id: 'group1', community_id: 'test-community', name: 'Group 1', active: 1, last_verified: expect.any(String) }); }); it('should mark non-matching groups as inactive', async () => { // Add initial group not in current sync db.exec( "INSERT INTO groups (id, community_id, name, active, last_verified) VALUES ('old-group', 'test-community', 'Old Group', 1, '2023-01-01')" ); await GroupSyncService.syncGroups(); const group = db.query('SELECT * FROM groups WHERE id = ?').get('old-group'); expect(group).toEqual({ id: 'old-group', community_id: 'test-community', name: 'Old Group', active: 0, last_verified: expect.any(String) }); expect(group.last_verified).not.toBe('2023-01-01'); // Should be updated }); it('should handle API errors', async () => { globalThis.fetch = mock(async () => ({ ok: false, statusText: 'Not Found', json: async () => ({ status: 'error', message: 'Not Found' }) })); await expect(GroupSyncService.syncGroups()).rejects.toThrow('API request failed: Not Found'); }); }); });