diff --git a/pruef-personen.png b/pruef-personen.png index 6d36a19c..46ffde66 100644 Binary files a/pruef-personen.png and b/pruef-personen.png differ diff --git a/server/pruef-personen-liste.mjs b/server/pruef-personen-liste.mjs index 1f374562..f5108f45 100644 --- a/server/pruef-personen-liste.mjs +++ b/server/pruef-personen-liste.mjs @@ -1,10 +1,16 @@ /* =================================================================== - Pruefung: In der Personenliste steht standardmaessig nur DogFather, - alle anderen kommen auf Knopfdruck dazu. + Pruefung: Die Personenliste ist je Rolle auf- und zuklappbar. - Der wichtigste Punkt ist der letzte: Verstecken ist eine ANSICHT, kein - Recht. Wer eingeklappt ist, hat unveraendert Zugang -- der Server darf - davon gar nichts mitbekommen. + Zwei Dinge sind dabei wichtiger als alles andere: + + 1. Die UEBERSCHRIFT mit der Anzahl bleibt immer stehen, auch + zugeklappt. Das ist der Unterschied zum Ausblenden: Man sieht + jederzeit, DASS es einen Manager gibt -- nur nicht, welchen. Wer + eine ganze Rolle spurlos verschwinden laesst, haelt sie irgendwann + fuer leer. + + 2. Zuklappen ist eine ANSICHT, kein Recht. Wer zugeklappt ist, hat + unveraendert Zugang -- der Server bekommt davon gar nichts mit. =================================================================== */ import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; @@ -24,7 +30,7 @@ express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...( await import("./index.js"); await new Promise((r) => setTimeout(r, 700)); const BASIS = "http://127.0.0.1:4187"; -setTimeout(() => { console.log("ABBRUCH"); process.exit(1); }, 180_000).unref?.(); +setTimeout(() => { console.log("ABBRUCH"); process.exit(1); }, 200_000).unref?.(); let fehler = 0; const ok = (b, t) => { console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; }; @@ -42,7 +48,6 @@ function anlegen(name, rolle, code, aktiv = 1) { const hash = scryptSync(code, salt, 64, { N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex"); d.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, aktiv, erstellt) VALUES (?,?,?,?,?,?,?)") .run(name, rolle, hash, salt, 32768, aktiv, jetzt); - return d.prepare("SELECT last_insert_rowid() AS id").get().id; } /* Genau die Aufstellung aus dem Bild vom 31.08.2026. */ anlegen("Dogfather", "admin", "CODE-DOGI-0001"); @@ -72,115 +77,136 @@ async function seiteFuer(kontext) { const lesen = (seite) => seite.evaluate(() => ({ namen: [...document.querySelectorAll(".person__name")].map((n) => n.textContent.replace(" (du)", "")), - /* Die Abschnitte in der Reihenfolge, in der sie tatsächlich stehen -- - nicht in der, in der sie gemeint waren. */ abschnitte: [...document.querySelectorAll(".gruppe")].map((g) => ({ name: g.querySelector(".gruppe__name")?.textContent, zahl: g.querySelector(".gruppe__zahl")?.textContent, unter: g.querySelector(".gruppe__unter")?.textContent, + auf: g.querySelector(".gruppe__kopf")?.getAttribute("aria-expanded"), + knopf: g.querySelector(".gruppe__kopf")?.tagName, personen: [...g.querySelectorAll(".person__name")].map((n) => n.textContent.replace(" (du)", "")), })), knopfDa: !document.getElementById("rest-schalter")?.hidden, knopfText: document.getElementById("rest-schalter-text")?.textContent, - auf: document.getElementById("rest-schalter")?.getAttribute("aria-expanded"), ueber: document.documentElement.scrollWidth - document.documentElement.clientWidth, })); +const klick = (seite, rolle) => + seite.locator(".gruppe__kopf", { hasText: new RegExp("^" + rolle) }).first().click(); + const kontext = await browser.newContext({ viewport: { width: 1440, height: 1100 } }); const konsole = []; const seite = await seiteFuer(kontext); seite.on("console", (m) => { if (m.type() === "error") konsole.push(m.text()); }); seite.on("pageerror", (e) => konsole.push("pageerror: " + e.message)); -console.log("\n1) Standardmäßig nur DogFather"); +console.log("\n1) Alle vier Überschriften stehen da – offen ist nur DogFather"); { const r = await lesen(seite); - console.log(" sichtbar:", r.namen.join(", ")); - console.log(" Knopf: ", r.knopfText); - ok(r.namen.length === 2, `zwei Personen sichtbar (${r.namen.length})`); - ok(r.abschnitte.length === 1 && r.abschnitte[0].name === "DogFather", - `zugeklappt steht nur der DogFather-Abschnitt da (${r.abschnitte.map((a) => a.name).join(", ") || "keiner"})`); + console.log(" ", r.abschnitte.map((a) => `${a.name}(${a.zahl},${a.auf === "true" ? "auf" : "zu"})`).join(" · ")); + + ok(r.abschnitte.length === 4, `vier Überschriften, auch zugeklappt (${r.abschnitte.length})`); + ok(r.abschnitte.map((a) => a.name).join(",") === "DogFather,Manager,Scout,Creator", + `Reihenfolge wie auf der Zugangsseite (${r.abschnitte.map((a) => a.name).join(", ")})`); + ok(r.abschnitte.map((a) => a.zahl).join(",") === "2,1,2,2", + `mit den Anzahlen (${r.abschnitte.map((a) => a.zahl).join(", ")})`); + + ok(r.namen.length === 2, `aber nur zwei Personen sichtbar (${r.namen.length})`); ok(r.namen.includes("Dogfather") && r.namen.includes("VanVan"), `Dogfather und VanVan (${r.namen.join(", ")})`); - ok(!r.namen.includes("Tili"), "kein Creator"); - ok(!r.namen.includes("Patrick"), "kein Scout"); - ok(r.knopfDa, "der Knopf ist da"); - /* Die ZAHL gehoert auf den Knopf -- "Alle zeigen" sagt nicht, wie - viele man gerade nicht sieht. */ - ok(/5 weitere zeigen/.test(r.knopfText || ""), `mit der Anzahl (${r.knopfText})`); - ok(/1 gesperrt/.test(r.knopfText || ""), "und dem Hinweis auf die gesperrte Person"); - ok(r.auf === "false", `aria-expanded=false (${r.auf})`); + ok(r.abschnitte[0].auf === "true", `DogFather ist offen (${r.abschnitte[0].auf})`); + ok(r.abschnitte.slice(1).every((a) => a.auf === "false"), "die anderen drei sind zu"); + + /* Als echtes