chore: import maquina-comercial-pessoal history via subtree

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

git-subtree-dir: maquina-comercial-pessoal
git-subtree-mainline: f5af038e19
git-subtree-split: a9ef4d776d
This commit is contained in:
Gustavo
2026-09-28 15:50:17 -03:00
co-authored by Claude Sonnet 5
150 changed files with 33449 additions and 0 deletions
@@ -0,0 +1,97 @@
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'));
});