import { describe, it, expect } from 'vitest'; import { formatWarning } from '../src/warnings.js'; /* Stub bildet key + interpolierte Variablen sichtbar ab, damit wir prüfen können, welche Werte (inkl. Escaping) formatWarning durchreicht. */ const t = (key, vars) => `${key}|${JSON.stringify(vars)}`; describe('formatWarning — vereinheitlichtes Warnungs-Modell', () => { it('mixedGate reicht Zeile durch und HTML-escaped das Label', () => { const out = formatWarning({type: 'mixedGate', line: 7, label: 'A & '}, t); expect(out).toBe('mixedWarn|{"line":7,"label":"A & <B>"}'); }); it('unknownStatus reicht Zeile durch und escaped den Code', () => { const out = formatWarning({type: 'unknownStatus', line: 3, code: '<'}, t); expect(out).toBe('unknownStatusWarn|{"line":3,"code":"<"}'); }); it('sourceLoad escaped die URL und reicht das technische Detail durch', () => { const out = formatWarning({type: 'sourceLoad', url: 'https://a/?x=1&y=2', error: 'HTTP 404'}, t); expect(out).toBe('sourceLoadWarn|{"url":"https://a/?x=1&y=2","error":"HTTP 404"}'); }); /* Eigener Typ, weil sourceLoadWarn auf CORS zeigt: Bei Etherpads Drosselung (10 Abrufe je 90 s) schickte das den Leser auf die falsche Fährte (D31). */ it('sourceTimeout ist ein eigener Typ und nennt die Sekunden', () => { const out = formatWarning({type: 'sourceTimeout', url: 'https://p/x&y', seconds: 20}, t); expect(out).toBe('sourceTimeoutWarn|{"url":"https://p/x&y","seconds":20}'); }); /* Kein `url` im Objekt: Der Nutzer hat gar nichts angefordert, was scheitern konnte — Werkbaum hat den Abruf verhindert (D31). */ it('padRateLimit nennt die Restzeit und braucht keine URL', () => { expect(formatWarning({type: 'padRateLimit', seconds: 7}, t)) .toBe('padRateLimitWarn|{"seconds":7}'); }); it('unbekannter Typ fällt auf eine generische, escapte Meldung zurück', () => { expect(formatWarning({type: 'was?', line: 9}, t)).toBe('was? (9)'); expect(formatWarning({type: 'x'}, t)).toBe('x (?)'); }); });