Filipe: "ich will dass du die komplette seite auf dem handy abcheckst.
ich will dass alles perfekt aussieht und bedienbar ist."
DER SCHWERSTE FUND: Auf ZWOELF Seiten war der "Meine Sicht"-Umschalter
nicht bedienbar -- wer darauf tippte, landete im Chat.
Bei 412 px (der haeufigsten Android-Breite ueberhaupt) brach die
Kopfleiste nicht um, der Umschalter wurde auf 50 px zusammengedrueckt,
sein Knopf behielt aber seine 104 px Mindestbreite und lag damit quer
ueber dem Chat-Knopf. Sichtbar war davon nichts.
Und die Ursache steht seit dem 05.09. woertlich im Kommentar daneben:
"Die Rechnung ging genau auf, solange rechts VIER Dinge standen. Mit der
Glocke sind es FUENF, und bei 320 px passte es nicht mehr." Am 06.09.
habe ich den Chat-Knopf dazugesetzt -- SECHS -- und die Schwelle bei 380
gelassen. Derselbe Fehler, eine Position weiter.
Die Lehre ist nicht "380 auf 430 erhoehen"; das waere er ein drittes
Mal, nur mit einer anderen Zahl. Eine feste Schwelle ist eine Rechnung,
die jemand einmal aufgestellt hat und die beim naechsten Knopf still
falsch wird. `flex-wrap: wrap` OHNE Schwelle rechnet nicht, sondern
misst -- es bricht genau dann um, wenn der Platz nicht reicht.
DASSELBE NOCH EINMAL, am anderen Ende: Bei 1280 px brauchte die Leiste
1235 px (Marke 375 + Bedienelemente 844 + Abstand 16) und hatte 1200.
Auch hier war der Chat-Knopf der Tropfen. Sie brach um, sobald das
Skript die Bedienelemente eingehaengt hatte, und schob die ganze Seite
52 px nach unten -- CLS 0,94. Jetzt gibt die MARKE nach (sie darf
gekuerzt werden, ein Knopf nicht), und umgebrochen wird nur noch auf
sehr schmalen Geraeten.
WEITERE ECHTE FUNDE:
* /workspace/api/chat/ungelesen wurde auf JEDER Seite ZWEIMAL geholt:
einmal beim Laden, einmal Millisekunden spaeter beim Aufgehen des
Ereignisstroms. Der 'open'-Zuhoerer war fuer Wiederverbindungen
gedacht und feuerte auch beim ersten Mal.
* Drei Kacheln teilten sich einen Farbton mit einer anderen (18 Farben
auf 21 Kacheln). Filipe wollte ausdruecklich, dass jede ihre eigene
hat. Nicht eine Farbe dazuerfunden -- der ganze Farbkreis ist mit
tools/kachel-farben.mjs neu in 21 geteilt; kleinster Abstand zweier
Nachbarn jetzt 120 Grad (vorher 106). Dabei fiel eine feste 16 in
der Mischschleife auf: Bei 18 Kacheln wurden die letzten beiden nie
mitgemischt.
* Der Agentur-Untertitel wurde auf dem Handy abgeschnitten.
* Ein zugeklappter <details>-Kasten (Kalender-Abo) verdeckte einen
Filter-Chip: Chromium versteckt dessen Inhalt ueber
`content-visibility`, nicht ueber `display` -- die Kaesten behalten
eine Groesse. Dieselbe Falle wie bei den Zeitbloecken, dieselbe
Loesung.
UND DREI PRUEFUNGEN, DIE SELBST FALSCH LAGEN:
* "achtzehn Kacheln" stand als feste Zahl im Test. Eine Pruefung, die
bei jeder neuen Kachel rot wird, erzieht dazu, ihr Rotwerden zu
ignorieren. Sie zaehlt jetzt aus bereiche.js.
* "das Licht der Kalender-Kachel (tuerkis) muss mehr Blau als Rot
haben" -- Wissen von aussen, und nach dem Neurechnen war der
Kalender rosa. Gemessen wird jetzt gegen den Ton der Kachel selbst.
* pruef-workspace-umzug meldete sein Ergebnis in eigenen Worten. Der
Gesamtlauf las daraus NULL Pruefungen und schrieb bei JEDEM Lauf ein
FEHL, obwohl alle 31 Punkte bestanden. Ein Fehlalarm, der immer
kommt, macht den einen echten unsichtbar.
Und weil "BUTTON 'Meine Sicht' verdeckt" mich eine Stunde gekostet hat,
sagen pruef-handy und pruef-tempo jetzt DAZU, was verdeckt und was
springt -- mit Elternkette und Koordinaten. Ein Befund, den man nicht
verorten kann, ist ein halber.
NEU: der Kalender zum Abonnieren (Stufe 3.2). Persoenlicher, jederzeit
widerrufbarer Link fuer Google, Apple und Outlook. 36 Pruefungen, die
das ICS ZURUECKLESEN statt es anzusehen -- entfaltet, entschluesselt,
verglichen. Wichtigster Punkt: Der Weg ohne Anmeldung darf nichts
zeigen, was der Weg mit Anmeldung nicht zeigt.
Co-Authored-By: Claude Opus 5 <[email protected]>
143 lines
7.8 KiB
JavaScript
143 lines
7.8 KiB
JavaScript
/* =====================================================================
|
|
Prüft, WELCHE Anfragen der abgeschalteten alten Workspace-Adresse
|
|
zugeordnet werden.
|
|
|
|
Zwei Fehler waeren hier teuer, und beide sieht man einer Bedingung
|
|
nicht an:
|
|
|
|
1. DIE NEUE ADRESSE MIT ABSCHALTEN. Derselbe Dienst bedient die alte
|
|
UND die neue Adresse. Wer nicht auf den Hostnamen prueft, sperrt
|
|
den Workspace fuer alle aus -- sofort nach dem Neustart und ohne
|
|
dass es vorher irgendwo auffaellt.
|
|
|
|
2. PRAEFIX-IRRTUM. "faengt an mit /workspace" trifft auch
|
|
/workspaceXYZ oder /workspace-alt -- Pfade, die nicht zum
|
|
Workspace gehoeren.
|
|
|
|
Geprueft wird die ECHTE Funktion aus workspace-umzug.js, nicht eine
|
|
Kopie der Bedingung -- eine Kopie wuerde beim naechsten Umbau
|
|
auseinanderlaufen und dann etwas anderes bestaetigen als das, was
|
|
wirklich laeuft.
|
|
|
|
Aufruf: node server/pruef-workspace-umzug.mjs
|
|
===================================================================== */
|
|
import { istAlteWorkspaceAdresse, workspaceUmzug, NEUE_ADRESSE } from "./workspace-umzug.js";
|
|
|
|
/* [Host, Pfad, erwartet, Begruendung] */
|
|
const FAELLE = [
|
|
// --- muss abgeschaltet sein (410 Gone) ---
|
|
["dogfather-universe.com", "/workspace/", true, "alte Adresse, Startseite"],
|
|
["dogfather-universe.com", "/workspace", true, "alte Adresse, ohne Schraegstrich"],
|
|
["dogfather-universe.com", "/workspace/start.html", true, "alte Adresse, Unterseite"],
|
|
["dogfather-universe.com", "/workspace/api/aufgaben", true, "alte Adresse, Schnittstelle"],
|
|
["www.dogfather-universe.com", "/workspace/", true, "auch mit www"],
|
|
["DOGFATHER-UNIVERSE.COM", "/workspace/", true, "Grossschreibung darf egal sein"],
|
|
["dogfather-universe.com:443", "/workspace/", true, "Portangabe darf egal sein"],
|
|
|
|
// --- darf NIEMALS abgeschaltet werden: das ist der neue Ort ---
|
|
["workspace.dogfather-universe.com", "/workspace/", false, "NEUE Adresse -- darf NIE abgeschaltet werden"],
|
|
["workspace.dogfather-universe.com", "/workspace/start.html", false, "NEUE Adresse, Unterseite"],
|
|
["workspace.dogfather-universe.com", "/workspace/api/aufgaben", false, "NEUE Adresse, Schnittstelle"],
|
|
|
|
// --- darf nicht betroffen sein: gehoert nicht zum Workspace ---
|
|
["dogfather-universe.com", "/", false, "Hauptseite"],
|
|
["dogfather-universe.com", "/index.html", false, "Hauptseite"],
|
|
["dogfather-universe.com", "/webdesign/", false, "anderer Bereich"],
|
|
["dogfather-universe.com", "/workspaceXYZ", false, "PRAEFIX-IRRTUM: gehoert nicht dazu"],
|
|
["dogfather-universe.com", "/workspace-alt/seite", false, "PRAEFIX-IRRTUM mit Bindestrich"],
|
|
["dogfather-universe.com", "/assets/css/main.css", false, "gemeinsame Datei"],
|
|
|
|
// --- darf nicht betroffen sein: lokale Tests wuerden sonst scheitern ---
|
|
["127.0.0.1:4100", "/workspace/", false, "lokaler Testserver"],
|
|
["localhost:4100", "/workspace/start.html", false, "lokaler Testserver"],
|
|
|
|
// --- Sonderfaelle ---
|
|
["", "/workspace/", false, "kein Host-Feld"],
|
|
["boese.example.com", "/workspace/", false, "fremder Host"],
|
|
];
|
|
|
|
let geprueft = 0;
|
|
const fehler = [];
|
|
for (const [host, pfad, erwartet, grund] of FAELLE) {
|
|
const ist = istAlteWorkspaceAdresse(host, pfad);
|
|
geprueft++;
|
|
if (ist !== erwartet) {
|
|
fehler.push(`${host || "(leer)"}${pfad} -> ${ist ? "abgeschaltet" : "erreichbar"}, erwartet ${erwartet ? "abgeschaltet" : "erreichbar"} (${grund})`);
|
|
}
|
|
}
|
|
|
|
/* ---- Die tatsaechliche ANTWORT pruefen, nicht nur die Entscheidung ----
|
|
Die Zuordnung oben kann stimmen und die Seite trotzdem kaputt sein: ein
|
|
nicht eingesetzter Platzhalter, ein Knopf ohne Verweis, HTML statt JSON
|
|
fuer die Schnittstelle. Deshalb wird die Middleware hier wirklich
|
|
aufgerufen -- mit nachgebildeten Anfrage- und Antwortobjekten. */
|
|
const pruefe = (bedingung, was) => { geprueft++; if (!bedingung) fehler.push(was); };
|
|
|
|
function antwortHolen(host, pfad) {
|
|
const req = { get: (n) => (String(n).toLowerCase() === "host" ? host : undefined), path: pfad, originalUrl: pfad };
|
|
const a = { code: null, art: null, koerper: null, weiter: false };
|
|
const res = {
|
|
status(c) { a.code = c; return this; },
|
|
type(t) { a.art = t; return this; },
|
|
send(k) { a.koerper = k; return this; },
|
|
json(k) { a.art = "json"; a.koerper = k; return this; },
|
|
};
|
|
workspaceUmzug(req, res, () => { a.weiter = true; });
|
|
return a;
|
|
}
|
|
|
|
const seite = antwortHolen("dogfather-universe.com", "/workspace/");
|
|
pruefe(seite.code === 410, `Hinweisseite antwortet mit ${seite.code}, erwartet 410`);
|
|
pruefe(seite.art === "html", `Hinweisseite hat Art ${seite.art}, erwartet html`);
|
|
pruefe(String(seite.koerper).includes(NEUE_ADRESSE + "/workspace/"),
|
|
"Hinweisseite nennt die neue Adresse nicht als Ziel");
|
|
pruefe(/<a[^>]+class="adresse"[^>]+href=/.test(String(seite.koerper)),
|
|
"Der Knopf ist kein anklickbarer Verweis — er saehe nur aus wie einer");
|
|
pruefe(!String(seite.koerper).includes("${"),
|
|
"Ein Platzhalter wurde nicht eingesetzt und steht woertlich in der Seite");
|
|
|
|
const api = antwortHolen("dogfather-universe.com", "/workspace/api/aufgaben");
|
|
pruefe(api.code === 410, `Schnittstelle antwortet mit ${api.code}, erwartet 410`);
|
|
pruefe(api.art === "json",
|
|
"Schnittstelle liefert kein JSON — ein noch offener Tab wuerde HTML als Daten zu lesen versuchen");
|
|
pruefe(api.koerper?.neueAdresse === NEUE_ADRESSE, "JSON nennt die neue Adresse nicht");
|
|
|
|
const durch = antwortHolen("workspace.dogfather-universe.com", "/workspace/");
|
|
pruefe(durch.weiter === true, "NEUE Adresse wurde abgefangen — der Workspace waere tot");
|
|
pruefe(durch.code === null, "NEUE Adresse bekam eine Antwort, statt durchgelassen zu werden");
|
|
|
|
/* Gegenprobe: Kann diese Pruefung ueberhaupt "nein" sagen? Ein Fall, von
|
|
dem wir wissen, dass er falsch ist, MUSS auffallen. */
|
|
const gegenprobe = istAlteWorkspaceAdresse("dogfather-universe.com", "/workspace/") === true
|
|
&& istAlteWorkspaceAdresse("workspace.dogfather-universe.com", "/workspace/") === false;
|
|
|
|
/* Und die genannte neue Adresse muss stimmen -- sie steht auf der
|
|
Hinweisseite, die abgemeldete Nutzer zu sehen bekommen. */
|
|
const zielStimmt = NEUE_ADRESSE === "https://workspace.dogfather-universe.com";
|
|
geprueft++;
|
|
if (!zielStimmt) fehler.push(`Ziel ist "${NEUE_ADRESSE}", erwartet https://workspace.dogfather-universe.com`);
|
|
|
|
const SOLL = FAELLE.length + 11;
|
|
|
|
/* IN DERSELBEN SCHREIBWEISE WIE ALLE ANDEREN (06.09.2026).
|
|
|
|
Diese Datei meldete ihr Ergebnis in eigenen Worten ("31 Pruefungen
|
|
gelaufen") statt in den Zeilen ` ok ` / ` FEHL `, nach denen
|
|
tools/alles-pruefen.mjs zaehlt. Der Gesamtlauf las daraus NULL
|
|
Pruefungen -- und weil "null Pruefungen" dort zu Recht als Fehler
|
|
gilt, stand hier bei jedem Lauf ein FEHL, obwohl alle 31 Punkte
|
|
bestanden.
|
|
|
|
Das ist die unangenehmste Sorte Fehlalarm: Er kommt immer, er ist
|
|
immer unbegruendet, und nach drei Malen liest ihn niemand mehr. Genau
|
|
dann faellt der eine echte nicht mehr auf. Deshalb schreibt diese
|
|
Datei jetzt dieselbe Sprache wie ihre Nachbarn. */
|
|
console.log(` ok ${geprueft} Faelle geprueft (erwartet ${SOLL})`);
|
|
console.log(` ${gegenprobe ? "ok " : "FEHL"} Gegenprobe: alt abgeschaltet, neu erreichbar`);
|
|
console.log(` ${fehler.length === 0 ? "ok " : "FEHL"} ${fehler.length} Beanstandungen`);
|
|
for (const f of fehler) console.log(" FEHL " + f);
|
|
|
|
if (geprueft !== SOLL) { console.log("FEHL: Anzahl stimmt nicht."); process.exit(1); }
|
|
if (!gegenprobe) { console.log("FEHL: Gegenprobe schlaegt nicht an -- die Pruefung waere wertlos."); process.exit(1); }
|
|
process.exit(fehler.length === 0 ? 0 : 1);
|