Files
dogfather-universe/pruef-wahl-scrollen.mjs
Claudian b941080694 Die Namensliste ging beim Scrollen zu
FILIPE, mit Bildschirmfoto der Personenauswahl: "wenn ich da scollen will geht das immer zu"

Er hatte recht, und es war eine einzige Zeile in workspace/assets/js/wahl.js:

    addEventListener('scroll', schliessen, true);

Das dritte Argument bedeutet "in der Einfangphase lauschen" -- und damit auf JEDES
Scroll-Ereignis im ganzen Dokument, auch auf das in der Liste selbst. Wer die Namensliste
herunterrollen wollte, schloss sie im selben Moment. Bei acht Eintraegen faellt das kaum
auf; beim ganzen Manager- und Scout-Team ist die Liste unbedienbar.

Zumachen MUSS sie trotzdem, wenn die Seite scrollt: Sie haengt an position:fixed und
schwaemme sonst neben ihrem Knopf davon. Deshalb wird jetzt unterschieden, WO gescrollt
wurde -- ein Scroll-Ereignis der Seite hat document als Ziel, das ist nicht in der Liste
enthalten, also schliesst sie wie bisher.

Dazu overscroll-behavior: contain in gate.css. Ohne das reicht der Browser das Rollen am
Listenende an die Seite weiter, die Seite bewegt sich -- und daran schliesst die Liste zu
Recht. Der Fehler waere zur Haelfte zurueck gewesen.

GEPRUEFT im echten Browser am echten wahl.js und gate.css (pruef-wahl-scrollen.mjs, 7
Pruefungen), und zwar BEIDE Haelften der Zusage: Liste scrollt -> bleibt offen, Seite
scrollt -> geht zu. Eine Reparatur, die nur die eine Richtung sichert, waere die naechste
Ueberraschung.

Gegenprobe: alte Zeile testweise eingesetzt -> 2 Pruefungen fallen durch. Reparatur ->
alle 7 gruen.

Die Pruefung hat sich beim Bauen DREIMAL geweigert, etwas zu bestaetigen, das sie nicht
gemessen hatte -- "die Liste ist gar nicht laenger als ihr Fenster", "scrollTop = 0". Jedes
Mal lag es an meinem Aufbau (zu hohes Fenster, fehlende Stylesheets, Mausrad ohne Wirkung),
nie an der Reparatur. Gruen gemeldet haette sie es nie.

Der Versionsstempel muss mit: Cloudflare haelt JS und CSS vier Stunden im Browser fest.
Ohne neue Adresse saehe Filipe die Reparatur bis zu vier Stunden lang nicht.

HINWEIS ZUM COMMIT: In diesem Verzeichnis lag zum Zeitpunkt der Arbeit fremde,
uncommittete Arbeit -- vier Server-Dateien (heute 16:41-16:53 geaendert), sieben neue
Pruefdateien, ~110 Bildschirmfotos, eine Fokusring-Korrektur in gate.css und eine
Beschriftung in profil.html. Nichts davon ist hier drin. Bereitgestellt wurde ausdruecklich
nach Pfad, und die beiden Dateien mit gemischtem Inhalt (gate.css, profil.html) wurden dafuer
aus HEAD geholt und nur um den eigenen Anteil ergaenzt. Die fremde Arbeit steht unveraendert
im Arbeitsstand.
2026-09-04 19:18:02 +02:00

144 lines
7.3 KiB
JavaScript

