/** * Shared test harness for server.test.ts family. * * Provides database setup, queue mocking, and env handling used by all * WebhookServer test suites. Each test file gets its own in‑memory DB * via the factory-style setup/teardown pair. */ import { Database } from 'bun:sqlite'; import { beforeAll, afterAll, beforeEach } from 'bun:test'; import { WebhookServer } from '../../src/server'; import { ResponseQueue } from '../../src/services/response-queue'; import { GroupSyncService } from '../../src/services/group-sync'; import { initializeDatabase } from '../../src/db'; import { setDb, resetDb } from '../../src/db/locator'; import { SimulatedResponseQueue } from './queue'; // ── Request builder ──────────────────────────────────────────────────── export function createTestRequest(payload: unknown): Request { return new Request('http://localhost:3007', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); } // ── Date helper ──────────────────────────────────────────────────────── export function getFutureDate(days: number): string { const date = new Date(); date.setDate(date.getDate() + days); return date.toISOString().split('T')[0]; } // ── Lifecycle helpers ────────────────────────────────────────────────── // ── Internal state ───────────────────────────────────────────────────── const ENV_BACKUP = { ...process.env }; // ── Public lifecycle factory ─────────────────────────────────────────── /** * Register the standard beforeAll / afterAll / beforeEach hooks for a * WebhookServer test module. Returns the shared in‑memory test DB so * individual tests can query it directly. * * Usage (at module scope in each test file): * const testDb = registerServerTestLifecycle(); */ export function registerServerTestLifecycle(): Database { const db = new Database(':memory:'); initializeDatabase(db); const originalAdd = (ResponseQueue as any).add; beforeAll(() => { /* DB already set up */ }); afterAll(() => { (ResponseQueue as any).add = originalAdd; resetDb(); db.close(); }); beforeEach(() => { // Clear simulated queue and swap in the fake SimulatedResponseQueue.clear(); (ResponseQueue as any).add = SimulatedResponseQueue.add; // Point WebhookServer at the test DB WebhookServer.dbInstance = db; setDb(db); // Re‑init schema (safe after destructive tests that DROP tables) initializeDatabase(db); // Truncate data db.exec('DELETE FROM response_queue'); try { db.exec('DELETE FROM task_origins'); } catch { /* may not exist */ } db.exec('DELETE FROM tasks'); db.exec('DELETE FROM users'); db.exec('DELETE FROM groups'); // Canonical active group db.exec(` INSERT OR IGNORE INTO groups (id, community_id, name, active) VALUES ('group-id@g.us', 'test-community', 'Test Group', 1) `); (GroupSyncService as any).cacheActiveGroups(); // Standard test env process.env = { ...ENV_BACKUP, INSTANCE_NAME: 'test-instance', NODE_ENV: 'test' }; }); return db; }