90 lines
3.7 KiB
JavaScript
90 lines
3.7 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs/promises';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { createTelegramAlerter } from '../src/alerts/telegram.mjs';
|
|
import { loadDotEnv, telegramConfig } from '../src/env.mjs';
|
|
|
|
test('telegram alert skips when disabled or missing config', async () => {
|
|
const calls = [];
|
|
const alerter = createTelegramAlerter({ enabled: false, token: '', chatId: '', fetchImpl: async (...args) => calls.push(args) });
|
|
assert.deepEqual(await alerter.alert('qr', 'QR necessario'), { sent: false, reason: 'disabled' });
|
|
assert.equal(calls.length, 0);
|
|
|
|
const missingConfigAlerter = createTelegramAlerter({ enabled: true, token: '', chatId: '', fetchImpl: async (...args) => calls.push(args) });
|
|
assert.deepEqual(await missingConfigAlerter.alert('qr', 'QR necessario'), { sent: false, reason: 'not_configured' });
|
|
assert.equal(calls.length, 0);
|
|
});
|
|
|
|
test('telegram alert sends message without leaking token to text', async () => {
|
|
const calls = [];
|
|
const fetchImpl = async (url, options) => {
|
|
calls.push({ url, options });
|
|
return { ok: true, json: async () => ({ ok: true }) };
|
|
};
|
|
const alerter = createTelegramAlerter({ enabled: true, token: '123:SECRET', chatId: '456', fetchImpl });
|
|
assert.deepEqual(await alerter.alert('qr', 'WhatsApp precisa de QR'), { sent: true });
|
|
assert.equal(calls.length, 1);
|
|
assert.match(calls[0].url, /sendMessage$/);
|
|
const payload = JSON.parse(calls[0].options.body);
|
|
assert.equal(payload.chat_id, '456');
|
|
assert.equal(payload.text, 'WhatsApp precisa de QR');
|
|
assert.doesNotMatch(payload.text, /SECRET/);
|
|
});
|
|
|
|
test('telegram alert deduplicates per key within cooldown', async () => {
|
|
let current = 1000;
|
|
const calls = [];
|
|
const fetchImpl = async (...args) => {
|
|
calls.push(args);
|
|
return { ok: true, json: async () => ({ ok: true }) };
|
|
};
|
|
const alerter = createTelegramAlerter({ enabled: true, token: 't', chatId: 'c', fetchImpl, now: () => current, cooldownMs: 1000 });
|
|
assert.equal((await alerter.alert('same', 'A')).sent, true);
|
|
assert.deepEqual(await alerter.alert('same', 'A again'), { sent: false, reason: 'cooldown' });
|
|
current = 2501;
|
|
assert.equal((await alerter.alert('same', 'A later')).sent, true);
|
|
assert.equal(calls.length, 2);
|
|
});
|
|
|
|
test('telegram alert sends first message when clock starts at zero', async () => {
|
|
const calls = [];
|
|
const fetchImpl = async (...args) => {
|
|
calls.push(args);
|
|
return { ok: true, json: async () => ({ ok: true }) };
|
|
};
|
|
const alerter = createTelegramAlerter({ enabled: true, token: 't', chatId: 'c', fetchImpl, now: () => 0, cooldownMs: 1000 });
|
|
|
|
assert.equal((await alerter.alert('zero', 'First')).sent, true);
|
|
assert.deepEqual(await alerter.alert('zero', 'Second'), { sent: false, reason: 'cooldown' });
|
|
assert.equal(calls.length, 1);
|
|
});
|
|
|
|
test('telegram config reflects values loaded from dotenv', async () => {
|
|
const keys = ['TELEGRAM_ALERTS_ENABLED', 'TELEGRAM_BOT_TOKEN', 'TELEGRAM_CHAT_ID'];
|
|
const previous = Object.fromEntries(keys.map((key) => [key, process.env[key]]));
|
|
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'telegram-env-'));
|
|
|
|
try {
|
|
for (const key of keys) delete process.env[key];
|
|
await fs.writeFile(
|
|
path.join(rootDir, '.env'),
|
|
'TELEGRAM_ALERTS_ENABLED=true\nTELEGRAM_BOT_TOKEN=123:SECRET\nTELEGRAM_CHAT_ID=456\n'
|
|
);
|
|
|
|
await loadDotEnv(rootDir);
|
|
|
|
assert.deepEqual(telegramConfig(), {
|
|
enabled: true,
|
|
botToken: '123:SECRET',
|
|
chatId: '456'
|
|
});
|
|
} finally {
|
|
for (const key of keys) {
|
|
if (previous[key] === undefined) delete process.env[key];
|
|
else process.env[key] = previous[key];
|
|
}
|
|
}
|
|
});
|