import test from 'node:test'; import assert from 'node:assert/strict'; import { openDb, ensureDefaultAdmin } from '../src/db.mjs'; import { createAppServer } from '../src/server/index.mjs'; test('createAppServer injeta o mesmo manager nas rotas WhatsApp e outreach', async (t) => { const db = openDb(':memory:'); ensureDefaultAdmin(db); let connects = 0; const whatsapp = { getStatus: () => ({ state: 'READY', connected: true, qrExpiresAt: null, error: null }), getQr: () => null, connect: async () => { connects += 1; }, disconnect: async () => ({ state: 'STOPPED' }), sendText: async () => ({ messageId: 'id' }) }; const jobs = { subscribe: () => null, activeJobs: () => [] }; const server = createAppServer({ db, jobs, whatsapp }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); t.after(async () => { await new Promise((resolve) => server.close(resolve)); db.close(); }); const { port } = server.address(); const base = `http://127.0.0.1:${port}`; const login = await fetch(`${base}/api/auth/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username: 'admin', password: 'admin' }) }); assert.equal(login.headers.get('cache-control'), 'no-store'); const cookie = login.headers.get('set-cookie').split(';')[0]; const status = await fetch(`${base}/api/outreach/status`, { headers: { cookie } }).then((response) => response.json()); assert.equal(status.whatsapp.state, 'READY'); const campaignsResponse = await fetch(`${base}/api/campaigns`, { headers: { cookie } }); assert.equal(campaignsResponse.status, 200); const campaigns = await campaignsResponse.json(); assert.deepEqual(campaigns.campaigns.map((campaign) => campaign.code), [ 'gdelivery-food', 'gti-food', 'gti-retail' ]); const connect = await fetch(`${base}/api/whatsapp/connect`, { method: 'POST', headers: { cookie } }); assert.equal(connect.status, 202); assert.equal(connects, 1); const qr = await fetch(`${base}/api/whatsapp/qr`, { headers: { cookie } }); assert.equal(qr.headers.get('pragma'), 'no-cache'); assert.equal(qr.headers.get('expires'), '0'); }); test('erro global 500 e generico para cliente e detalhado somente no log', async (t) => { const db = openDb(':memory:'); ensureDefaultAdmin(db); db.prepare( `INSERT INTO leads (dedup_key, empresa, whatsapp, segmento, prioridade, score) VALUES ('global-error', 'Hamburgueria Erro', '5511999990001', 'hamburguerias', 1, 100)` ).run(); const secret = 'GLOBAL-SENTINEL-SECRET'; db.exec(` CREATE TRIGGER global_sentinel_failure BEFORE INSERT ON whatsapp_number_verifications BEGIN SELECT RAISE(FAIL, '${secret}'); END; `); const logs = []; const whatsapp = { getStatus: () => ({ state: 'READY', connected: true }), getQr: () => null, checkNumber: async (number) => ({ registered: true, numero: number, numero_resolvido: number }), sendText: async () => { throw new Error('sendText nao deveria ser chamado'); }, connect: async () => {}, disconnect: async () => ({ state: 'STOPPED' }) }; const jobs = { subscribe: () => null, activeJobs: () => [] }; const server = createAppServer({ db, jobs, whatsapp, log: (message) => logs.push(message) }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); t.after(async () => { await new Promise((resolve) => server.close(resolve)); db.close(); }); const base = `http://127.0.0.1:${server.address().port}`; const login = await fetch(`${base}/api/auth/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username: 'admin', password: 'admin' }) }); const cookie = login.headers.get('set-cookie').split(';')[0]; const response = await fetch(`${base}/api/campaigns/1/prepare`, { method: 'POST', headers: { cookie, 'content-type': 'application/json' }, body: '{}' }); assert.equal(response.status, 500); const body = await response.json(); assert.deepEqual(body, { erro: 'erro interno do servidor' }); assert.doesNotMatch(JSON.stringify(body), new RegExp(secret, 'i')); assert.match(logs.join('\n'), new RegExp(secret, 'i')); });