Der Knopf auf der Umzugsseite ist jetzt ein echter Verweis
Hinweis von Filipe: Wenn etwas wie ein Knopf aussieht, muss man auch
draufdruecken koennen. Er hatte recht.
Meine urspruengliche Begruendung - die Adresse solle nur zum Lesen
dastehen, damit niemand versehentlich ein Lesezeichen auf den alten Weg
setzt - traegt nicht: Wer klickt, landet auf der NEUEN Adresse und setzt
sein Lesezeichen genau dort. Ein Element, das wie ein Knopf aussieht und
sich nicht wie einer verhaelt, ist eine Falle.
Der Knopf hat jetzt einen Hover- und einen Tastatur-Fokuszustand, und
beide Bewegungen entfallen bei prefers-reduced-motion.
Die Pruefung geht dabei einen Schritt weiter als vorher: Sie prueft nicht
mehr nur, WELCHE Anfragen zugeordnet werden, sondern ruft die Middleware
wirklich auf und sieht sich die ANTWORT an. Denn die Zuordnung kann
stimmen und die Seite trotzdem kaputt sein:
- ein Platzhalter, der woertlich in der Seite steht statt eingesetzt zu
werden
- ein Knopf ohne Verweis (genau der Fall, den Filipe gemeldet hat)
- HTML statt JSON fuer /workspace/api/ - ein noch offener Tab wuerde
sonst die Hinweisseite als Daten zu lesen versuchen
- und die wichtigste: dass die NEUE Adresse durchgelassen wird
31 Pruefungen, alle gruen. Gegenprobe gemacht: Dreht man den Knopf zurueck
zu einem div ohne Verweis, meldet die Pruefung 2 Fehler - sie haette den
gemeldeten Mangel also selbst gefunden.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
|
||||
Aufruf: node server/pruef-workspace-umzug.mjs
|
||||
===================================================================== */
|
||||
import { istAlteWorkspaceAdresse, NEUE_ADRESSE } from "./workspace-umzug.js";
|
||||
import { istAlteWorkspaceAdresse, workspaceUmzug, NEUE_ADRESSE } from "./workspace-umzug.js";
|
||||
|
||||
/* [Host, Pfad, erwartet, Begruendung] */
|
||||
const FAELLE = [
|
||||
@@ -66,6 +66,46 @@ for (const [host, pfad, erwartet, grund] of FAELLE) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- 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
|
||||
@@ -77,8 +117,8 @@ 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 + 1;
|
||||
console.log(`${geprueft} Faelle geprueft (erwartet ${SOLL}), ${fehler.length} Beanstandungen.`);
|
||||
const SOLL = FAELLE.length + 11;
|
||||
console.log(`${geprueft} Pruefungen gelaufen (erwartet ${SOLL}), ${fehler.length} Beanstandungen.`);
|
||||
console.log(`Gegenprobe (alt abgeschaltet, neu erreichbar): ${gegenprobe ? "ja" : "NEIN"}`);
|
||||
for (const f of fehler) console.log(" FEHL " + f);
|
||||
|
||||
|
||||
@@ -71,9 +71,15 @@ export function istAlteWorkspaceAdresse(hostKopfzeile, pfad) {
|
||||
/* Kurze Seite statt einer nackten Fehlermeldung. Wer hier landet, hat
|
||||
einen alten Link oder eine alte Verknuepfung -- er soll erfahren, wohin
|
||||
der Workspace gezogen ist, statt vor einem leeren Fenster zu sitzen.
|
||||
Bewusst ohne Verweis zum Anklicken: Die Adresse steht zum Lesen da,
|
||||
damit niemand aus Versehen ein neues Lesezeichen auf den alten Weg
|
||||
setzt. Augenschonend dunkel wie der Rest der Seite. */
|
||||
|
||||
Der Knopf ist ein echter Verweis (Korrektur 06.09.2026, Hinweis von
|
||||
Filipe). Zuerst stand die Adresse nur zum Lesen da, mit der Begruendung,
|
||||
niemand solle versehentlich ein Lesezeichen auf den alten Weg setzen.
|
||||
Das Argument traegt nicht: Wer klickt, landet auf der NEUEN Adresse und
|
||||
setzt sein Lesezeichen genau dort. Etwas, das wie ein Knopf aussieht,
|
||||
muss sich auch wie einer verhalten -- alles andere ist eine Falle.
|
||||
|
||||
Augenschonend dunkel wie der Rest der Seite. */
|
||||
const HINWEIS = `<!doctype html>
|
||||
<html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
@@ -87,15 +93,20 @@ const HINWEIS = `<!doctype html>
|
||||
h1{font-size:1.5rem;margin:0 0 1rem;font-weight:650}
|
||||
p{color:#9aa6b2;margin:0 0 1rem}
|
||||
.adresse{display:inline-block;margin-top:.5rem;padding:.85rem 1.4rem;
|
||||
background:#0674b9;color:#fff;border-radius:10px;
|
||||
font-weight:600;letter-spacing:.01em;word-break:break-all}
|
||||
background:#0674b9;color:#fff;border-radius:10px;text-decoration:none;
|
||||
font-weight:600;letter-spacing:.01em;word-break:break-all;
|
||||
transition:background .15s ease,transform .15s ease}
|
||||
.adresse:hover,.adresse:focus-visible{background:#0a86d4;transform:translateY(-1px)}
|
||||
.adresse:focus-visible{outline:3px solid #7fd0ec;outline-offset:3px}
|
||||
@media (prefers-reduced-motion:reduce){.adresse{transition:none}
|
||||
.adresse:hover,.adresse:focus-visible{transform:none}}
|
||||
</style></head>
|
||||
<body><div class="kasten">
|
||||
<h1>Der Creator Workspace ist umgezogen</h1>
|
||||
<p>Diese Adresse gibt es nicht mehr. Der Workspace hat jetzt eine eigene
|
||||
Adresse — dadurch lässt er sich als richtige App installieren.</p>
|
||||
<p>Bitte künftig hier anmelden:</p>
|
||||
<div class="adresse">workspace.dogfather-universe.com</div>
|
||||
<a class="adresse" href="${NEUE_ADRESSE}/workspace/">workspace.dogfather-universe.com</a>
|
||||
</div></body></html>`;
|
||||
|
||||
/** Express-Zwischenschritt: beantwortet die alte Adresse mit 410 Gone. */
|
||||
|
||||
Reference in New Issue
Block a user