You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
5.1 KiB
TypeScript
160 lines
5.1 KiB
TypeScript
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(() => {
|
|
// Clear and reset test data
|
|
db.exec('DELETE FROM groups');
|
|
db.exec('DELETE FROM sqlite_sequence WHERE name="groups"');
|
|
GroupSyncService['lastSyncAttempt'] = 0;
|
|
|
|
// Setup mock fetch to return proper Response object
|
|
fetchMock = mock(async () => {
|
|
const groups = [
|
|
{ id: 'group1', subject: 'Group 1', linkedParent: 'test-community' },
|
|
{ id: 'group2', subject: 'Group 2', linkedParent: 'other-community' },
|
|
{ id: 'group3', subject: 'Group 3' } // No linkedParent
|
|
];
|
|
return {
|
|
ok: true,
|
|
status: 200,
|
|
statusText: 'OK',
|
|
headers: new Headers({'Content-Type': 'application/json'}),
|
|
text: async () => JSON.stringify(groups),
|
|
json: async () => groups
|
|
};
|
|
});
|
|
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 () => {
|
|
// Reset last sync attempt to force a sync
|
|
GroupSyncService['lastSyncAttempt'] = 0;
|
|
|
|
const result = await GroupSyncService.syncGroups();
|
|
|
|
// Verify the correct groups were processed
|
|
expect(result).toEqual({
|
|
added: 1, // group1 should be added
|
|
updated: 0 // no existing groups to update
|
|
});
|
|
|
|
// Verify database state
|
|
const groups = db.query('SELECT * FROM groups').all();
|
|
expect(groups).toHaveLength(1);
|
|
|
|
const group = groups[0];
|
|
expect(group.id).toBe('group1');
|
|
expect(group.community_id).toBe('test-community');
|
|
expect(group.name).toBe('Group 1');
|
|
expect(group.active).toBe(1);
|
|
expect(group.last_verified).toBeTruthy();
|
|
|
|
// Verify only the matching group was processed
|
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
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 () => {
|
|
const consoleErrorMock = mock(() => {});
|
|
console.error = consoleErrorMock;
|
|
|
|
globalThis.fetch = mock(async () => ({
|
|
ok: false,
|
|
status: 404,
|
|
statusText: 'Not Found',
|
|
headers: new Headers(),
|
|
text: async () => 'Not Found',
|
|
json: async () => ({ error: 'Not Found' })
|
|
}));
|
|
|
|
await expect(GroupSyncService.syncGroups()).rejects.toThrow('API request failed: Not Found');
|
|
expect(consoleErrorMock).toHaveBeenCalled();
|
|
|
|
console.error = originalConsoleError;
|
|
});
|
|
});
|
|
});
|