diff --git a/server/pruef-formulare.mjs b/server/pruef-formulare.mjs index a7bade63..959986bf 100644 --- a/server/pruef-formulare.mjs +++ b/server/pruef-formulare.mjs @@ -310,6 +310,181 @@ console.log("\n=== Kein Feld ohne Gestaltung"); await kontext.close(); } +/* ===================================================================== + WAS AUFKLAPPT, MUSS AUCH PLATZ BEKOMMEN (22.09.2026) + ===================================================================== + Filipe zum Bildschirmfoto: „wie scheisse sieht das aus, verbesser das + bitte." Zu sehen war das Aufgaben-Formular: „Anlegen" und + „Abbrechen" lagen mitten in der Personenliste. + + WARUM DIE PRUEFUNG DARUEBER DAS NICHT FINDEN KONNTE: Sie oeffnet das + Formular und misst die Felder -- im zugeklappten Zustand. Der Fehler + entsteht erst beim AUFKLAPPEN. Ein Zustand, der nie hergestellt + wird, kann nicht gemessen werden; die Pruefung war gruen und hat + dabei nie hingesehen. + + Gemessen war es dann eindeutig, bei 1280 px: + + Zelle Zeilen Hoehe Inhalt + feld-verant 24px 44px 68 107 + feld-mehrere 43px 44px 87 261 <-- 174 zu viel + + Die Zelle steckte in einer festen 44-Pixel-Zeile. Was herauslaeuft, + belegt keinen Platz -- also legt es sich ueber das Naechste. + + HIER WIRD NICHT DIESE EINE STELLE GEPRUEFT, sondern die Eigenschaft: + Jedes Element mit `aria-expanded` im Formular wird aufgeklappt, und + danach darf keine Rasterzelle mehr Inhalt haben, als sie hoch ist. + Damit faellt auch die naechste auf, die es noch gar nicht gibt. + ===================================================================== */ +console.log("\n=== Was aufklappt, bekommt auch Platz"); +{ + const kontext = await browser.newContext({ viewport: { width: 1280, height: 1000 } }); + const seite = await kontext.newPage(); + await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" }); + await seite.click('.rolle[data-rolle="admin"]'); + await seite.fill("#code", "CODE-DOGI-0001"); + await seite.click("button[type=submit]"); + await seite.waitForTimeout(900); + + let zellenGesamt = 0, aufgeklapptGesamt = 0; + const schlimm = []; + + for (const [wohin, knopf] of FORMULARE) { + await seite.goto(`${BASIS}/workspace/${wohin}`, { waitUntil: "networkidle" }); + await seite.waitForTimeout(900); + const auf = await seite.$(knopf); + if (!auf) continue; + await auf.click().catch(() => {}); + await seite.waitForTimeout(700); + + /* ALLES AUFKLAPPEN, was sich aufklappen laesst. */ + const wieViele = await seite.evaluate(() => { + const f = document.querySelector(".neu__raster"); + if (!f) return 0; + const knoepfe = [...f.querySelectorAll("[aria-expanded]")] + .filter((b) => b.offsetParent !== null); + for (const b of knoepfe) b.click(); + return knoepfe.length; + }); + await seite.waitForTimeout(600); + aufgeklapptGesamt += wieViele; + + const befund = await seite.evaluate(() => { + const r = document.querySelector(".neu__raster"); + if (!r) return { zellen: 0, zuEng: [] }; + const zellen = [...r.children].filter((c) => !c.hidden && c.offsetParent !== null); + + /* WIE TIEF REICHT DER INHALT WIRKLICH -- zwei Anlaeufe davor + waren falsch, und der zweite war der gefaehrlichere: + + (1) `scrollHeight` der Zelle. Meldete elf Zellen als kaputt, + die alle in Ordnung sind: Der Hinweis unter einem Feld + haengt seit dem 17.09. ABSICHTLICH absolut unter der Zelle + (`top: 100%`). Er ragt hinaus, das ist seine Aufgabe. Eine + Warnung, die bei richtigem Verhalten anschlaegt, wird + abgeschaltet. + + (2) Nur die DIREKTEN Kinder im Fluss. Das war gruen -- auch + mit dem echten Fehler. Nachgemessen mit + zurueckgenommener Behebung: immer noch gruen. Der Grund + ist das Raster selbst: Es staucht das Kind auf die feste + Zeilenhoehe, das Kind bleibt also brav in der Zelle. Was + herauslaeuft, ist der Inhalt DARIN. Eine Pruefung, die + nur eine Ebene tief sieht, sieht davon nichts. + + Also in die Tiefe -- aber nicht blind: Teilbaeume unter + absolut gesetzten Elementen bleiben aussen vor (siehe 1), und + wer selbst scrollt (`overflow` nicht `visible`), darf Inhalt + unterhalb haben; das ist der Sinn eines Rollbereichs. */ + const unten = (c) => { + const oben = c.getBoundingClientRect().top; + let tiefste = 0; + const geh = (el) => { + for (const k of el.children) { + const st = getComputedStyle(k); + if (st.position === "absolute" || st.position === "fixed") continue; + if (st.display === "none" || k.hidden) continue; + tiefste = Math.max(tiefste, k.getBoundingClientRect().bottom - oben); + if (st.overflow === "visible" && st.overflowY === "visible") geh(k); + } + }; + geh(c); + return Math.round(tiefste); + }; + const zuEng = zellen + /* 4 px Luft fuer Abrundungen im Rastermass. 174 px faellt + hier nicht durch. */ + .filter((c) => unten(c) > Math.round(c.getBoundingClientRect().height) + 4) + .map((c) => `${c.id || "(ohne Kennung)"}: Inhalt reicht bis ${unten(c)} px, ` + + `Zelle ist ${Math.round(c.getBoundingClientRect().height)} px hoch`); + return { zellen: zellen.length, zuEng }; + }); + zellenGesamt += befund.zellen; + for (const z of befund.zuEng) schlimm.push(`${wohin} — ${z}`); + } + + /* DIE ANZAHL GEHOERT IN DIE BEDINGUNG. Ohne sie waere „nichts laeuft + heraus" auch dann gruen, wenn gar nichts aufgeklappt wurde -- und + genau das war der Fehler der Pruefung darueber. */ + ok(zellenGesamt > 10, `${zellenGesamt} Rasterzellen angesehen`); + ok(aufgeklapptGesamt > 0, + `${aufgeklapptGesamt} aufklappbare Bereiche wirklich geoeffnet`); + ok(schlimm.length === 0 && aufgeklapptGesamt > 0, + schlimm.length + ? `${schlimm.length} Zelle(n) laufen aus ihrer Zeile heraus:\n ` + + schlimm.join("\n ") + : "keine Zelle laeuft aus ihrer Zeile heraus"); + + /* GEGENPROBE: Die Messung muss ein Herauslaufen auch SEHEN. Dafuer + wird eine Zelle kuenstlich eingeklemmt -- und danach wieder + freigegeben. Ohne diese Zeile waere „nichts laeuft heraus" die + Aussage einer Messung, von der niemand weiss, ob sie etwas + bemerken wuerde. */ + /* Fuer die Gegenprobe zurueck auf ein Formular, das offen ist -- der + letzte Durchlauf oben kann auf einer Seite geendet haben, die gar + keines hat. Eine Gegenprobe, die mangels Gelegenheit ausfaellt, + ist keine. */ + await seite.goto(`${BASIS}/workspace/aufgaben.html`, { waitUntil: "networkidle" }); + await seite.waitForTimeout(900); + await seite.click("#neu-oeffnen").catch(() => {}); + await seite.waitForTimeout(700); + + const probe = await seite.evaluate(() => { + /* Dieselbe Rechnung wie oben -- sonst prueft die Gegenprobe eine + andere Messung als die, um die es geht. */ + const unten = (c) => { + const oben = c.getBoundingClientRect().top; + let tiefste = 0; + const geh = (el) => { + for (const k of el.children) { + const st = getComputedStyle(k); + if (st.position === "absolute" || st.position === "fixed") continue; + if (st.display === "none" || k.hidden) continue; + tiefste = Math.max(tiefste, k.getBoundingClientRect().bottom - oben); + if (st.overflow === "visible" && st.overflowY === "visible") geh(k); + } + }; + geh(c); + return Math.round(tiefste); + }; + const r = document.querySelector(".neu__raster"); + const c = r && [...r.children].find((x) => !x.hidden && x.offsetParent !== null && unten(x) > 40); + if (!c) return null; + const vorher = c.style.height; + c.style.height = "12px"; + const erkannt = unten(c) > Math.round(c.getBoundingClientRect().height) + 4; + c.style.height = vorher; + const wiederGut = unten(c) <= Math.round(c.getBoundingClientRect().height) + 4; + return { erkannt, wiederGut }; + }); + ok(!!probe && probe.erkannt && probe.wiederGut, + probe ? "Gegenprobe: eine kuenstlich eingeklemmte Zelle wird erkannt" + : "KONNTE NICHT NACHSEHEN: keine Zelle fuer die Gegenprobe gefunden"); + + await kontext.close(); +} + await browser.close(); try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ } console.log(fehler ? `\n${fehler} Formular(e) fehlerhaft.` : "\nAlles in Ordnung."); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 1aa65f65..97e22552 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`. --> - - + + - +