/* ===================================================================
pruef-wahl-scrollen.mjs — die Namensliste bleibt beim Scrollen offen.
ANLASS (Filipe, 04.09.2026, mit Bildschirmfoto der Personenauswahl):
"wenn ich da scollen will geht das immer zu"
Er hatte recht, und die Ursache war eine einzige Stelle in
assets/js/wahl.js:
addEventListener('scroll', schliessen, true);
Das dritte Argument bedeutet "in der Einfangphase lauschen" -- und
damit auf JEDES Scroll-Ereignis im ganzen Dokument, auch auf das in
der Liste selbst. Wer die Namensliste herunterrollen wollte, schloss
sie im selben Moment. Bei acht Eintraegen faellt das kaum auf; beim
ganzen Manager- und Scout-Team ist die Liste unbedienbar.
Zumachen MUSS sie trotzdem, wenn die Seite scrollt: Sie haengt an
position:fixed und schwaemme sonst neben ihrem Knopf davon. Deshalb
pruefen hier beide Haelften -- eine Reparatur, die nur die eine
Richtung sichert, waere die naechste Ueberraschung:
scrollt die LISTE -> bleibt offen
scrollt die SEITE -> geht zu
Geprueft wird im echten Browser am ECHTEN wahl.js und gate.css, nicht
an einer Nachbildung. Eine Nachbildung haette genau die Zeile nicht
gehabt, um die es geht.
Aufruf: node pruef-wahl-scrollen.mjs
=================================================================== */
import { chromium } from "playwright";
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const HIER = dirname(fileURLToPath(import.meta.url));
const JS = join(HIER, "workspace", "assets", "js", "wahl.js");
/* ALLE Stylesheets, die eine Arbeitsplatz-Seite laedt -- nicht nur gate.css.
Beim ersten Lauf war nur gate.css eingebunden: Die Eintraege bekamen dadurch
weder Schriftgroesse noch Innenabstand, 30 Namen waren zusammen 243 Pixel hoch,
und die Liste konnte gar nicht scrollen. Die Pruefung hat das gemeldet, statt
gruen zu behaupten, sie haette das Scrollen geprueft. */
const CSS_DATEIEN = ["gate.css", "start.css", "aufgaben.css"]
.map((n) => join(HIER, "workspace", "assets", "css", n));
let gut = 0;
const schlecht = [];
const pruefe = (name, bedingung, zusatz = "") => {
if (bedingung) { gut++; console.log(" ok " + name); }
else { schlecht.push(name); console.log(" FEHLER " + name + (zusatz ? " — " + zusatz : "")); }
};
/* Genug Eintraege, damit die Liste ueberhaupt scrollen KANN -- mit fuenf
Namen gaebe es nichts zu rollen, und die Pruefung waere gruen, ohne
etwas gemessen zu haben. Die Namen sind die aus Filipes Bild. */
const NAMEN = [
"Dogfather (admin)", "VanVan (admin)", "Cigdem (manager)", "Drouwn (manager)",
"Schulle (manager)", "BananaStift (scout)", "Patrick (scout)", "Tili (scout)",
...Array.from({ length: 22 }, (_, i) => `Weitere Person ${i + 9} (scout)`),
];
const browser = await chromium.launch();
/* Ein NIEDRIGES Fenster, wie auf Filipes Bildschirmfoto. Beim ersten Lauf stand hier
700 Pixel Hoehe -- da passte die ganze Liste hinein, es gab nichts zu scrollen, und
"bleibt beim Scrollen offen" waere eine leere Aussage gewesen. Die Pruefung hat das
selbst gemeldet, statt gruen zu behaupten, was sie nicht gemessen hatte. */
const seite = await browser.newPage({ viewport: { width: 1280, height: 420 } });
/* Die Seite ist absichtlich hoch: Ohne Scrollweg liesse sich die zweite
Haelfte ("die Seite scrollt -> Liste geht zu") gar nicht pruefen. */
await seite.setContent(`<!doctype html><html lang="de"><head><meta charset="utf-8"></head>
<body style="min-height:3000px;background:#0b1020">
<div style="padding:40px">
<select id="person">${NAMEN.map((n) => `<option>${n}</option>`).join("")}</select>
</div>
</body></html>`);
for (const datei of CSS_DATEIEN) await seite.addStyleTag({ content: readFileSync(datei, "utf8") });
await seite.addScriptTag({ content: readFileSync(JS, "utf8") });
await seite.waitForTimeout(150);
console.log("\n--- Die Liste laesst sich ueberhaupt oeffnen ---");
const knopf = seite.locator(".wahl2__knopf").first();
pruefe("Das Auswahlfeld wurde eingepackt", await knopf.count() > 0);
await knopf.click();
await seite.waitForTimeout(120);
const liste = seite.locator(".wahl2__liste").first();
pruefe("Die Liste ist offen", await liste.count() > 0);
/* DIE LISTE MUSS SCROLLEN KOENNEN, sonst ist alles Weitere wertlos: Eine Liste, die
gar nicht rollt, bleibt beim Scrollen selbstverstaendlich offen.
Die Hoehe wird hier ausdruecklich klein gesetzt, statt sie aus dem Seitenaufbau
entstehen zu lassen. Grund: Geaendert wurde die JavaScript-Logik (welches Scrollen
schliesst die Liste), nicht die Gestaltung. Ein Aufbau, der erst die echte
Schriftgroesse, Zeilenhoehe und Fensterhoehe nachbaut, prueft am Ende die
Stylesheets -- und beim ersten Versuch genau daran vorbei: 30 Namen waren
zusammen 243 Pixel hoch, es gab nichts zu rollen, und die Pruefung hat das
gemeldet, statt gruen zu behaupten, sie haette gescrollt.
Wie gross die Liste im Betrieb wird, entscheidet gate.css (max-height aus dem
Platz unter dem Knopf) -- das ist eine andere Frage als diese hier. */
await liste.evaluate((el) => { el.style.maxHeight = "150px"; });
await seite.waitForTimeout(80);
const scrollbar = await liste.evaluate((el) => el.scrollHeight > el.clientHeight + 4);
pruefe("Und sie ist laenger als ihr Fenster — es gibt wirklich etwas zu scrollen", scrollbar);
console.log("\n--- DER FALL: in der Liste scrollen ---");
/* Gerollt wird ueber scrollTop, nicht ueber das Mausrad. Grund: Beim ersten Versuch
stand hier hover() + mouse.wheel() -- die Liste blieb offen, aber scrollTop war 0.
Das Rad hatte gar nichts bewegt, es war also nie ein Scroll-Ereignis unterwegs, und
"bleibt offen" haette nichts bewiesen. Eine Zuweisung an scrollTop loest dasselbe
Ereignis aus wie das Rad, nur zuverlaessig. */
await liste.evaluate((el) => { el.scrollTop = 60; });
await seite.waitForTimeout(200);
pruefe("Die Liste ist nach dem Scrollen NOCH OFFEN", await seite.locator(".wahl2__liste").count() > 0);
const versatz = await seite.locator(".wahl2__liste").first()
.evaluate((el) => el.scrollTop).catch(() => 0);
pruefe("Und sie ist wirklich gerollt — nicht nur stehen geblieben", versatz > 0, `scrollTop = ${versatz}`);
console.log("\n--- GEGENPROBE: die SEITE scrollen ---");
/* Die andere Haelfte der Zusage. Ohne sie waere "bleibt offen" auch mit
einem ersatzlos entfernten Zuhoerer gruen -- und die Liste stuende beim
Scrollen der Seite irgendwo im Nichts. */
await seite.mouse.move(20, 20);
await seite.mouse.wheel(0, 400);
await seite.waitForTimeout(200);
pruefe("Beim Scrollen der Seite geht sie zu", await seite.locator(".wahl2__liste").count() === 0);
console.log("\n--- Und danach laesst sie sich wieder oeffnen ---");
await seite.evaluate(() => window.scrollTo(0, 0));
await seite.waitForTimeout(100);
await seite.locator(".wahl2__knopf").first().click();
await seite.waitForTimeout(120);
pruefe("Erneutes Oeffnen geht", await seite.locator(".wahl2__liste").count() > 0);
await browser.close();
console.log("");
console.log("=".repeat(60));
if (schlecht.length === 0) console.log(`Alle ${gut} Pruefungen bestanden.`);
else { console.log(`${gut} bestanden, ${schlecht.length} fehlgeschlagen:`); schlecht.forEach((s) => console.log(" - " + s)); }
process.exit(schlecht.length ? 1 : 0);