117 lines
3.9 KiB
JavaScript
117 lines
3.9 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import {
|
|
hasCampaignsPausedByRestart,
|
|
notifyInitialReconnectFailure,
|
|
notifyStartupState,
|
|
notifyWhatsAppTransition,
|
|
startInitialWhatsAppReconnect
|
|
} from '../src/alerts/runtime-alerts.mjs';
|
|
|
|
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
|
|
test('startup alerts notify restart pause and QR requirement once', async () => {
|
|
const alerts = [];
|
|
const alerter = { alert: async (key, text) => alerts.push({ key, text }) };
|
|
|
|
await notifyStartupState({
|
|
alerter,
|
|
whatsappStatus: 'QR_REQUIRED',
|
|
campaignsPausedByRestart: true
|
|
});
|
|
|
|
assert.deepEqual(alerts.map((alert) => alert.key), ['campaigns-paused-restart', 'whatsapp-qr']);
|
|
});
|
|
|
|
test('startup alert delivery failures are logged and do not reject startup', async () => {
|
|
const logs = [];
|
|
const alerter = { alert: async () => { throw new Error('telegram token SECRET failed'); } };
|
|
|
|
await assert.doesNotReject(() => notifyStartupState({
|
|
alerter,
|
|
whatsappStatus: 'QR_REQUIRED',
|
|
campaignsPausedByRestart: true,
|
|
log: (message) => logs.push(message)
|
|
}));
|
|
|
|
assert.equal(logs.length, 2);
|
|
assert.match(logs[0], /telegram: alerta campaigns-paused-restart falhou/);
|
|
assert.match(logs[1], /telegram: alerta whatsapp-qr falhou/);
|
|
assert.doesNotMatch(logs.join('\n'), /SECRET|token/i);
|
|
});
|
|
|
|
test('initial WhatsApp reconnect failure alerts operator without real send', async () => {
|
|
const alerts = [];
|
|
const logs = [];
|
|
let resolveAlert;
|
|
const alerted = new Promise((resolve) => { resolveAlert = resolve; });
|
|
const alerter = {
|
|
alert: async (key, text) => {
|
|
alerts.push({ key, text });
|
|
resolveAlert();
|
|
}
|
|
};
|
|
|
|
const started = await startInitialWhatsAppReconnect({
|
|
hasSession: async () => true,
|
|
whatsapp: { connect: async () => { throw new Error('falha fake'); } },
|
|
alerter,
|
|
log: (message) => logs.push(message)
|
|
});
|
|
|
|
await alerted;
|
|
|
|
assert.equal(started, true);
|
|
assert.deepEqual(alerts.map((alert) => alert.key), ['whatsapp-initial-reconnect-failed']);
|
|
assert.match(logs[0], /reconexao inicial falhou: falha fake/);
|
|
});
|
|
|
|
test('initial reconnect alert delivery failures are logged and do not reject', async () => {
|
|
const logs = [];
|
|
const alerter = { alert: async () => { throw new Error('telegram token SECRET failed'); } };
|
|
|
|
await assert.doesNotReject(() => notifyInitialReconnectFailure({
|
|
alerter,
|
|
error: new Error('falha fake'),
|
|
log: (message) => logs.push(message)
|
|
}));
|
|
|
|
assert.match(logs[0], /reconexao inicial falhou: falha fake/);
|
|
assert.match(logs[1], /telegram: alerta whatsapp-initial-reconnect-failed falhou/);
|
|
assert.doesNotMatch(logs.join('\n'), /SECRET|token/i);
|
|
});
|
|
|
|
test('WhatsApp transition alerts when leaving READY and requiring QR', async () => {
|
|
const alerts = [];
|
|
const alerter = { alert: async (key, text) => alerts.push({ key, text }) };
|
|
|
|
await notifyWhatsAppTransition({ alerter, previousState: 'READY', nextState: 'QR_REQUIRED' });
|
|
|
|
assert.deepEqual(alerts.map((alert) => alert.key), ['whatsapp-left-ready', 'whatsapp-qr']);
|
|
});
|
|
|
|
test('restart pause detector only matches paused campaigns with server_restart reason', () => {
|
|
let sql;
|
|
const db = {
|
|
prepare: (statement) => {
|
|
sql = statement;
|
|
return { get: () => ({ found: 1 }) };
|
|
}
|
|
};
|
|
|
|
assert.equal(hasCampaignsPausedByRestart(db), true);
|
|
assert.match(sql, /status = 'paused'/);
|
|
assert.match(sql, /pause_reason = 'server_restart'/);
|
|
});
|
|
|
|
test('server startup does not await Telegram startup alert delivery before listen', async () => {
|
|
const source = await fs.readFile(path.join(root, 'scripts', 'servidor.mjs'), 'utf8');
|
|
|
|
assert.doesNotMatch(source, /await notifyStartupState/);
|
|
assert.match(source, /void notifyStartupState\(\{[^}]*log/s);
|
|
assert.ok(source.indexOf('notifyStartupState') < source.indexOf('server.listen'));
|
|
});
|