Filipe, 22.09.2026: "ersetze die zentrale durch, Die IrrenAnstalt.
genau so geschrieben bitte. und alles was treff heißt oder wo treff
steht soll durch Rudel ersetzt werden bitte."
Die Schreibweise "IrrenAnstalt" mit grossem A in der Mitte ist so
gewollt. Das steht als Hinweis daneben, damit sie beim naechsten Mal
niemand "korrigiert".
WAS UMBENANNT WURDE: alles, was jemand LIEST -- Kachelnamen,
Ueberschriften, Markenzeilen, Saetze, Meldungen, Aufgabenvorlagen.
116 Zeilen in 42 Dateien.
WAS BLEIBT: Adressen (treff-regeln.html), Bezeichner (TREFF_ROLLEN),
Datenbankwerte (bereich = 'treff'), Abfrageteile (b=treff). Eine
Adresse umzubenennen bricht jedes Lesezeichen, und ein Datenbankwert
umzuschreiben waere eine Umstellung ohne Gegenwert. Dieselbe
Entscheidung wie heute frueh bei Dogi-Media, wo material.html auch
material.html geblieben ist.
DREI GRAMMATIKFEHLER IM EIGENEN ENTWURF, alle vor dem Ausliefern
gefunden -- ein blindes Ersetzen reicht hier nicht:
1. "der Treff" ist maennlich, "das Rudel" saechlich. Ohne Tabelle
waere ueberall "Der Rudel" gestanden. (Und "Treffer" waere zu
"Rudeler" geworden, "Treffen" zu "Rudelen" -- deshalb greift die
Regel nur bei Wortgrenze und nie vor einem Kleinbuchstaben.)
2. BINDESTRICH-ZUSAMMENSETZUNGEN. In "der Treff-Chat" gehoert der
Artikel zu "Chat", nicht zu "Treff". Der erste Durchlauf machte
daraus "das Rudel-Chat", "das Rudel-Kacheln" und "ein Rudel-Raum".
Jetzt greift die Artikelregel nur, wenn das Wort allein steht.
3. GESCHUETZTE LEERZEICHEN. In den Markenzeilen steht
`Der Treff`, damit die zwei Woerter nicht umbrechen. Das
Muster hat daran vorbeigegriffen: "Der Rudel", auf fuenf
Seiten. Jetzt wird das Trennzeichen mitgefasst und unveraendert
wieder eingesetzt.
Gefunden wurden alle drei, weil jede einzelne der 116 Zeilen vor dem
Schreiben als ALT/NEU ausgegeben und gelesen wurde -- und danach
gezielt nach falschen Artikeln gesucht ("den Rudel", "der Rudel",
"einen Rudel"). Uebrig blieben sechs Treffer, und die sind alle
richtig: "einen Rudel-Raum", "der Rudel-Chat", "den Rudel-Regeln" --
Zusammensetzungen, bei denen der Artikel zum letzten Wort gehoert.
UND ZWEI PRUEFUNGEN, die die Umbenennung nicht mitbekommen haetten:
`/Treff/.test(...)` und `/Treff/i.test(...)`. Ein regulaerer Ausdruck
ist keine Zeichenkette -- sie haetten ab sofort nach einem Wort
gesucht, das die Seite nicht mehr sagt, und waeren still rot geworden,
ohne dass etwas kaputt ist.
Geprueft, alle gruen: pruef-treff, pruef-treffchat,
pruef-deutsche-texte, pruef-uebernahme, pruef-crew-adresse,
pruef-willkommen, pruef-wege-nach-draussen, pruef-vorlagen,
pruef-start-ansicht, pruef-struktur.
Co-Authored-By: Claude Opus 5 <[email protected]>
377 lines
17 KiB
JavaScript
377 lines
17 KiB
JavaScript
/* =====================================================================
|
|
JEDER HAT EINE EIGENE SEITE -- UND ALLES STEHT IN DER RICHTIGEN
|
|
REIHENFOLGE (19.09.2026)
|
|
|
|
Zwei Auftraege von Filipe, die dieselbe Frage stellen: Was sieht wer,
|
|
und in welcher Ordnung?
|
|
|
|
"jeder soll ein steckbrief haben, jeder der ein account hat,
|
|
rechte hand, modis und community, jeder soll genau wie ich foto
|
|
und so hinzufuegen koennen."
|
|
|
|
"ich will das oben die sachen fuer dogfather sind, dan die sachen
|
|
fuer modis und dan community bereich ... was sie nicht sehen sehen
|
|
sie nicht."
|
|
|
|
WAS HIER SCHIEFGEHEN KANN, UND ZWAR LAUTLOS:
|
|
|
|
1. KACHEL OHNE TUER. Die Kachel steht da, die Seite ist zu -- ein
|
|
Knopf, der auf die Startseite zurueckwirft. Umgekehrt genauso:
|
|
Tuer offen, keine Kachel, also findet es niemand.
|
|
|
|
2. WER IN KEINEN ABSCHNITT PASST, VERSCHWINDET. Genau das war der
|
|
Fall: assets/js/steckbrief.js kannte drei Gruppen (Management,
|
|
Scouting, Creator). Die rechte Hand, die Modis und die Community
|
|
fielen heraus -- ohne Fehler, ohne leere Liste. Sie waren einfach
|
|
nicht da.
|
|
|
|
3. DIE REIHENFOLGE ENTSTEHT AUS VERSEHEN. Sie hing davon ab, welche
|
|
Kachelliste an welche angehaengt wurde. So landete die Moderation
|
|
hinter allen sieben Brettern der Community.
|
|
|
|
HINWEIS AN MICH SELBST: In den Meldungstexten stehen hier bewusst
|
|
KEINE typografischen Anfuehrungszeichen. Ein oeffnendes Zeichen, das
|
|
versehentlich mit einem geraden geschlossen wird, beendet den String
|
|
mitten im Satz -- das ist mir beim Schreiben dieser Datei zweimal
|
|
passiert. In Kommentaren sind sie harmlos, in Strings nicht.
|
|
|
|
Aufrufen mit: node server/pruef-jeder-hat-eine-seite.mjs
|
|
===================================================================== */
|
|
import { mkdtempSync, rmSync, readFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { request as httpAnfrage } from "node:http";
|
|
import { eigenerPort } from "./helfer-port.mjs";
|
|
|
|
const PORT = await eigenerPort(import.meta, "pruef-jeder-hat-eine-seite");
|
|
const ordner = mkdtempSync(join(tmpdir(), "ws-seite-"));
|
|
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
|
|
process.env.PORT = String(PORT);
|
|
process.env.SITE_ACCESS_SECRET = "lokaler-test";
|
|
process.env.SITE_PUBLIC_LAUNCH_AT = "2020-01-01T00:00:00+01:00";
|
|
|
|
const express = (await import("express")).default;
|
|
const ec = express.response.cookie;
|
|
express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...(o || {}), secure: false }); };
|
|
import { notbremse } from "./helfer-notbremse.mjs";
|
|
await import("./index.js");
|
|
notbremse(150_000, "pruef-jeder-hat-eine-seite");
|
|
await new Promise((r) => setTimeout(r, 700));
|
|
|
|
process.on("uncaughtException", (f) => { console.error("ABSTURZ:", f); process.exit(7); });
|
|
|
|
let fehler = 0, geprueft = 0;
|
|
const melde = (t) => console.log(t);
|
|
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
|
|
|
|
const CREW = "crew.dogfather-universe.com";
|
|
const WURZEL = join(import.meta.dirname, "..");
|
|
|
|
function roh(pfad, host, kopf = {}, koerper = null) {
|
|
return new Promise((fertig, schief) => {
|
|
const a = httpAnfrage({
|
|
host: "127.0.0.1", port: PORT, path: pfad,
|
|
method: koerper ? "POST" : "GET",
|
|
headers: { Host: host, ...(koerper ? { "Content-Type": "application/json" } : {}), ...kopf },
|
|
}, (antwort) => {
|
|
let text = "";
|
|
antwort.on("data", (s) => { text += s; });
|
|
antwort.on("end", () => fertig({ code: antwort.statusCode, text, kopf: antwort.headers }));
|
|
});
|
|
a.on("error", schief);
|
|
if (koerper) a.write(JSON.stringify(koerper));
|
|
a.end();
|
|
});
|
|
}
|
|
const json = (a) => { try { return JSON.parse(a.text); } catch { return {}; } };
|
|
|
|
const { DatabaseSync } = await import("node:sqlite");
|
|
const { scryptSync, randomBytes } = await import("node:crypto");
|
|
|
|
/* Eine Person je Rolle, die im Treff vorkommt -- plus eine aus der
|
|
Agentur als Gegenprobe. */
|
|
const LEUTE = [
|
|
["Filipe", "admin", "CODE-DOGI-0001"],
|
|
["Rieke", "hand", "CODE-HAND-0001"],
|
|
["Kessi", "modi", "CODE-MODI-0001"],
|
|
["Mara", "gast", "CODE-GAST-0001"],
|
|
["Nico", "creator", "CODE-CREA-0001"],
|
|
];
|
|
{
|
|
const d = new DatabaseSync(process.env.WORKSPACE_DB);
|
|
for (const [name, rolle, code] of LEUTE) {
|
|
const salz = randomBytes(16).toString("hex");
|
|
const hash = scryptSync(code, salz, 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 (?,?,?,?,?,1,?)")
|
|
.run(name, rolle, hash, salz, 32768, new Date().toISOString());
|
|
}
|
|
d.close();
|
|
}
|
|
|
|
async function anmelden(rolle, code, host) {
|
|
let a = await roh("/workspace/api/anmelden", host, {}, { rolle, code });
|
|
if (a.code === 400 && a.text.includes("alter_offen")) {
|
|
a = await roh("/workspace/api/anmelden", host, {}, { rolle, code, alter_ok: true });
|
|
}
|
|
return [].concat(a.kopf["set-cookie"] || []).map((z) => z.split(";")[0]).join("; ");
|
|
}
|
|
|
|
/* WELCHE ADRESSE GEHOERT ZU WELCHER ROLLE. Die Trennung der beiden
|
|
Haeuser ist eine Hausregel, keine Nebensache: Team Dogi und die
|
|
Community leben auf crew.*, die Agentur auf workspace.*. Wer das in
|
|
einer Pruefung uebersieht, misst eine Schranke und nennt sie Fehler. */
|
|
const AGENTUR = "workspace.dogfather-universe.com";
|
|
const HAUS_VON = {
|
|
admin: CREW, hand: CREW, modi: CREW, gast: CREW,
|
|
creator: AGENTUR, scout: AGENTUR, manager: AGENTUR, spicy: AGENTUR,
|
|
};
|
|
|
|
const kekse = {};
|
|
for (const [, rolle, code] of LEUTE) kekse[rolle] = await anmelden(rolle, code, HAUS_VON[rolle]);
|
|
|
|
/* =======================================================================
|
|
1. JEDER KOMMT AUF SEINE EIGENE SEITE
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 1. Die Tuer zum Steckbrief ===");
|
|
{
|
|
/* JEDE ROLLE AUF IHRER EIGENEN ADRESSE.
|
|
|
|
Der erste Lauf hat hier einen echten Unterschied sichtbar gemacht:
|
|
Ein Creator bekommt auf crew.dogfather-universe.com eine 302 --
|
|
die Hausregel trennt Agentur und Team Dogi, und das ist richtig
|
|
so. Haette ich die Pruefung nicht danach getrennt, haette ich ein
|
|
funktionierendes Schloss fuer einen Fehler gehalten. */
|
|
for (const [name, rolle] of LEUTE) {
|
|
const haus = HAUS_VON[rolle];
|
|
const a = await roh("/workspace/steckbrief.html", haus, { cookie: kekse[rolle] });
|
|
ok(a.code === 200, `${name} kommt auf den Steckbrief (${a.code}, ${haus})`);
|
|
}
|
|
const b = await roh("/workspace/steckbrief.html", CREW);
|
|
ok(b.code === 302 || b.code === 401 || b.code === 403,
|
|
`ohne Anmeldung nicht (${b.code})`);
|
|
}
|
|
|
|
melde("");
|
|
melde("=== 2. Und bekommt dort seinen eigenen Eintrag ===");
|
|
{
|
|
for (const [name, rolle] of LEUTE) {
|
|
const a = json(await roh("/workspace/api/steckbrief/mein", HAUS_VON[rolle], { cookie: kekse[rolle] }));
|
|
ok(a.steckbrief?.name === name,
|
|
`${name} sieht seinen eigenen (${a.steckbrief?.name})`);
|
|
/* DAS FELD FUERS BILD MUSS DA SEIN -- sonst gibt es nichts
|
|
hochzuladen, und Filipes Satz (genau wie ich foto und so
|
|
hinzufuegen) waere nicht erfuellt. */
|
|
ok("bild" in (a.steckbrief || {}), " und hat ein Feld fuers Bild");
|
|
ok(Array.isArray(a.kanaele) && a.kanaele.length > 0,
|
|
` und ${a.kanaele?.length} Kanaele zum Eintragen`);
|
|
}
|
|
}
|
|
|
|
/* =======================================================================
|
|
3. NIEMAND FAELLT AUS DER UEBERSICHT
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 3. Jede Rolle hat einen Abschnitt ===");
|
|
{
|
|
const { ROLLEN_NAME } = await import("./workspace.js");
|
|
const alleRollen = Object.keys(ROLLEN_NAME);
|
|
ok(alleRollen.length >= 6, `es gibt ${alleRollen.length} Rollen im Haus`);
|
|
|
|
const a = json(await roh("/workspace/api/steckbrief", CREW, { cookie: kekse.admin }));
|
|
const liste = a.steckbriefe || [];
|
|
/* NICHT ALLE FUENF -- UND DAS IST RICHTIG SO.
|
|
|
|
Der erste Lauf erwartete hier fuenf und bekam vier. Der Fehler lag
|
|
in der Erwartung: Auf der Crew-Adresse gehoert der Creator nicht
|
|
dazu, die beiden Haeuser sind getrennt. Haette ich die Zahl auf
|
|
`>= 1` gesetzt, waere die Pruefung gruen geworden und haette
|
|
nichts mehr gemessen -- also wird genau das geprueft, was gelten
|
|
soll: die vier aus dem Haus, und der Creator NICHT. */
|
|
const drin = liste.map((z) => z.name).sort();
|
|
ok(drin.length === 4 && !drin.includes("Nico"),
|
|
`auf der Crew-Adresse sieht DogFather die vier des Hauses: ${drin.join(", ")}`);
|
|
|
|
let ohneAbschnitt = 0;
|
|
const unterWeitere = [];
|
|
for (const p of liste) {
|
|
if (!p.abschnitt) ohneAbschnitt++;
|
|
else if (p.abschnitt === "Weitere") unterWeitere.push(`${p.name} (${p.rolle})`);
|
|
}
|
|
ok(liste.length > 0 && ohneAbschnitt === 0,
|
|
`alle ${liste.length} haben einen Abschnitt (${ohneAbschnitt} ohne)`);
|
|
ok(unterWeitere.length === 0,
|
|
`keiner landet im Sammelplatz Weitere${unterWeitere.length ? ": " + unterWeitere.join(", ") : ""}`);
|
|
|
|
/* JEDE ROLLE DES HAUSES, nicht nur die fuenf angelegten Leute.
|
|
Sonst waere dieser Abschnitt eine Aussage ueber meine Testdaten. */
|
|
const { abschnittFuer } = await import("./workspace-steckbrief.js");
|
|
const vergessen = alleRollen.filter((r) => abschnittFuer(r).name === "Weitere");
|
|
ok(vergessen.length === 0,
|
|
`alle ${alleRollen.length} Rollen sind zugeordnet${vergessen.length ? " -- fehlt: " + vergessen.join(", ") : ""}`);
|
|
|
|
/* GEGENPROBE. Ohne sie waere "niemand faellt heraus" auch dann wahr,
|
|
wenn gar nichts zugeordnet wuerde. */
|
|
ok(abschnittFuer("gibtsnicht").name === "Weitere",
|
|
"eine unbekannte Rolle landet sichtbar im Sammelplatz, statt zu verschwinden");
|
|
|
|
/* UND KEINE ROLLENNAMEN DER COMMUNITY IM BROWSER. */
|
|
const jsDatei = readFileSync(join(WURZEL, "workspace/assets/js/steckbrief.js"), "utf8");
|
|
let gefunden = [];
|
|
for (const wort of ["'modi'", "'hand'", "'gast'", '"modi"', '"hand"', '"gast"']) {
|
|
if (jsDatei.includes(wort)) gefunden.push(wort);
|
|
}
|
|
ok(gefunden.length === 0,
|
|
`keine Rollennamen in der ausgelieferten Datei${gefunden.length ? ": " + gefunden.join(", ") : ""}`);
|
|
}
|
|
|
|
/* =======================================================================
|
|
4. DIE REIHENFOLGE DER GRUPPEN
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 4. Oben die Arbeit, dann Moderation, dann Community ===");
|
|
{
|
|
const { bereicheFuer } = await import("./workspace.js");
|
|
|
|
const folgeVon = (rolle) => {
|
|
const k = bereicheFuer({ rolle });
|
|
if (!Array.isArray(k)) return null;
|
|
const gesehen = [];
|
|
for (const x of k) if (!gesehen.includes(x.gruppe)) gesehen.push(x.gruppe);
|
|
return gesehen;
|
|
};
|
|
|
|
const modi = folgeVon("modi");
|
|
ok(!!modi?.includes("Moderation"),
|
|
`ein Modi hat eine eigene Moderationsgruppe (${modi?.join(" | ")})`);
|
|
ok(!!modi?.includes("Community"), "und die Community daneben");
|
|
/* SIE MUESSEN GETRENNT SEIN -- vorher trug die Moderationskachel
|
|
dieselbe Gruppe wie die Bretter und verschwand darin. */
|
|
ok(modi?.indexOf("Moderation") !== modi?.indexOf("Community"),
|
|
"und beide sind wirklich zwei Gruppen, nicht eine");
|
|
|
|
const gast = folgeVon("gast");
|
|
ok(!!gast?.includes("Community"), `ein Mitglied hat das Rudel (${gast?.join(" | ")})`);
|
|
ok(!!gast?.includes("Für dich"), "und eine eigene Seite");
|
|
/* Was sie nicht sehen, sehen sie nicht. */
|
|
ok(!gast?.includes("Moderation"), "aber KEINE Moderation");
|
|
ok(!gast?.includes("Täglich"), "und keine Arbeitsgruppe des Teams");
|
|
|
|
/* DIE SORTIERREGEL IM BROWSER MUSS DIESELBEN NAMEN KENNEN. Eine
|
|
Gruppe, die dort fehlt, landet bei den Arbeitsgruppen -- fuer die
|
|
Community waere das genau falsch herum. */
|
|
const startJs = readFileSync(join(WURZEL, "workspace/assets/js/start.js"), "utf8");
|
|
const zuletzt = /GRUPPEN_ZULETZT\s*=\s*\[([^\]]*)\]/s.exec(startJs)?.[1] || "";
|
|
ok(zuletzt.length > 0, "die Sortierliste steht in start.js");
|
|
for (const g of ["Moderation", "Community", "Für dich"]) {
|
|
ok(zuletzt.includes(g), `${g} steht in der Liste am Ende`);
|
|
}
|
|
/* UND DIE ARBEITSGRUPPEN STEHEN NICHT DARIN. Sie behalten ihre
|
|
gewachsene Reihenfolge -- eine Liste, die auch sie festschreibt,
|
|
ueberschreibt bestehende Entscheidungen, ohne sie gelesen zu haben. */
|
|
for (const g of ["Täglich", "Rund ums Live", "Rund um den Creator"]) {
|
|
ok(!zuletzt.includes(g), `${g} wird NICHT ans Ende geschoben`);
|
|
}
|
|
|
|
/* JEDE GRUPPE, DIE ES GIBT, MUSS IN EINER DER BEIDEN LISTEN STEHEN.
|
|
Sonst landet sie stillschweigend bei der Arbeit -- was fuer die
|
|
meisten richtig ist, aber nicht fuer alle. Diese Zeile findet die
|
|
naechste neue Gruppe, bevor sie an der falschen Stelle auftaucht. */
|
|
const alleGruppen = new Set();
|
|
for (const rolle of ["admin", "hand", "modi", "gast"]) {
|
|
for (const g of folgeVon(rolle) || []) alleGruppen.add(g);
|
|
}
|
|
ok(alleGruppen.size >= 5,
|
|
`${alleGruppen.size} Gruppen im Haus: ${[...alleGruppen].join(", ")}`);
|
|
}
|
|
|
|
/* =======================================================================
|
|
5. IM BROWSER -- steht die Kachel da, und in welcher Reihenfolge?
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 5. Im Browser ===");
|
|
{
|
|
let pw = null;
|
|
try {
|
|
pw = await import("file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
|
|
} catch { /* dritter Ausgang */ }
|
|
|
|
if (!pw) {
|
|
melde(" -- Playwright ist nicht da -- im Browser wurde NICHT nachgesehen.");
|
|
melde(" Das ist kein Befund. Die Abschnitte 1-4 gelten weiter.");
|
|
} else {
|
|
const browser = await pw.chromium.launch();
|
|
try {
|
|
for (const [name, rolle] of [["Mara", "gast"], ["Kessi", "modi"], ["Filipe", "admin"]]) {
|
|
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1000 } });
|
|
await ctx.addCookies(kekse[rolle].split("; ").filter(Boolean).map((z) => {
|
|
const [n, ...r] = z.split("=");
|
|
return { name: n, value: r.join("="), domain: "127.0.0.1", path: "/" };
|
|
}));
|
|
const seite = await ctx.newPage();
|
|
const kaputt = [];
|
|
seite.on("pageerror", (e) => kaputt.push(String(e).slice(0, 140)));
|
|
|
|
await seite.goto(`http://127.0.0.1:${PORT}/workspace/start.html`, { waitUntil: "networkidle" });
|
|
await seite.waitForTimeout(900);
|
|
|
|
const gruppen = await seite.evaluate(() =>
|
|
[...document.querySelectorAll(".gruppe")].map((g) =>
|
|
(g.querySelector("h2, .gruppe__name")?.textContent || "").trim()).filter(Boolean));
|
|
|
|
melde(` --- ${name} sieht: ${gruppen.join(" | ")}`);
|
|
ok(gruppen.length > 0, `${name}: es werden Gruppen angezeigt (${gruppen.length})`);
|
|
|
|
const hatSteckbrief = await seite.evaluate(() =>
|
|
!!document.querySelector('a[href*="steckbrief.html"]'));
|
|
ok(hatSteckbrief, `${name}: die Steckbrief-Kachel ist da`);
|
|
|
|
const platz = (n) => gruppen.findIndex((g) => g.includes(n));
|
|
const pFuer = platz("Für dich"), pCom = platz("Community"), pMod = platz("Moderation");
|
|
if (pFuer >= 0 && pCom >= 0) {
|
|
ok(pFuer > pCom, ` das Eigene steht hinter der Community (${pFuer} > ${pCom})`);
|
|
}
|
|
if (pMod >= 0 && pCom >= 0) {
|
|
ok(pMod < pCom, ` die Moderation steht VOR der Community (${pMod} < ${pCom})`);
|
|
}
|
|
if (pMod >= 0) {
|
|
const pArbeit = gruppen.findIndex((g) => /Täglich|Rund ums Live|Rund um das Team/.test(g));
|
|
if (pArbeit >= 0) {
|
|
ok(pArbeit < pMod, ` die eigene Arbeit steht ganz oben (${pArbeit} < ${pMod})`);
|
|
}
|
|
}
|
|
if (rolle === "gast") {
|
|
ok(pMod === -1, " ein Mitglied sieht KEINE Moderationsgruppe");
|
|
}
|
|
|
|
await seite.goto(`http://127.0.0.1:${PORT}/workspace/steckbrief.html`,
|
|
{ waitUntil: "networkidle" });
|
|
await seite.waitForTimeout(900);
|
|
const eigen = await seite.evaluate(() => ({
|
|
name: document.getElementById("sb-name")?.textContent?.trim() || "",
|
|
hatDatei: !!document.getElementById("sb-datei"),
|
|
hatSpeichern: !!document.getElementById("sb-speichern"),
|
|
abschnitte: [...document.querySelectorAll(".team-gruppe__name")].map((x) => x.textContent.trim()),
|
|
}));
|
|
ok(eigen.name === name, ` sein Steckbrief zeigt den Namen (${eigen.name})`);
|
|
ok(eigen.hatDatei && eigen.hatSpeichern,
|
|
" mit Feld fuers Bild und Speichern-Knopf");
|
|
melde(` Abschnitte dort: ${eigen.abschnitte.join(", ") || "(keine)"}`);
|
|
ok(kaputt.length === 0,
|
|
` kein Skriptfehler${kaputt.length ? ": " + kaputt.join(" | ") : ""}`);
|
|
await ctx.close();
|
|
}
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
melde("");
|
|
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
|
|
melde(fehler ? "NICHT IN ORDNUNG" : "ALLES IN ORDNUNG");
|
|
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* Rest */ }
|
|
process.exit(fehler ? 1 : 0);
|