diff --git a/server/pruef-chat-optik.mjs b/server/pruef-chat-optik.mjs
index d8cd036e..9a615581 100644
--- a/server/pruef-chat-optik.mjs
+++ b/server/pruef-chat-optik.mjs
@@ -394,6 +394,105 @@ melde("\n=== Der Fuss bleibt in der Blase ===");
await luna.seite.waitForTimeout(300);
}
+/* =====================================================================
+ EINE NACHRICHT, DIE NICHT ANKOMMT (20.09.2026)
+
+ Der wichtigste Satz im Code daneben lautete: „NICHT STILL
+ VERSCHWINDEN LASSEN. Wer etwas schreibt und es sieht, glaubt, es
+ sei angekommen." Gemessen am 20.09.2026 wurde er nicht eingehalten:
+ `markiereAlsGescheitert` setzte `n.gescheitert = true` -- und
+ gelesen hat das Merkmal NIEMAND, weder das Skript noch das CSS.
+ Eine gescheiterte Nachricht sah exakt aus wie eine zugestellte.
+
+ Ein Kommentar, der eine Absicht beschreibt, erfüllt sie nicht.
+
+ Und der Satz in der Meldezeile bat den Nutzer, die Arbeit der Seite
+ zu machen: „kopiere sie und versuch es erneut" -- markieren,
+ kopieren, Feld leeren, einfügen, senden. Fünf Handgriffe für etwas,
+ das die Seite in einem tun kann; den Text hat sie ja noch.
+
+ Geprüft wird deshalb der GANZE Weg, und zwar an einem echten
+ Fehlschlag: Die Anfrage wird unterwegs abgefangen, die Nachricht
+ muss sichtbar scheitern, und der Knopf daneben muss sie wirklich
+ zustellen.
+ ===================================================================== */
+{
+ melde("\n— Eine Nachricht, die nicht ankommt —");
+
+ /* Den Sendeweg EINMAL scheitern lassen. Nicht den Server abschalten:
+ Dann wäre auch der Ereignisstrom weg, und die Prüfung misst einen
+ anderen Fehler als den gemeinten. */
+ let abgefangen = 0;
+ await luna.seite.route("**/api/chat/raeume/*/nachrichten", (weg) => {
+ if (abgefangen === 0) { abgefangen++; return weg.abort("failed"); }
+ return weg.continue();
+ });
+
+ const TEXT = "Diese Nachricht scheitert beim ersten Versuch.";
+ await luna.seite.fill("#text", TEXT);
+ await luna.seite.press("#text", "Enter");
+ await luna.seite.waitForTimeout(900);
+
+ ok(abgefangen === 1, `die Anfrage wurde wirklich abgefangen (${abgefangen}x)`);
+
+ const gescheitert = await luna.seite.evaluate((t) => {
+ const alle = [...document.querySelectorAll(".chat-nachricht")];
+ const z = alle.find((e) => e.textContent.includes(t));
+ if (!z) return null;
+ return {
+ markiert: z.dataset.gescheitert === "ja",
+ knopf: !!z.querySelector(".chat-nachricht__nochmal"),
+ /* Sieht man den Unterschied WIRKLICH -- oder steht er nur im
+ Merkmal? Gemessen an echten Bildpunkten. */
+ rand: getComputedStyle(z.querySelector(".chat-nachricht__blase")).borderTopWidth,
+ };
+ }, TEXT);
+
+ ok(gescheitert !== null, "die Nachricht steht noch im Verlauf");
+ ok(gescheitert?.markiert === true, "und ist sichtbar als gescheitert markiert");
+ ok(gescheitert?.rand !== "0px",
+ `der Unterschied ist auch zu SEHEN, nicht nur im Merkmal (Rand ${gescheitert?.rand})`);
+ ok(gescheitert?.knopf === true, "und daneben steht „Nochmal senden“");
+
+ /* Der Satz in der Meldezeile verlangt nichts mehr vom Nutzer. */
+ const satz = await luna.seite.evaluate(() =>
+ document.getElementById("fehler")?.textContent || "");
+ ok(!/kopiere/i.test(satz),
+ `und die Meldung bittet nicht mehr ums Kopieren („${satz.slice(0, 70)}“)`);
+
+ /* ---- Und jetzt der Knopf ---------------------------------------- */
+ const vorher = await luna.seite.evaluate(() =>
+ document.querySelectorAll(".chat-nachricht").length);
+ await luna.seite.click(".chat-nachricht__nochmal");
+ await luna.seite.waitForTimeout(1200);
+
+ const danach = await luna.seite.evaluate((t) => {
+ const alle = [...document.querySelectorAll(".chat-nachricht")];
+ const treffer = alle.filter((e) => e.textContent.includes(t));
+ return {
+ anzahl: alle.length,
+ mitText: treffer.length,
+ nochGescheitert: treffer.some((e) => e.dataset.gescheitert === "ja"),
+ };
+ }, TEXT);
+
+ ok(danach.mitText === 1,
+ `die Nachricht steht danach GENAU EINMAL da (${danach.mitText}x) `
+ + `— nicht doppelt, wie es bei einem zweiten Sendeweg passieren würde`);
+ ok(danach.nochGescheitert === false, "und gilt nicht mehr als gescheitert");
+ ok(danach.anzahl === vorher, `die Zahl der Nachrichten blieb gleich (${vorher} → ${danach.anzahl})`);
+
+ /* Und sie ist WIRKLICH beim Gegenüber angekommen -- nicht nur im
+ eigenen Bild. Das ist der Unterschied zwischen „sieht gut aus"
+ und „funktioniert". */
+ await pat.seite.waitForTimeout(800);
+ const beimAnderen = await pat.seite.evaluate((t) =>
+ document.body.textContent.includes(t), TEXT);
+ ok(beimAnderen === true, "und sie ist beim Gegenüber angekommen");
+
+ await luna.seite.unroute("**/api/chat/raeume/*/nachrichten");
+}
+
await luna.ctx.close();
await pat.ctx.close();
await browser.close();
diff --git a/server/pruef-treffchat.mjs b/server/pruef-treffchat.mjs
index f269dc70..652f1075 100644
--- a/server/pruef-treffchat.mjs
+++ b/server/pruef-treffchat.mjs
@@ -464,9 +464,22 @@ melde("=== 6. Die Kachel ===");
{
const ich = json(await ruf("/workspace/api/ich", CREW, "GET", { cookie: kGast }));
const alle = [...(ich.bereiche || []), ...(ich.bereiche_zusatz || [])];
- const k = alle.find((x) => x.ziel === "chat.html");
+ /* NACH DER SEITE SUCHEN, NICHT NACH DER GANZEN ADRESSE (20.09.2026).
+ Hier stand `x.ziel === "chat.html"`. Seit dem 19.09. traegt die
+ Kachel `chat.html?raum=treff` -- sie fuehrt direkt in den Raum,
+ statt in einer Liste zu landen. Die Pruefung fand sie danach gar
+ nicht mehr und meldete acht Fehler ueber „undefined": kein Befund
+ ueber das Haus, sondern einer ueber sich selbst. */
+ const k = alle.find((x) => String(x.ziel).split("?")[0] === "chat.html");
ok(!!k, "die Community hat eine Chat-Kachel");
- ok(k?.name === "Chat", `sie heißt „${k?.name}“`);
+ /* NICHT MEHR AUF DEN WORTLAUT „Chat" FESTGENAGELT. Ein Modi hat
+ ZWEI Kacheln, die in den Chat fuehren -- die des Teams und die
+ des Treffs. Hiessen beide „Chat", waere das die Falle, die am
+ 19.09. behoben wurde. Geprueft wird deshalb, worauf es ankommt:
+ Man erkennt den Chat, und der Name ist eindeutig. */
+ ok(/chat/i.test(k?.name || ""), `sie ist als Chat erkennbar: „${k?.name}“`);
+ ok(alle.filter((x) => x.name === k?.name).length === 1,
+ `und ihr Name kommt genau einmal vor („${k?.name}“)`);
ok(/nacht/i.test(k?.unter || ""),
`und sagt schon auf der Startseite, dass er nachts schläft: „${k?.unter}“`);
diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html
index 4c81e8b9..6ad585a5 100644
--- a/workspace/anruf-probe.html
+++ b/workspace/anruf-probe.html
@@ -16,15 +16,15 @@
verdeckt. Gefunden hat es pruef-struktur.
Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. -->
-
-
+
+
-
+