/* ===================================================================== pruef-livepunkt.mjs — Der LIVE-Punkt, wenn er sendet --------------------------------------------------------------------- Filipe, 22.09.2026: „in dieser kachel soll wenn ich live bin um 20h bis 22h ein live button der richtig geil ist mit einem live roten punkt symbol am besten, das soll aufblinken für zwei stunden. man soll nicht drauf drücken können aber so dass es auffällt. … die leute sollen auch automatisch eine benarichtigung bekommen um 20 uhr dass ich live bin." DIE WICHTIGSTE FRAGE IST NICHT „BLINKT ES" Sie lautet: Was passiert, wenn der Live-Dienst NICHT antwortet? Die öffentliche Seite macht daraus seit jeher ein „nicht live" (`assets/js/streamplan.js`, `.catch()` setzt `istLive = false`). Wer das liest, macht die Seite zu und verpasst den Stream — und niemand merkt je, dass es an einer Zeile liegt. Deshalb prüft diese Datei vor allem den dritten Ausgang: live / wartet / weiß nicht, an sechs Antworten des Dienstes durchgespielt. DIE ZWEITWICHTIGSTE: BLINKT ES AUCH DANN, WENN ES NICHT SOLL? Wer Bewegungsarmut eingestellt hat, macht das meist wegen Schwindel oder Migräne. Ein Punkt, der trotzdem pulst, ist dann keine Information, sondern eine Zumutung — und man sieht es beim Bauen nicht, weil der eigene Rechner die Einstellung nicht hat. ===================================================================== */ import { readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const HIER = dirname(fileURLToPath(import.meta.url)); const W = join(HIER, "..", "workspace"); let ok = 0, fehl = 0; const pruef = (name, bedingung, zusatz = "") => { if (bedingung) { ok++; console.log(` OK ${name}`); } else { fehl++; console.log(` FEHL ${name}${zusatz ? " — " + zusatz : ""}`); } }; const lies = (p) => readFileSync(join(W, p), "utf8"); console.log("\n===== DER LIVE-PUNKT =====\n"); /* ===================================================================== 1. DIE AUSLEGUNG — live / wartet / weiss nicht ===================================================================== */ console.log("=== Drei Antworten, nicht zwei ==="); { /* Die Funktion wird aus der ausgelieferten Datei geholt, nicht nachgebaut. Eine Nachbildung wäre die zweite Fassung, die anders altert — dann prüfte diese Datei sich selbst. */ const quelle = lies("assets/js/live.js"); const fenster = { window: {}, document: { addEventListener() {} }, fetch: () => { throw new Error("nicht benutzt"); }, setInterval: () => 0, clearInterval: () => {}, }; const fn = new Function("window", "document", "fetch", "setInterval", "clearInterval", quelle + "\nreturn window.LiveStatus;"); const L = fn(fenster.window, fenster.document, fenster.fetch, fenster.setInterval, fenster.clearInterval); pruef("live.js liefert eine Auslegung", typeof L?.auswerten === "function"); const faelle = [ { was: "er sendet", d: { ok: true, live: true, title: "Abendrunde" }, soll: "live" }, { was: "er sendet nicht", d: { ok: true, live: false, source: "automatisch", autoHealthy: true }, soll: "wartet" }, { was: "der Pruefer ist gestoert", d: { ok: true, live: false, source: "automatisch", autoHealthy: false }, soll: "weissnicht" }, { was: "von Hand auf 'nicht live' gesetzt", d: { ok: true, live: false, source: "hand", autoHealthy: false }, soll: "wartet" }, { was: "der Dienst meldet einen Fehler", d: { ok: false }, soll: "weissnicht" }, { was: "gar keine Antwort", d: null, soll: "weissnicht" }, ]; for (const f of faelle) { const r = L.auswerten(f.d); pruef(`${f.was} -> ${f.soll}`, r.zustand === f.soll, `kam: ${r.zustand}`); } /* DER KERN. Ohne diese Zeile wäre alles oben Dekoration. */ pruef('"weiss nicht" ist NICHT dasselbe wie "wartet"', L.auswerten({ ok: true, live: false, source: "automatisch", autoHealthy: false }).zustand !== L.auswerten({ ok: true, live: false, source: "automatisch", autoHealthy: true }).zustand); pruef("der Titel kommt mit, wenn er sendet", L.auswerten({ ok: true, live: true, title: "Abendrunde" }).titel === "Abendrunde"); /* Das Abzeichen -- Wort UND Punkt, damit ein Vorleseprogramm nicht nur einen leeren Kreis ansagt. */ fenster.document.createElement = (tag) => ({ tagName: tag.toUpperCase(), className: "", textContent: "", kinder: [], appendChild(k) { this.kinder.push(k); }, setAttribute(a, w) { this["_" + a] = w; }, }); const a = L.abzeichen("LIVE"); pruef("das Abzeichen traegt einen Punkt und ein Wort", a.kinder.length === 2 && a.kinder.some((k) => /wort/.test(k.className)) && a.kinder.some((k) => /punkt/.test(k.className))); pruef("und einen lesbaren Text (nicht nur einen Kreis)", a.kinder.some((k) => k.textContent === "LIVE")); pruef("der Punkt allein ist fuer Vorleseprogramme verborgen", a.kinder.some((k) => /punkt/.test(k.className) && k["_aria-hidden"] === "true")); } /* ===================================================================== 2. ES IST KEIN KNOPF ===================================================================== */ console.log("\n=== Man kann nicht draufdruecken ==="); { const css = lies("assets/css/module.css"); const block = css.slice(css.indexOf(".live-marke {")); pruef("die Marke nimmt keine Klicks an (pointer-events: none)", /\.live-marke\s*\{[^}]*pointer-events:\s*none/s.test(css)); pruef("und laesst sich nicht markieren (user-select: none)", /\.live-marke\s*\{[^}]*user-select:\s*none/s.test(css)); pruef("sie ist kein