test: añade tests para groups.upsert y alias_coverage_ratio
Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>webui
parent
9a7d13938e
commit
2a1a6f2535
@ -0,0 +1,87 @@
|
||||
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
||||
import { WebhookServer } from '../../../src/server';
|
||||
import { GroupSyncService } from '../../../src/services/group-sync';
|
||||
import { makeMemDb, injectAllServices, resetServices } from '../../helpers/db';
|
||||
import type { Database as SqliteDatabase } from 'bun:sqlite';
|
||||
|
||||
describe('WebhookServer - groups.upsert encadena syncGroups y syncMembersForActiveGroups', () => {
|
||||
const envBackup = { ...process.env };
|
||||
let db: SqliteDatabase;
|
||||
|
||||
let originalSyncGroups: any;
|
||||
let originalRefresh: any;
|
||||
let originalSyncMembers: any;
|
||||
|
||||
let calledSyncGroups = 0;
|
||||
let calledRefresh = 0;
|
||||
let calledSyncMembers = 0;
|
||||
|
||||
beforeEach(() => {
|
||||
process.env = {
|
||||
...envBackup,
|
||||
NODE_ENV: 'production',
|
||||
EVOLUTION_API_INSTANCE: 'inst-1',
|
||||
EVOLUTION_API_URL: 'http://localhost:1234',
|
||||
EVOLUTION_API_KEY: 'dummy',
|
||||
CHATBOT_PHONE_NUMBER: '123456789',
|
||||
WEBHOOK_URL: 'http://localhost:3000/webhook'
|
||||
};
|
||||
|
||||
db = makeMemDb();
|
||||
// Inyectar DB en servicios
|
||||
(WebhookServer as any).dbInstance = db;
|
||||
injectAllServices(db);
|
||||
|
||||
// Guardar originales y stubear
|
||||
originalSyncGroups = GroupSyncService.syncGroups;
|
||||
originalRefresh = GroupSyncService.refreshActiveGroupsCache;
|
||||
originalSyncMembers = GroupSyncService.syncMembersForActiveGroups;
|
||||
|
||||
calledSyncGroups = 0;
|
||||
calledRefresh = 0;
|
||||
calledSyncMembers = 0;
|
||||
|
||||
GroupSyncService.syncGroups = async () => {
|
||||
calledSyncGroups++;
|
||||
return { added: 0, updated: 0 };
|
||||
};
|
||||
GroupSyncService.refreshActiveGroupsCache = () => {
|
||||
calledRefresh++;
|
||||
};
|
||||
GroupSyncService.syncMembersForActiveGroups = async () => {
|
||||
calledSyncMembers++;
|
||||
return { groups: 0, added: 0, updated: 0, deactivated: 0 };
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Restaurar stubs
|
||||
GroupSyncService.syncGroups = originalSyncGroups;
|
||||
GroupSyncService.refreshActiveGroupsCache = originalRefresh;
|
||||
GroupSyncService.syncMembersForActiveGroups = originalSyncMembers;
|
||||
|
||||
resetServices();
|
||||
try { db.close(); } catch {}
|
||||
process.env = envBackup;
|
||||
});
|
||||
|
||||
test('dispara syncGroups -> refreshActiveGroupsCache -> syncMembersForActiveGroups y responde 200', async () => {
|
||||
const payload = {
|
||||
event: 'groups.upsert',
|
||||
instance: 'inst-1',
|
||||
data: { any: 'thing' }
|
||||
};
|
||||
|
||||
const req = new Request('http://localhost/webhook', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
const res = await WebhookServer.handleRequest(req);
|
||||
expect(res.status).toBe(200);
|
||||
expect(calledSyncGroups).toBe(1);
|
||||
expect(calledRefresh).toBe(1);
|
||||
expect(calledSyncMembers).toBe(1);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,53 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue