117 lines
5.5 KiB
JavaScript
117 lines
5.5 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert');
|
|
const { isDiscordWebhook, formatDurationShort, summarizePerHosterFromBatch, buildWebhookRequest, resolveDiscordMention } = require('../lib/webhook-notify');
|
|
|
|
const SAMPLE_SUMMARY = {
|
|
total: 10,
|
|
succeeded: 8,
|
|
failed: 2,
|
|
files: [
|
|
{ name: 'a.mkv', results: [
|
|
{ hoster: 'voe.sx', status: 'done' },
|
|
{ hoster: 'byse.sx', status: 'error', error: 'x' }
|
|
] },
|
|
{ name: 'b.mkv', results: [
|
|
{ hoster: 'voe.sx', status: 'done' },
|
|
{ hoster: 'byse.sx', status: 'done' }
|
|
] }
|
|
]
|
|
};
|
|
|
|
test('isDiscordWebhook recognizes discord URLs incl. ptb/canary/discordapp', () => {
|
|
assert.ok(isDiscordWebhook('https://discord.com/api/webhooks/123/abc'));
|
|
assert.ok(isDiscordWebhook('https://discordapp.com/api/webhooks/123/abc'));
|
|
assert.ok(isDiscordWebhook('https://ptb.discord.com/api/webhooks/123/abc'));
|
|
assert.ok(isDiscordWebhook('https://canary.discord.com/api/webhooks/123/abc'));
|
|
assert.strictEqual(isDiscordWebhook('https://example.com/hook'), false);
|
|
assert.strictEqual(isDiscordWebhook(''), false);
|
|
assert.strictEqual(isDiscordWebhook(null), false);
|
|
});
|
|
|
|
test('formatDurationShort formats h/m/s tiers', () => {
|
|
assert.strictEqual(formatDurationShort(45), '45s');
|
|
assert.strictEqual(formatDurationShort(125), '2m 5s');
|
|
assert.strictEqual(formatDurationShort(3 * 3600 + 12 * 60), '3h 12m');
|
|
assert.strictEqual(formatDurationShort(-5), '0s');
|
|
assert.strictEqual(formatDurationShort(undefined), '0s');
|
|
});
|
|
|
|
test('summarizePerHosterFromBatch counts ok/fail per hoster', () => {
|
|
const s = summarizePerHosterFromBatch(SAMPLE_SUMMARY);
|
|
assert.deepStrictEqual(s['voe.sx'], { ok: 2, fail: 0 });
|
|
assert.deepStrictEqual(s['byse.sx'], { ok: 1, fail: 1 });
|
|
});
|
|
|
|
test('summarizePerHosterFromBatch handles malformed input', () => {
|
|
assert.deepStrictEqual(summarizePerHosterFromBatch(null), {});
|
|
assert.deepStrictEqual(summarizePerHosterFromBatch({}), {});
|
|
assert.deepStrictEqual(summarizePerHosterFromBatch({ files: [{ results: null }] }), {});
|
|
});
|
|
|
|
test('buildWebhookRequest produces Discord content body for discord URLs', () => {
|
|
const req = buildWebhookRequest('https://discord.com/api/webhooks/1/x', SAMPLE_SUMMARY, { durationSec: 3700, appVersion: '3.3.59', machineName: 'srv-1' });
|
|
assert.strictEqual(req.method, 'POST');
|
|
assert.strictEqual(req.headers['Content-Type'], 'application/json');
|
|
const body = JSON.parse(req.body);
|
|
assert.ok(typeof body.content === 'string');
|
|
assert.match(body.content, /Batch fertig/);
|
|
assert.match(body.content, /srv-1/);
|
|
assert.match(body.content, /8 ok/);
|
|
assert.match(body.content, /2 Fehler/);
|
|
assert.match(body.content, /1h 1m/);
|
|
assert.match(body.content, /voe\.sx: 2\/2/);
|
|
});
|
|
|
|
test('buildWebhookRequest produces raw JSON payload for generic URLs', () => {
|
|
const req = buildWebhookRequest('https://example.com/hook', SAMPLE_SUMMARY, { durationSec: 60, appVersion: '3.3.59', timestamp: '2026-06-09T00:00:00Z' });
|
|
const body = JSON.parse(req.body);
|
|
assert.strictEqual(body.event, 'batch-done');
|
|
assert.strictEqual(body.total, 10);
|
|
assert.strictEqual(body.succeeded, 8);
|
|
assert.strictEqual(body.failed, 2);
|
|
assert.strictEqual(body.durationSec, 60);
|
|
assert.strictEqual(body.version, '3.3.59');
|
|
assert.deepStrictEqual(body.perHoster['byse.sx'], { ok: 1, fail: 1 });
|
|
});
|
|
|
|
test('resolveDiscordMention: @here / @everyone use parse=everyone', () => {
|
|
assert.deepStrictEqual(resolveDiscordMention('@here'), { token: '@here', allowed: { parse: ['everyone'] } });
|
|
assert.deepStrictEqual(resolveDiscordMention('everyone'), { token: '@everyone', allowed: { parse: ['everyone'] } });
|
|
});
|
|
|
|
test('resolveDiscordMention: bare numeric id → user mention', () => {
|
|
assert.deepStrictEqual(resolveDiscordMention('123456789012345'), { token: '<@123456789012345>', allowed: { users: ['123456789012345'] } });
|
|
assert.deepStrictEqual(resolveDiscordMention('<@!123456789012345>'), { token: '<@123456789012345>', allowed: { users: ['123456789012345'] } });
|
|
});
|
|
|
|
test('resolveDiscordMention: role:id and <@&id> → role mention', () => {
|
|
assert.deepStrictEqual(resolveDiscordMention('role:99887766'), { token: '<@&99887766>', allowed: { roles: ['99887766'] } });
|
|
assert.deepStrictEqual(resolveDiscordMention('<@&99887766>'), { token: '<@&99887766>', allowed: { roles: ['99887766'] } });
|
|
});
|
|
|
|
test('resolveDiscordMention: empty / junk → null', () => {
|
|
assert.strictEqual(resolveDiscordMention(''), null);
|
|
assert.strictEqual(resolveDiscordMention(' '), null);
|
|
assert.strictEqual(resolveDiscordMention('not-an-id'), null);
|
|
});
|
|
|
|
test('buildWebhookRequest: discord with mention prepends token + sets allowed_mentions', () => {
|
|
const req = buildWebhookRequest('https://discord.com/api/webhooks/1/x', SAMPLE_SUMMARY, { durationSec: 60, mention: '123456789012345' });
|
|
const body = JSON.parse(req.body);
|
|
assert.ok(body.content.startsWith('<@123456789012345> '));
|
|
assert.deepStrictEqual(body.allowed_mentions, { users: ['123456789012345'] });
|
|
});
|
|
|
|
test('buildWebhookRequest: discord without mention blocks all pings (allowed_mentions parse empty)', () => {
|
|
const req = buildWebhookRequest('https://discord.com/api/webhooks/1/x', SAMPLE_SUMMARY, { durationSec: 60 });
|
|
const body = JSON.parse(req.body);
|
|
assert.deepStrictEqual(body.allowed_mentions, { parse: [] });
|
|
});
|
|
|
|
test('buildWebhookRequest tolerates empty summary', () => {
|
|
const req = buildWebhookRequest('https://example.com/hook', null, {});
|
|
const body = JSON.parse(req.body);
|
|
assert.strictEqual(body.total, 0);
|
|
assert.strictEqual(body.succeeded, 0);
|
|
});
|