Anleitung, Etappen 3 bis 7: alle vier Fassungen, Pflege, Suche, Rundgang, Abnahme
Der Bauplan ist damit vollstaendig umgesetzt.
ETAPPE 3 -- SCOUT, MANAGER UND SPICY MEDIA.
Woertlich aus Kapitel 07 bis 09, zusammen 84 Karten. Die Zahlen des
Bauplans stimmen auf die Karte genau: 18/21/22/23, verteilt 5/6/7,
5/7/9, 6/9/7, 5/5/13.
EINE ZWEIDEUTIGKEIT IM PDF, GEMESSEN STATT GERATEN. Beim Manager
nennt die Merke-Spalte "61, 58, 51 feste Punkte", und Layout- und
Raw-Auszug ordnen sie verschiedenen Kacheln zu. Nachgezaehlt im Code:
LIVE 69, Content-Ideen 61, Community 58, Technik 51. Damit ist die
zeilenweise Lesart bewiesen richtig -- die Layout-Lesart haette "61"
der LIVE-Analyse gegeben, die 69 hat.
Die Zuordnungspruefung laeuft jetzt fuer alle vier Rollen, und die
erwartete Kartenzahl wird AUS DER KACHELLISTE abgeleitet, nicht aus
der Abnahmeliste abgeschrieben. Dazu eine Gegenprobe, dass sich die
vier Fassungen wirklich unterscheiden -- sonst waeren alle Zeilen
gruen, solange die Kachellisten zufaellig passen.
ETAPPE 4 -- DIE PFLEGE, fuer DogFather UND Spicy.
Bearbeitet wird an Ort und Stelle: Stufe und die drei Zeilen je Karte,
Titel und Text je Listenzeile, Leitgedanke je Rolle. Fehlende Karten
werden benannt und lassen sich mit einem Griff anlegen -- das ist der
Fall "Fuer diese Kachel fehlt ein Eintrag" aus Kapitel 11. Dazu "Wer
ist wie weit": eine Arbeitslage, keine Ueberwachung.
KEINE ZWEITE ROLLENAUSWAHL. Die Vorschau gibt es schon -- sie heisst
"Meine Sicht" und steht in der Kopfleiste. Geprueft wird fuers Pflegen
`req.person` und nicht `req.sicht`: Wer durch fremde Augen sieht, soll
nicht aus Versehen in fremdem Namen aendern.
DIE MARKE "NEU" HAT EIN ENDE: 14 Tage ODER bis die Person die Seite
nach der Aenderung geoeffnet hat. Der Bauplan sagt dazu nichts, und
ohne Ende waere nach einem halben Jahr alles neu.
ETAPPE 5 -- DIE SUCHE.
Die Karten stehen in der Kopfleisten-Suche, aber nur die der EIGENEN
Rolle: Faende ein Creator die Manager-Karte, stuende dort "Zuteilen,
freigeben" neben einer Kachel, die er nicht hat. Der Treffer traegt
den Zusatz hinter dem Fragezeichen, sonst landen fuenf Karten auf
derselben Seite.
ETAPPE 6 -- BEGRUESSUNG UND RUNDGANG.
Fuenf Schritte ueber die Zentrale, im letzten leuchten nur die
Muss-Kacheln. EIGENE DATEI (`rundgang.js`) und nicht ein Stueck
start.js: Er laeuft auf der meistbenutzten Seite des Hauses, und wenn
hier etwas schiefgeht, darf davon nichts anderes betroffen sein.
Keine gerechnete Koordinate, kein Loch in einer Abdeckung -- die Seite
wird leiser, das Ziel bleibt hell. Faellt das Skript aus, ist beim
naechsten Laden alles normal.
DER ROLLENWECHSEL IST KEINE SONDERREGEL, sondern der Schluessel:
`(Person, Rolle)`. Die neue Rolle hat schlicht noch keine Zeile, also
startet die Einweisung von selbst noch einmal. Eine Spalte
"zuruecksetzen", an die jemand denken muesste, waere die Stelle, an
der es vergessen wird.
EIN FUND AUS DER MESSUNG: Gemerkt wurde zuerst erst am ENDE des
Rundgangs. Wer "Los geht's" drueckte und dann wegging, bekam die
Begruessung bei jedem Aufruf wieder -- fuer immer. Jetzt wird beim
ZEIGEN gemerkt; das ist die Tatsache, um die es geht.
ETAPPE 7 -- DIE ABNAHME.
Dabei fiel auf, dass der Rollen-Rundgang SPICY MEDIA gar nicht kannte:
fuenf Durchgaenge, aber zweimal Manager, zweimal Scout und Spicy nie.
Ihr gehoert die Gruppe "Rund um das Team" samt Team-Lage -- diese
Kachel ist in keinem Durchgang je geoeffnet worden. Jetzt laeuft sie
mit: 452 statt 406 Pruefungen.
MITGENOMMEN, WEIL ES ROT WAR: `pruef-eventkarte` und
`pruef-haus-luecke` bildeten ihr Tagesdatum aus UTC. Zwischen 00:00
und 02:00 deutscher Zeit liegt UTC im Vortag -- ein naechtlicher Lauf
haette an einem Datum gesucht, das er selbst nicht geschrieben hat.
Beide benutzen jetzt `helfer-zeit`. `pruef-struktur` ist damit gruen.
Gemessen (alle gruen, kein einziger Befund)
pruef-anleitung 125 Pruefungen (vorher 70)
pruef-rollen 452 Pruefungen (vorher 406) -- mit Spicy Media
pruef-struktur gruen (vorher rot)
pruef-rechtetafel, pruef-css-klassen, pruef-kachel-universum,
pruef-suchfeld, pruef-kachelraster, pruef-start-ansicht,
pruef-sicht, pruef-eventkarte alle gruen
mess-anleitung Rundgang fuenf Schritte, im letzten genau 5
Muss-Kacheln hervorgehoben; beim zweiten
Aufruf keine Begruessung mehr; kein
Querschieben bei 412 und 1440 px
Sicherung: ~/sicherungen/workspace-vor-anleitung-e37-20261006-1536.db
OFFEN, NICHT VON MIR UND NICHT AUS DIESEM BAUPLAN: pruef-haus-luecke
endet mit Rueckgabewert 3 ("konnte nicht nachsehen") -- eine der
beiden Adressen liefert das Anschlagbrett nicht. Nachgemessen: Das war
vor dieser Arbeit genauso.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -235,6 +235,9 @@ melde("\n=== Die Stufen ===");
|
||||
const jeStufe = {};
|
||||
for (const k of creator.j.karten) jeStufe[k.stufe] = (jeStufe[k.stufe] || 0) + 1;
|
||||
const bekannt = new Set((creator.j.stufen || []).map((s) => s.schluessel));
|
||||
/* Dieselbe Menge weiter unten fuer alle vier Rollen -- der Server
|
||||
nennt die Stufen, diese Datei kennt keine eigene Liste. */
|
||||
const STUFEN_DA = bekannt;
|
||||
ok([...Object.keys(jeStufe)].every((s) => bekannt.has(s)),
|
||||
`jede Karte traegt eine bekannte Stufe (${Object.keys(jeStufe).join(", ")})`);
|
||||
ok(Object.values(jeStufe).reduce((a, b) => a + b, 0) === creator.j.karten.length,
|
||||
@@ -388,6 +391,94 @@ ok(nachher?.merke === "VON HAND GEAENDERT",
|
||||
`der geaenderte Text steht noch da ("${(nachher?.merke || "").slice(0, 24)}")`);
|
||||
ok(anzahlNachher === 18, `und es sind keine Karten dazugekommen (${anzahlNachher})`);
|
||||
|
||||
/* =====================================================================
|
||||
ALLE VIER FASSUNGEN — JEDE GEGEN IHRE EIGENEN KACHELN
|
||||
=====================================================================
|
||||
|
||||
Oben ist der Creator Zeile fuer Zeile geprueft. Hier laufen alle vier
|
||||
durch dieselbe Zuordnung, und die ZAHLEN WERDEN ABGELEITET, nicht
|
||||
abgeschrieben: Wie viele Karten eine Rolle haben muss, sagt ihre
|
||||
Kachelliste -- nicht die Abnahmeliste im Bauplan.
|
||||
|
||||
Der Bauplan nennt 18/21/22/23. Die stimmen heute. Am Tag, an dem
|
||||
eine Kachel dazukommt, waere eine feste Zahl hier eine Luege, die
|
||||
erst auffaellt, wenn jemand sie nachzaehlt. Also zaehlt die
|
||||
Pruefung selbst -- und meldet die Zahl, damit man sie lesen kann.
|
||||
===================================================================== */
|
||||
melde("\n=== Jede Rolle erklaert genau ihre eigenen Kacheln ===");
|
||||
const FASSUNGEN_HIER = ["creator", "scout", "manager", "spicy"];
|
||||
for (const rolle of FASSUNGEN_HIER) {
|
||||
const a = await holen(rolle);
|
||||
if (a.code !== 200 || !a.j?.hat_fassung) {
|
||||
ok(false, `${rolle.padEnd(8)} hat keine Fassung (HTTP ${a.code})`);
|
||||
continue;
|
||||
}
|
||||
const soll = kachelnFuer(rolle);
|
||||
soll.delete("anleitung"); // die Seite erklaert sich nicht selbst
|
||||
const ist = new Set(a.j.karten.map((k) => k.kachel));
|
||||
const fehlt = [...soll.keys()].filter((x) => !ist.has(x));
|
||||
const zuviel = [...ist].filter((x) => !soll.has(x));
|
||||
|
||||
ok(soll.size > 0 && fehlt.length === 0 && zuviel.length === 0,
|
||||
fehlt.length || zuviel.length
|
||||
? `${rolle.padEnd(8)} stimmt nicht -- ohne Karte: ${fehlt.join(", ") || "nichts"}; `
|
||||
+ `ohne Kachel: ${zuviel.join(", ") || "nichts"}`
|
||||
: `${rolle.padEnd(8)} ${soll.size} Kacheln, ${ist.size} Karten, eins zu eins`);
|
||||
|
||||
/* Jede Karte vollstaendig. Eine halbe Karte sieht aus wie ein
|
||||
Ladefehler, und zwar auf jeder der vier Seiten gleich. */
|
||||
const halb = a.j.karten.filter((k) => !k.wozu || !k.tust || !k.merke);
|
||||
ok(halb.length === 0,
|
||||
halb.length ? `${rolle.padEnd(8)} ${halb.length} unvollstaendige Karten: `
|
||||
+ halb.map((k) => k.kachel).join(", ")
|
||||
: `${rolle.padEnd(8)} jede Karte hat alle drei Zeilen`);
|
||||
|
||||
/* Die Stufen -- gezaehlt, nicht vorgegeben. */
|
||||
const je = {};
|
||||
for (const k of a.j.karten) je[k.stufe] = (je[k.stufe] || 0) + 1;
|
||||
const summe = Object.values(je).reduce((x, y) => x + y, 0);
|
||||
ok(summe === a.j.karten.length
|
||||
&& Object.keys(je).every((x) => STUFEN_DA.has(x)),
|
||||
`${rolle.padEnd(8)} Stufen ${je.muss || 0}/${je.regelmaessig || 0}/${je.bedarf || 0} `
|
||||
+ `(zusammen ${summe} von ${a.j.karten.length})`);
|
||||
|
||||
/* Die Ersten Schritte duerfen nur auf Kacheln dieser Rolle zeigen --
|
||||
oder auf gar nichts ("Installieren", "Kopfleiste" sind Knoepfe in
|
||||
der Kopfleiste, keine Seiten). */
|
||||
const alleKacheln = kachelnFuer(rolle);
|
||||
const ins_leere = (a.j.schritte || []).filter((x) => x.ziel)
|
||||
.filter((x) => !alleKacheln.has(B.schluesselVonZiel(x.ziel)));
|
||||
ok((a.j.schritte || []).length === 5 && ins_leere.length === 0,
|
||||
ins_leere.length
|
||||
? `${rolle.padEnd(8)} Schritte ins Leere: ${ins_leere.map((x) => x.ziel).join(", ")}`
|
||||
: `${rolle.padEnd(8)} fuenf Erste Schritte, alle mit gueltigem Ziel`);
|
||||
|
||||
/* Und der Rest der Fassung ist da. Eine Rolle ohne Rhythmus oder
|
||||
ohne "Nicht deins" waere eine halbe Einweisung. */
|
||||
ok(!!a.j.leitgedanke && (a.j.saetze || []).length === 3
|
||||
&& (a.j.nicht || []).length >= 3 && (a.j.takt || []).length >= 3
|
||||
&& (a.j.fragen || []).length >= 3,
|
||||
`${rolle.padEnd(8)} Leitgedanke, 3 Saetze, ${(a.j.nicht || []).length} x Nicht deins, `
|
||||
+ `${(a.j.takt || []).length} Takt-Zeilen, ${(a.j.fragen || []).length} Fragen`);
|
||||
}
|
||||
|
||||
/* GEGENPROBE ZUR SCHLEIFE: Sie darf nicht leer durchgelaufen sein.
|
||||
Vier Rollen, und jede musste wirklich etwas liefern. */
|
||||
ok(FASSUNGEN_HIER.length === 4, `vier Fassungen durchgegangen`);
|
||||
|
||||
/* Und: Die Fassungen muessen sich UNTERSCHEIDEN. Lieferte der Server
|
||||
allen dieselbe Liste, waeren alle Zeilen oben trotzdem gruen --
|
||||
solange die Kachellisten zufaellig passten. */
|
||||
{
|
||||
const koepfe = [];
|
||||
for (const rolle of FASSUNGEN_HIER) {
|
||||
const a = await holen(rolle);
|
||||
koepfe.push(a.j?.leitgedanke || "");
|
||||
}
|
||||
ok(new Set(koepfe).size === 4,
|
||||
`Gegenprobe: vier verschiedene Leitgedanken (${new Set(koepfe).size} verschiedene)`);
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
ETAPPE 2 — DIE ERSTEN SCHRITTE ZUM ABHAKEN
|
||||
===================================================================== */
|
||||
@@ -522,6 +613,199 @@ ok(hWieder.liste.some((h) => h.art === "anl_schritte" && h.anzahl === 1),
|
||||
sehen -- der Haken auf Schritt 2 und die vier von eben. */
|
||||
for (const s of schritte0) await haken("creator", s.id, false);
|
||||
|
||||
/* =====================================================================
|
||||
ETAPPE 4 — DIE PFLEGE
|
||||
===================================================================== */
|
||||
melde("\n=== Pflege: wer darf ===");
|
||||
const pput = (rolle, pfad, rumpf, host = null) =>
|
||||
roh(pfad, host, rumpf, kekse[rolle], "PUT");
|
||||
|
||||
const eineKarte = (await holen("creator")).j.karten.find((k) => k.kachel === "chat");
|
||||
braucht(!!eineKarte?.id, "keine Karte zum Bearbeiten gefunden");
|
||||
|
||||
const pCreator = await pput("creator", `/workspace/api/anleitung/karte/${eineKarte.id}`,
|
||||
{ stufe: "bedarf", wozu: "x", tust: "y", merke: "z" });
|
||||
ok(pCreator.code === 403, `ein Creator darf nicht pflegen (HTTP ${pCreator.code}, erwartet 403)`);
|
||||
const pScout = await pput("scout", `/workspace/api/anleitung/karte/${eineKarte.id}`,
|
||||
{ stufe: "bedarf", wozu: "x", tust: "y", merke: "z" });
|
||||
ok(pScout.code === 403, `ein Scout auch nicht (HTTP ${pScout.code}, erwartet 403)`);
|
||||
const pModi = await pput("modi", `/workspace/api/anleitung/karte/${eineKarte.id}`,
|
||||
{ stufe: "bedarf", wozu: "x", tust: "y", merke: "z" }, CREW_HOST);
|
||||
ok(pModi.code === 404, `ein Modi bekommt die Pflege gar nicht (HTTP ${pModi.code}, erwartet 404)`);
|
||||
|
||||
melde("\n=== Pflege: Spicy aendert eine Stufe, und sie gilt sofort ===");
|
||||
const vorher = eineKarte.stufe;
|
||||
const pSpicy = await pput("spicy", `/workspace/api/anleitung/karte/${eineKarte.id}`,
|
||||
{ stufe: "bedarf", wozu: "Nachrichten mit deinem Team.",
|
||||
tust: "Mit „Neu“ ein Gespräch beginnen.", merke: "GEAENDERT VON SPICY" });
|
||||
ok(pSpicy.code === 200, `Spicy Media darf (HTTP ${pSpicy.code})`);
|
||||
const nachSpicy = await holen("creator");
|
||||
const chatNeu = nachSpicy.j.karten.find((k) => k.kachel === "chat");
|
||||
ok(chatNeu?.stufe === "bedarf",
|
||||
`die Stufe steht sofort in der Creator-Fassung (${vorher} -> ${chatNeu?.stufe})`);
|
||||
ok(chatNeu?.merke === "GEAENDERT VON SPICY", "…und der Text auch");
|
||||
|
||||
/* DIE MARKE "NEU". Der Creator hat die Seite gerade geladen -- damit
|
||||
ist sein Besuch juenger als die Aenderung davor, aber AELTER als die
|
||||
von eben. Die Reihenfolge ist der ganze Beweis. */
|
||||
ok(chatNeu?.neu === true, "die geaenderte Karte traegt die Marke „Neu“");
|
||||
const nochmal = await holen("creator");
|
||||
ok(nochmal.j.karten.find((k) => k.kachel === "chat")?.neu === false,
|
||||
"…und beim zweiten Hinsehen nicht mehr");
|
||||
|
||||
/* Zurueck auf Anfang, damit die Zuordnungspruefung oben weiter stimmt. */
|
||||
await pput("spicy", `/workspace/api/anleitung/karte/${eineKarte.id}`,
|
||||
{ stufe: vorher, wozu: "Nachrichten mit deinem Team.",
|
||||
tust: "Mit „Neu“ ein Gespräch beginnen.",
|
||||
merke: "Fehler an der Seite gehören in Support, nicht in den Chat." });
|
||||
|
||||
melde("\n=== Pflege: was nicht durchgehen darf ===");
|
||||
const pUnsinn = await pput("admin", `/workspace/api/anleitung/karte/${eineKarte.id}`,
|
||||
{ stufe: "gibtesnicht", wozu: "", tust: "", merke: "" });
|
||||
ok(pUnsinn.code === 400, `eine erfundene Stufe wird abgelehnt (HTTP ${pUnsinn.code})`);
|
||||
const pWeg = await pput("admin", "/workspace/api/anleitung/karte/999999",
|
||||
{ stufe: "muss", wozu: "", tust: "", merke: "" });
|
||||
ok(pWeg.code === 404, `eine Karte, die es nicht gibt (HTTP ${pWeg.code})`);
|
||||
|
||||
melde("\n=== Pflege: fehlenden Eintrag anlegen und wieder entfernen ===");
|
||||
/* Erst loeschen, dann ist er "fehlend" -- genau der Fall, den der
|
||||
Bauplan "Fuer diese Kachel fehlt ein Eintrag" nennt. */
|
||||
const weg = await roh(`/workspace/api/anleitung/karte/${eineKarte.id}`, null, null,
|
||||
kekse.admin, "DELETE");
|
||||
ok(weg.code === 200, `DogFather kann eine Karte entfernen (HTTP ${weg.code})`);
|
||||
const ohne = await holen("creator");
|
||||
ok(ohne.j.karten.length === 17 && !ohne.j.karten.some((k) => k.kachel === "chat"),
|
||||
`danach 17 Karten, die Chat-Karte fehlt (${ohne.j.karten.length})`);
|
||||
|
||||
const neu1 = await roh("/workspace/api/anleitung/karte", null,
|
||||
{ rolle: "creator", kachel: "chat", stufe: "muss",
|
||||
wozu: "Nachrichten mit deinem Team.", tust: "Mit „Neu“ ein Gespräch beginnen.",
|
||||
merke: "Fehler an der Seite gehören in Support, nicht in den Chat." },
|
||||
kekse.admin, "POST");
|
||||
ok(neu1.code === 200, `…und wieder anlegen (HTTP ${neu1.code})`);
|
||||
const neu2 = await roh("/workspace/api/anleitung/karte", null,
|
||||
{ rolle: "creator", kachel: "chat", stufe: "muss", wozu: "", tust: "", merke: "" },
|
||||
kekse.admin, "POST");
|
||||
ok(neu2.code === 409,
|
||||
`ein zweites Mal nicht -- eine Kachel hat genau eine Karte (HTTP ${neu2.code})`);
|
||||
const zurueck = await holen("creator");
|
||||
ok(zurueck.j.karten.length === 18,
|
||||
`wieder 18 Karten (${zurueck.j.karten.length})`);
|
||||
|
||||
melde("\n=== Pflege: eine Zeile aendern ===");
|
||||
const einSchritt = zurueck.j.schritte[0];
|
||||
const zAend = await pput("admin", `/workspace/api/anleitung/zeile/${einSchritt.id}`,
|
||||
{ titel: einSchritt.titel, text: "GEAENDERTER TEXT", ziel: einSchritt.ziel });
|
||||
ok(zAend.code === 200, `eine Listenzeile laesst sich aendern (HTTP ${zAend.code})`);
|
||||
const nachZeile = await holen("creator");
|
||||
ok(nachZeile.j.schritte[0]?.text === "GEAENDERTER TEXT", "…und der Text steht da");
|
||||
await pput("admin", `/workspace/api/anleitung/zeile/${einSchritt.id}`,
|
||||
{ titel: einSchritt.titel, text: einSchritt.text, ziel: einSchritt.ziel });
|
||||
|
||||
melde("\n=== Pflege: wer ist wie weit ===");
|
||||
const standR = await roh("/workspace/api/anleitung/stand", null, null, kekse.admin);
|
||||
let standJ = null; try { standJ = JSON.parse(standR.text); } catch { /* bleibt null */ }
|
||||
ok(standR.code === 200 && Array.isArray(standJ?.leute),
|
||||
`DogFather sieht den Stand (HTTP ${standR.code}, ${standJ?.leute?.length ?? 0} Leute)`);
|
||||
ok((standJ?.leute || []).some((p) => p.rolle === "creator" && p.gesamt === 5),
|
||||
"…und der Creator steht mit fuenf Schritten drin");
|
||||
const standC = await roh("/workspace/api/anleitung/stand", null, null, kekse.creator);
|
||||
ok(standC.code === 403, `ein Creator sieht ihn nicht (HTTP ${standC.code}, erwartet 403)`);
|
||||
|
||||
/* =====================================================================
|
||||
ETAPPE 5 — DIE SUCHE
|
||||
===================================================================== */
|
||||
melde("\n=== Suche ===");
|
||||
async function suchen(rolle, wort, host = null) {
|
||||
const r = await roh(`/workspace/api/suche?q=${encodeURIComponent(wort)}`, host, null, kekse[rolle]);
|
||||
let j = null; try { j = JSON.parse(r.text); } catch { /* bleibt null */ }
|
||||
const g = (j?.gruppen || []).find((x) => x.titel === "Anleitung");
|
||||
return { code: r.code, treffer: g?.treffer || [], gruppen: (j?.gruppen || []).length };
|
||||
}
|
||||
|
||||
/* Ein Wort, das NUR in der Creator-Fassung steht. */
|
||||
const sCreator = await suchen("creator", "Jemand schaut noch drauf");
|
||||
ok(sCreator.code === 200 && sCreator.treffer.length > 0,
|
||||
`der Creator findet seine eigene Karte (${sCreator.treffer.length} Treffer)`);
|
||||
/* DIE ZAHL GEHOERT IN DIE BEDINGUNG. `every()` liefert auf einer LEEREN
|
||||
Liste `true` -- diese Zeile war beim ersten Lauf gruen, ohne einen
|
||||
einzigen Treffer angesehen zu haben. Genau der Fehler vom 01.09.2026
|
||||
im Shop, nur mit anderen Namen. */
|
||||
ok(sCreator.treffer.length > 0
|
||||
&& sCreator.treffer.every((t) => t.ziel && !t.ziel.includes("undefined")),
|
||||
`…und jeder der ${sCreator.treffer.length} Treffer hat ein Ziel `
|
||||
+ `(${sCreator.treffer.map((t) => t.ziel).join(", ") || "keine"})`);
|
||||
|
||||
/* Ein Wort, das NUR in der Manager-Fassung steht. */
|
||||
const sFremd = await suchen("creator", "Zuteilen, freigeben");
|
||||
ok(sFremd.treffer.length === 0,
|
||||
`der Creator findet die Manager-Karte NICHT (${sFremd.treffer.length} Treffer)`);
|
||||
const sManager = await suchen("manager", "Zuteilen, freigeben");
|
||||
ok(sManager.treffer.length > 0,
|
||||
`Gegenprobe: der Manager findet sie sehr wohl (${sManager.treffer.length} Treffer)`);
|
||||
|
||||
const sModi = await suchen("modi", "Freigabe heißt", CREW_HOST);
|
||||
ok(sModi.code === 200 && sModi.treffer.length === 0,
|
||||
`ein Modi findet nichts davon (HTTP ${sModi.code}, ${sModi.treffer.length} Treffer)`);
|
||||
|
||||
/* Die Adresse im Treffer muss den Zusatz hinter dem Fragezeichen
|
||||
tragen -- sonst landen fuenf Karten auf derselben Seite. */
|
||||
const sBereich = await suchen("creator", "Ruhig statt Drama");
|
||||
ok(sBereich.treffer.some((t) => t.ziel === "bereich.html?b=community"),
|
||||
`ein Bereichs-Treffer traegt seinen Zusatz (${sBereich.treffer.map((t) => t.ziel).join(", ")})`);
|
||||
|
||||
/* =====================================================================
|
||||
ETAPPE 6 — BEGRUESSUNG UND RUNDGANG
|
||||
===================================================================== */
|
||||
melde("\n=== Einweisung beim ersten Anmelden ===");
|
||||
async function einweisung(rolle, host = null) {
|
||||
const r = await roh("/workspace/api/anleitung/einweisung", host, null, kekse[rolle]);
|
||||
let j = null; try { j = JSON.parse(r.text); } catch { /* bleibt null */ }
|
||||
return { code: r.code, j };
|
||||
}
|
||||
|
||||
const e1 = await einweisung("creator");
|
||||
ok(e1.code === 200 && e1.j?.zeigen === true,
|
||||
`beim ersten Mal wird sie gezeigt (HTTP ${e1.code}, zeigen ${e1.j?.zeigen})`);
|
||||
ok(Array.isArray(e1.j?.muss) && e1.j.muss.length === 5,
|
||||
`…mit den fuenf Muss-Kacheln (${e1.j?.muss?.length})`);
|
||||
|
||||
const gesehen = await roh("/workspace/api/anleitung/einweisung/gesehen", null, {}, kekse.creator,
|
||||
"POST");
|
||||
ok(gesehen.code === 200, `„gesehen“ laesst sich merken (HTTP ${gesehen.code})`);
|
||||
const e2 = await einweisung("creator");
|
||||
ok(e2.j?.zeigen === false, "beim zweiten Mal nicht mehr");
|
||||
|
||||
/* DIE CREW BEKOMMT 200 UND NICHT 404. Das Skript laeuft auf JEDER
|
||||
Startseite; ein Fehlschlag waere eine rote Zeile in der Konsole bei
|
||||
jedem Aufruf -- und die verdeckt die naechste, die echt ist. */
|
||||
const eModi = await einweisung("modi", CREW_HOST);
|
||||
ok(eModi.code === 200 && eModi.j?.zeigen === false,
|
||||
`ein Modi bekommt eine ruhige Absage (HTTP ${eModi.code}, zeigen ${eModi.j?.zeigen})`);
|
||||
const eDogi = await einweisung("admin");
|
||||
ok(eDogi.code === 200 && eDogi.j?.zeigen === false,
|
||||
`DogFather auch -- er braucht keine Einweisung (zeigen ${eDogi.j?.zeigen})`);
|
||||
|
||||
/* DER ROLLENWECHSEL. Der Bauplan verlangt, dass die Einweisung dann
|
||||
einmal neu startet. Gebaut ist das NICHT als Sonderregel, sondern
|
||||
ueber den Schluessel (Person, Rolle) -- die neue Rolle hat schlicht
|
||||
noch keine Zeile. Genau das wird hier nachgemessen. */
|
||||
{
|
||||
const d4 = new DatabaseSync(process.env.WORKSPACE_DB);
|
||||
d4.prepare("UPDATE personen SET rolle = 'scout' WHERE rolle = 'creator'").run();
|
||||
d4.close();
|
||||
const neuAn = await anmelden("scout");
|
||||
const alt = kekse.scout;
|
||||
kekse.scout = neuAn || alt;
|
||||
const eNach = await einweisung("scout");
|
||||
kekse.scout = alt;
|
||||
ok(eNach.j?.zeigen === true,
|
||||
`nach einem Rollenwechsel startet sie einmal neu (zeigen ${eNach.j?.zeigen})`);
|
||||
const d5 = new DatabaseSync(process.env.WORKSPACE_DB);
|
||||
d5.prepare("UPDATE personen SET rolle = 'creator' WHERE name = 'Luna'").run();
|
||||
d5.close();
|
||||
}
|
||||
|
||||
/* ---------- Abschluss ------------------------------------------------ */
|
||||
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }
|
||||
console.log(`\n${fehler ? "FEHLER: " + fehler : "Alles in Ordnung"} — ${geprueft} Prüfungen`);
|
||||
|
||||
Reference in New Issue
Block a user