Zahlen-Seite: wieder fuer alle fuenf Rollen
Filipe, mit der Kachel im Bild: "jetzt soll jede rolle diese kachel sehen. spicy, dogfather, manager, scout und creator. aber die creator kriegen dan quasi nur ihre daten zu sehen und der manager scout dogfather oder spicy koennen eintragen." Damit ist die Sperre vom 07.09.2026 aufgehoben. Geaendert sind genau zwei Zeilen -- die Kachel in bereiche.js und die Tuer in workspace.js. Ausdruecklich als Liste der fuenf Rollen, NICHT als `null`: `null` hiesse auch jede Rolle, die es noch nicht gibt. WER WAS DARF, musste ich nicht bauen -- es stand schon da und konnte nur niemand benutzen: sichtbareCreatorIds() gibt einem Creator genau seine eigene Nummer, darfEintragen() ist Leitung plus Scout. Das ist exakt Filipes Satz, ohne eine einzige Aenderung am Server. WAS DER UMBAU AUFGEDECKT HAT: "Aus Datei einlesen" hatte als einziger Knopf NIE eine Rechteregel -- folgenlos, solange nur DogFather hereinkam, ab heute haette ein Creator ihn gesehen und eine Absage bekommen. Alle drei Eintrag-Knoepfe stehen jetzt in EINER Liste mit ihrer Regel daneben, und der Knopf startet `hidden`, damit er nicht kurz aufblitzt. Gefunden hat das nicht das Nachdenken, sondern die Gegenprobe von heute Mittag: Sie wurde rot, weil der Test-Scout auf der Startseite landete -- waehrend ich nebenan eine Erklaerung "fuer Scouts und Manager" schrieb fuer eine Seite, die beide gar nicht oeffnen konnten. pruef-backstage-import: 36 -> 50 Pruefungen. Gemessen wird der UNTERSCHIED zwischen den Rollen, nicht die Anwesenheit von irgendetwas: jeder Knopf einzeln, bei Scout und Creator, dazu die Kachel auf der Startseite und die Gegenprobe, dass die Zahlen des Creators trotzdem dastehen. Sonst waere "der Creator sieht keinen Knopf" auch dann gruen, wenn seine Seite leer bliebe. Mit SCHIRM=1 legt die Pruefung zwei Bilder ab, eins je Rolle. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -72,7 +72,7 @@ await starten();
|
||||
kind.kill();
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
|
||||
let idNova, idKiro, idLumi;
|
||||
let idNova, idKiro, idLumi, idSam;
|
||||
{
|
||||
const d = new DatabaseSync(DB);
|
||||
const anlegen = (name, rolle, code, tiktok) => {
|
||||
@@ -84,13 +84,20 @@ let idNova, idKiro, idLumi;
|
||||
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
||||
};
|
||||
anlegen("Filipe", "admin", "CODE-DOGI-0001");
|
||||
anlegen("Sam", "scout", "CODE-SAM-00001");
|
||||
idSam = anlegen("Sam", "scout", "CODE-SAM-00001");
|
||||
/* Nova hat ein Handle, Kiro NICHT -- er wird ueber den Namen
|
||||
gefunden. Lumi hat ein Handle mit anderer Schreibweise als in der
|
||||
Tabelle: Genau daran zeigt sich, ob normalisiert wird. */
|
||||
idNova = anlegen("Nova", "creator", "CODE-NOVA-0001", "nova_live");
|
||||
idKiro = anlegen("Kiro", "creator", "CODE-KIRO-0001", null);
|
||||
idLumi = anlegen("Lumi", "creator", "CODE-LUMI-0001", "LumiStreamt");
|
||||
/* Sam betreut Nova. Ohne diese Zeile haette der Scout gar keinen
|
||||
Creator -- die Seite waere leer, und eine Pruefung auf "der Scout
|
||||
sieht den Backstage-Satz NICHT" waere gruen, weil er ueberhaupt
|
||||
nichts sieht. Das ist der Unterschied zwischen einem Beweis und
|
||||
einem Zufall. */
|
||||
d.prepare("INSERT INTO betreuung (creator_id, betreuer_id, seit) VALUES (?,?,?)")
|
||||
.run(idNova, idSam, jetzt);
|
||||
d.close();
|
||||
}
|
||||
await starten();
|
||||
@@ -268,6 +275,17 @@ console.log("\n=== Gegenproben ===");
|
||||
ok(status === 200, `heute als Tag geht dagegen durch (HTTP ${status})`);
|
||||
}
|
||||
|
||||
/* Vorbedingung fuer die Gegenprobe weiter unten: Sam MUSS Nova sehen.
|
||||
Sonst waere "der Scout sieht den Backstage-Satz nicht" nur die
|
||||
Auskunft, dass seine Seite leer ist. */
|
||||
{
|
||||
const a = await fetch(BASIS + "/workspace/api/leistung", { headers: { Cookie: keksScout } });
|
||||
const d = await a.json().catch(() => ({}));
|
||||
const namen = (d.creator || []).map((c) => c.name).join(", ");
|
||||
ok(/Nova/.test(namen),
|
||||
`der Scout sieht seinen Creator in der Liste (${namen || "leer"})`);
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
7. Und die Seite selbst
|
||||
======================================================================= */
|
||||
@@ -320,8 +338,14 @@ console.log("\n=== Die Seite ===");
|
||||
|
||||
await seite.click("#netz-zu");
|
||||
await seite.waitForTimeout(300);
|
||||
const hinweis = await seite.$eval("#quellen-hinweis", (e) => (e.hidden ? "" : e.textContent));
|
||||
ok(/Backstage/.test(hinweis) && /TikTok-Datei/.test(hinweis),
|
||||
/* Gemessen wird SATZ FUER SATZ, nicht der Block. Ein Block, der
|
||||
als Ganzes erscheint, erklaert einem Scout auch den Knopf, den er
|
||||
nicht hat -- das ist keine Hilfe, sondern eine Absage. */
|
||||
const satz = (id) => seite.$eval(id, (e) => (e.hidden ? "" : e.textContent))
|
||||
.catch(() => "");
|
||||
const netzSatz = await satz("#quelle-netz");
|
||||
const ttSatz = await satz("#quelle-tt");
|
||||
ok(/Backstage/.test(netzSatz) && /TikTok-Datei/.test(ttSatz),
|
||||
"unter den Knöpfen steht dauerhaft, was die beiden Quellen sind");
|
||||
|
||||
/* Und der fertige Text für den Creator -- mit den zwei Angaben, an
|
||||
@@ -335,6 +359,126 @@ console.log("\n=== Die Seite ===");
|
||||
"und den Weg in der App");
|
||||
ok(/nicht gespeichert/.test(fuerCreator),
|
||||
"und was mit der Datei passiert -- das gehört dem Creator gesagt");
|
||||
|
||||
/* ---- DIESELBE SEITE, ANDERE ROLLE (11.09.2026) -----------------
|
||||
Filipe, mit der Kachel im Bild: "jetzt soll jede rolle diese
|
||||
kachel sehen. spicy, dogfather, manager, scout und creator. aber
|
||||
die creator kriegen dan quasi nur ihre daten zu sehen und der
|
||||
manager scout dogfather oder spicy koennen eintragen."
|
||||
|
||||
Bis heute war die Seite auf ["admin"] gesperrt. Dass ich das
|
||||
ueberhaupt gemerkt habe, verdanke ich dieser Gegenprobe: Sie
|
||||
wurde rot, weil Sam auf der Startseite landete -- waehrend ich
|
||||
nebenan eine Erklaerung "fuer Scouts und Manager" schrieb.
|
||||
|
||||
GEPRUEFT WIRD DER UNTERSCHIED, NICHT DIE ANWESENHEIT. Ein Scout
|
||||
und ein Creator sehen dieselbe Seite; was sie unterscheidet, sind
|
||||
die Knoepfe. Deshalb wird bei beiden JEDER Knopf einzeln gemessen
|
||||
-- ein "sieht etwas" waere bei beiden gruen und wertlos. */
|
||||
const rollenBild = async (rolle, code) => {
|
||||
const c = await browser.newContext({ viewport: { width: 1400, height: 1000 } });
|
||||
const p = await c.newPage();
|
||||
const fehler = [];
|
||||
p.on("pageerror", (e) => fehler.push(String(e).slice(0, 140)));
|
||||
await p.goto(BASIS + "/workspace/", { waitUntil: "networkidle" });
|
||||
await p.click(`.rolle[data-rolle="${rolle}"]`);
|
||||
await p.fill("#code", code);
|
||||
await p.click("button[type=submit]");
|
||||
await p.waitForURL("**/start.html", { timeout: 25000 });
|
||||
/* Erst die Kachel: Ein Weg, den man nur ueber die Adresse findet,
|
||||
ist kein Weg. Filipe hat ausdruecklich die KACHEL gezeigt.
|
||||
|
||||
ABWARTEN, BIS SIE DA SIND. Der erste Entwurf las sofort nach
|
||||
waitForURL -- da hatte das Skript die Kacheln noch gar nicht
|
||||
gebaut, und die Pruefung meldete "keine Kachel" fuer beide
|
||||
Rollen. Das war kein Befund, das war eine zu frueh gestellte
|
||||
Frage. Und weil KEINE Kachel gefunden wurde, haette ein
|
||||
schlichtes "mindestens eine" den Fehler auch nicht bemerkt. */
|
||||
await p.waitForSelector(".kachel__link", { timeout: 20000 });
|
||||
const kachel = await p.evaluate(() =>
|
||||
[...document.querySelectorAll("a[href]")]
|
||||
.some((a) => (a.getAttribute("href") || "").includes("leistung.html")));
|
||||
await p.goto(BASIS + "/workspace/leistung.html", { waitUntil: "networkidle" });
|
||||
await p.waitForTimeout(1800);
|
||||
const bild = await p.evaluate(() => {
|
||||
const h = (id) => {
|
||||
const e = document.getElementById(id);
|
||||
return e ? e.hidden : "fehlt";
|
||||
};
|
||||
return {
|
||||
weg: location.pathname,
|
||||
kacheln: 0,
|
||||
import: h("import-oeffnen"), netz: h("netz-oeffnen"), tt: h("tt-oeffnen"),
|
||||
ziele: h("ziele-aendern"),
|
||||
block: h("quellen-hinweis"), sNetz: h("quelle-netz"), sTt: h("quelle-tt"),
|
||||
/* Wie viele Creator stehen zur Auswahl? Ein Creator darf hier
|
||||
kein Auswahlfeld haben -- es haette nur ihn selbst drin. */
|
||||
wahl: document.getElementById("creator-wahl")?.hidden === false
|
||||
? document.querySelectorAll("#creator option").length : 0,
|
||||
aendern: document.querySelectorAll(".tagzeile__knopf").length,
|
||||
};
|
||||
});
|
||||
bild.kachel = kachel;
|
||||
bild.fehler = fehler.join(" | ");
|
||||
/* Bilder nur auf Zuruf (SCHIRM=1). Eine Pruefung, die bei jedem
|
||||
Lauf Dateien ablegt, muellt das Verzeichnis zu -- und ein Bild
|
||||
beweist ohnehin nichts, das misst der Code darueber. Es ist zum
|
||||
HINSEHEN da, wenn Filipe fragt, wie es fuer eine Rolle aussieht. */
|
||||
if (process.env.SCHIRM) {
|
||||
await p.screenshot({ path: join(HIER, `pruef-zahlen-${rolle}.png`), fullPage: false });
|
||||
}
|
||||
await c.close();
|
||||
return bild;
|
||||
};
|
||||
|
||||
const scoutBild = await rollenBild("scout", "CODE-SAM-00001");
|
||||
ok(scoutBild.kachel === true && /leistung\.html$/.test(scoutBild.weg),
|
||||
`der Scout findet die Kachel und kommt auf die Seite (${scoutBild.weg})`);
|
||||
ok(scoutBild.fehler === "", `kein Skriptfehler beim Scout (${scoutBild.fehler || "keiner"})`);
|
||||
ok(scoutBild.tt === false && scoutBild.import === false && scoutBild.ziele === false,
|
||||
"der Scout darf eintragen: Datei, TikTok-Datei und Ziele sind da");
|
||||
ok(scoutBild.netz === true,
|
||||
"die Backstage-Tabelle bleibt ihm zu -- sie gilt für ALLE Creator");
|
||||
ok(scoutBild.sTt === false && scoutBild.sNetz === true,
|
||||
"und er liest nur die Erklärung zu dem Weg, den er auch hat");
|
||||
ok(scoutBild.aendern > 0,
|
||||
`er kann einen Tag eintragen (${scoutBild.aendern} Knöpfe in der Liste)`);
|
||||
|
||||
const creatorBild = await rollenBild("creator", "CODE-NOVA-0001");
|
||||
ok(creatorBild.kachel === true && /leistung\.html$/.test(creatorBild.weg),
|
||||
`der Creator findet die Kachel und kommt auf die Seite (${creatorBild.weg})`);
|
||||
ok(creatorBild.fehler === "", `kein Skriptfehler beim Creator (${creatorBild.fehler || "keiner"})`);
|
||||
ok(creatorBild.import === true && creatorBild.netz === true
|
||||
&& creatorBild.tt === true && creatorBild.ziele === true,
|
||||
"der Creator sieht KEINEN einzigen Eintrag-Knopf");
|
||||
ok(creatorBild.aendern === 0,
|
||||
`auch nicht an den einzelnen Tagen (${creatorBild.aendern} Knöpfe)`);
|
||||
ok(creatorBild.block === true,
|
||||
"und keinen Quellen-Hinweis -- eine Erklärung ohne Knopf ist Rauschen");
|
||||
ok(creatorBild.wahl === 0,
|
||||
`und kein Auswahlfeld für fremde Creator (${creatorBild.wahl} Einträge)`);
|
||||
|
||||
/* GEGENPROBE ZUR GEGENPROBE: Dass der Creator nichts sieht, darf
|
||||
nicht daran liegen, dass die Seite bei ihm leer bleibt. Seine
|
||||
eigenen Zahlen muessen da sein -- sonst waere alles oben gruen,
|
||||
weil nichts geladen hat. */
|
||||
const creatorZahlen = await (async () => {
|
||||
const c = await browser.newContext({ viewport: { width: 1400, height: 1000 } });
|
||||
const p = await c.newPage();
|
||||
await p.goto(BASIS + "/workspace/", { waitUntil: "networkidle" });
|
||||
await p.click('.rolle[data-rolle="creator"]');
|
||||
await p.fill("#code", "CODE-NOVA-0001");
|
||||
await p.click("button[type=submit]");
|
||||
await p.waitForURL("**/start.html", { timeout: 25000 });
|
||||
await p.goto(BASIS + "/workspace/leistung.html", { waitUntil: "networkidle" });
|
||||
await p.waitForTimeout(1800);
|
||||
const t = await p.evaluate(() => document.getElementById("tagetabelle")?.textContent || "");
|
||||
await c.close();
|
||||
return t;
|
||||
})();
|
||||
ok(/\d/.test(creatorZahlen) && creatorZahlen.length > 20,
|
||||
`seine eigenen Zahlen stehen trotzdem da (${creatorZahlen.length} Zeichen)`);
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user