Auf dem Brett steht jetzt Deutsch, nicht ASCII

Unter jeder Kategorie stand eine Erklaerung ohne Umlaute:
"Was im Livechat passiert, waehrend gesendet wird. Loeschen,
stummschalten, begruessen, deeskalieren." Elf der vierzehn Kategorien
und alle drei Stufen waren betroffen, dazu vier Stellen mit zwei
Bindestrichen statt eines Gedankenstrichs.

Entstanden ist es beim Schreiben ueber Hilfsskripte, die an Umlauten
scheitern -- fuer einen Kommentar gleichgueltig, fuer einen Satz, den
ein Mensch liest, ein Fehler. Gesehen hat es keine Pruefung: Der Text
war inhaltlich richtig, der Katalog vollstaendig, alles gruen.
Aufgefallen ist es auf einem Bildschirmfoto.

NEU: pruef-deutsche-texte (9 Pruefungen)
Sieht 174 Katalogtexte und 28 ausgelieferte Seiten durch. Bewusst eine
Liste von Wortstuecken statt eines Musters aus Buchstabenfolgen: "ue"
ist in "Feuer" und "neue" richtig, "ss" in jedem zweiten Wort. Die
Liste ist ein Netz, kein Beweis, und der Kopf der Datei sagt das.

Die Skripte bleiben absichtlich aussen vor. Ausprobiert: Dieselbe
Liste schlaegt dort 71 Mal an und kein einziges Mal zu Recht -- es
sind Feldnamen, Stilklassen und Adressen, die ASCII sein MUESSEN.
Eine Warnung, die immer kommt, ist keine Warnung mehr. Ihr sichtbarer
Text wird deshalb am fertigen Bildschirm geprueft, ueber innerText.

AUSSERDEM, auf demselben Bildschirmfoto gefunden:
Die Fusszeile der Vorlagenkarten war eine starre Flex-Zeile. Bei einer
schon uebernommenen Aufgabe stehen dort drei Dinge statt zwei, und
"Frist: in 2 Tagen" brach mitten im Wort auf drei Zeilen um. Keine
neue feste Breite dagegen, sondern flex-wrap plus nowrap -- eine
Regel, die misst, statt einer Zahl, die beim naechsten Element wieder
faellig waere.

UND EINE LEHRE ZUM MESSEN: Die erste Fassung dieser Pruefung zaehlte
element.getClientRects(). Sie blieb gruen, auch mit dem Fehler wieder
eingebaut -- ein Flex-Kind wird zum Block und liefert immer genau ein
Rechteck. Gefunden hat das nur die Gegenprobe. Gemessen wird jetzt
ueber einen Bereich um den Textknoten.

Das Bildschirmfoto landet ausserdem dort, wo die Zeile darunter es
ansagt (server/), nicht im Arbeitsverzeichnis.

pruef-modi-katalog 49 (vorher 45), pruef-deutsche-texte 9,
pruef-css-klassen, pruef-struktur, pruef-vorlagen,
pruef-aufgaben-vorlagen: alle ohne Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-16 23:22:05 +02:00
co-authored by Claude Opus 5
parent 76fa8b95fc
commit 78b64f6eca
37 changed files with 733 additions and 399 deletions
+41
View File
@@ -0,0 +1,41 @@
/* =====================================================================
ERSATZSCHREIBUNGEN ERKENNEN (16.09.2026)
"waehrend", "Loeschen", "begruessen" -- Umlaute, die als ae/oe/ue/ss
geschrieben sind. In einem Kommentar ist das die Hausschreibweise, in
einem Satz fuer Menschen ein Fehler. Warum er entsteht und was sich
dagegen pruefen laesst, steht ausfuehrlich in pruef-deutsche-texte.
Diese Datei importiert NICHTS. Sie ist ein Blatt, wie helfer-tag: Wer
nur wissen will, ob ein Satz sauber ist, soll dafuer keinen Server
hochfahren und keine Pruefung ausloesen -- pruef-deutsche-texte ruft
beim Laden `process.exit` auf, ein Import von dort waere toedlich.
Und es ist der Grund, warum die Liste hier steht und nicht zweimal
irgendwo: Zwei Listen, die dasselbe entscheiden, laufen auseinander.
===================================================================== */
/** Wortstuecke, die als Ersatzschreibung praktisch eindeutig sind.
*
* Klein geschrieben; verglichen wird klein gegen klein. Bewusst KEIN
* blosses "ae|oe|ue|ss": Das steht in "Feuer", "Michael", "Poesie" und
* "Wasser" voellig zu Recht. Die Liste ist ein Netz, kein Beweis --
* sie findet das Haeufige und kann Seltenes durchlassen. */
export const ERSATZSCHREIBUNGEN = [
"aehnlich", "aender", "aerger", "anfaeng", "ausser", "aussen",
"begruess", "beitraeg", "bloed", "draussen", "empfaeng", "faell",
"froehl", "fuer", "gaest", "gemaess", "geraet", "groess", "gross",
"gruess", "haett", "haeng", "heiss", "hoech", "hoeh", "hoer",
"kaempf", "koenn", "koerper", "laeng", "laesst", "laeuf", "loesch",
"maessig", "massnahme", "moech", "moegl", "muess", "naechst",
"oeffn", "oefter", "plaen", "schaetz", "schliess", "schoen", "spaet",
"staerk", "stoer", "taegl", "taet", "traeg", "ueber", "uebung",
"ungefaehr", "veraend", "verlaeuf", "vorschlaeg", "waehl", "waehr",
"waere", "weiss", "woert", "zaehl", "zugaeng", "zurueck",
];
/** Welche Ersatzschreibungen stecken in diesem Text? Leer heisst sauber. */
export function ersatzschreibungen(text) {
const klein = String(text || "").toLowerCase();
return ERSATZSCHREIBUNGEN.filter((m) => klein.includes(m));
}
+184
View File
@@ -0,0 +1,184 @@
/* =====================================================================
TEXT FUER MENSCHEN TRAEGT UMLAUTE (16.09.2026)
Auf dem Aufgabenbrett des Teams stand, gut lesbar, in der Erklaerung
unter der Kategorie Chat-Moderation:
"Was im Livechat passiert, waehrend gesendet wird. Loeschen,
stummschalten, begruessen, deeskalieren."
Vierzehn Kategorien und drei Stufen -- vierundzwanzig solcher
Stellen. Keine Pruefung hat es gesehen: Der Text war inhaltlich
richtig, der Katalog vollstaendig, die Seite gruen. Aufgefallen ist
es erst auf einem Bildschirmfoto.
---------------------------------------------------------------------
WARUM ES PASSIERT IST -- UND WIEDER PASSIEREN WUERDE
Kommentare sind in diesem Haus bewusst ohne Umlaute geschrieben, und
Aenderungen an grossen Dateien laufen ueber Hilfsskripte, die an
Umlauten und Maskierungen gern scheitern. Wer in so einem Skript Text
schreibt, schreibt ihn reflexhaft in ASCII. Fuer einen Kommentar ist
das gleichgueltig. Fuer einen Satz, den ein Mensch liest, ist es ein
Fehler -- und einer, der keine Fehlermeldung erzeugt.
Ein Warnhinweis daneben haette nicht geholfen. Das steht so in den
Hausregeln, aus einem anderen Schaden: Ein Kommentar, der vor einem
Fehler warnt, verhindert ihn nicht. Er wird beim naechsten Mal nicht
gelesen. Deshalb eine Pruefung.
---------------------------------------------------------------------
WAS SIE SEHEN KANN -- UND WAS NICHT
Rechnerisch entscheiden laesst es sich NICHT. "ue" ist in "Feuer",
"Steuer", "neue" und "aktuell" voellig richtig, "ae" in "Michael",
"oe" in "Poesie", und "ss" stimmt in jedem zweiten deutschen Wort.
Ein Muster aus blossen Buchstabenfolgen wuerde entweder alles
durchlassen oder staendig falschen Alarm schlagen.
Deshalb eine Liste von Wortstuecken, die als Ersatzschreibung
praktisch eindeutig sind ("waehr", "loesch", "begruess", "ueber").
Sie ist ein NETZ, kein Beweis: Sie findet das Haeufige und kann
Seltenes durchlassen. Das ist ehrlich so gemeint -- eine Pruefung,
die ihre Grenze nennt, ist mehr wert als eine, die mehr verspricht,
als sie haelt.
Vor dem Bauen gemessen: null Fehlalarme auf 174 Katalogtexten und
28 ausgelieferten Seiten.
---------------------------------------------------------------------
UND WARUM DIE SKRIPTE NICHT MITGEPRUEFT WERDEN
Ausprobiert -- und es war das Aufschlussreichste an der Sache: In den
38 Skripten unter workspace/assets/js schlug dieselbe Liste 71 Mal
an, und KEIN EINZIGER Treffer war ein Fehler. Es waren Feldnamen
("f-geraet"), Stilklassen ("team-karte__ueber"), Adressen
("/workspace/api/uebersicht"), Datenschluessel ("review_faellig").
Die muessen ASCII sein -- ein Umlaut waere dort der Fehler.
Eine Warnung, die immer kommt, ist keine Warnung mehr. Der sichtbare
Text aus den Skripten wird deshalb dort geprueft, wo er Text ist und
kein Bezeichner: am fertig gebauten Bildschirm, in
pruef-modi-katalog.
Aufrufen mit: node server/pruef-deutsche-texte.mjs
===================================================================== */
import { readdirSync, readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { ersatzschreibungen } from "./helfer-deutsch.mjs";
/* Pfade am Ort DIESER Datei festmachen, nicht am Arbeitsverzeichnis.
Sonst misst die Pruefung verschiedene Dinge, je nachdem, aus welchem
Ordner sie gestartet wurde -- und findet im schlimmsten Fall gar
keine Seiten und meldet trotzdem "in Ordnung". */
const SEITEN_ORDNER = fileURLToPath(new URL("../workspace/", import.meta.url));
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++; };
/* =======================================================================
1. DIE KATALOGE
======================================================================= */
melde("");
melde("=== 1. Was in den Katalogen steht ===");
const [w, v] = await Promise.all([
import("./workspace.js"), import("./workspace-vorlagen.js"),
]);
const texte = [];
for (const k of w.MODI_KATEGORIEN) texte.push([`Kategorie ${k.wert}`, `${k.name} ${k.text}`]);
for (const s of w.MODI_STUFEN) texte.push([`Stufe ${s.wert}`, `${s.name} ${s.text}`]);
for (const g of v.MODI_GRUPPEN) texte.push([`Gruppe ${g.schluessel}`, `${g.name} ${g.text}`]);
for (const a of v.MODI_AUFGABEN_FLACH) texte.push([`Modi ${a.schluessel}`, `${a.titel} ${a.text}`]);
for (const a of v.MODI_KATALOG) texte.push([`Agentur ${a.schluessel}`, `${a.titel} ${a.text}`]);
/* DIE ANZAHL GEHOERT IN DIE BEDINGUNG, nicht nur in den Meldetext.
Waere der Katalog leer, haette die Schleife darunter nichts zu tun
und wuerde ein sattes Gruen melden. */
ok(texte.length >= 150, `${texte.length} ausgelieferte Katalogtexte gefunden`);
const schmutzig = texte.filter(([, t]) => ersatzschreibungen(t).length);
for (const [wo, t] of schmutzig) {
melde(` ${wo}: [${ersatzschreibungen(t).join(", ")}] ${t.slice(0, 70)}`);
}
ok(schmutzig.length === 0,
`keiner davon schreibt Umlaute als ae/oe/ue/ss (${schmutzig.length} Funde)`);
/* ZWEI BINDESTRICHE SIND KEIN GEDANKENSTRICH. Derselbe Reflex aus
demselben Grund: Im Kommentar ist "--" die Hausschreibweise, auf dem
Bildschirm sind es zwei Striche, die wie ein Tippfehler aussehen. */
const striche = texte.filter(([, t]) => t.includes("--"));
for (const [wo, t] of striche) melde(` ${wo}: ${t.slice(0, 70)}`);
ok(striche.length === 0,
`und keiner zwei Bindestriche statt eines Gedankenstrichs (${striche.length} Funde)`);
/* =======================================================================
2. DER SICHTBARE TEXT DER SEITEN
======================================================================= */
melde("");
melde("=== 2. Was fest auf den Seiten steht ===");
{
let seiten = 0, stellen = 0;
for (const datei of readdirSync(SEITEN_ORDNER)) {
if (!datei.endsWith(".html")) continue;
seiten++;
/* Kommentare und Skriptbloecke raus -- dort ist ASCII richtig. */
const roh = readFileSync(SEITEN_ORDNER + datei, "utf8")
.replace(/<!--[\s\S]*?-->/g, " ")
.replace(/<(script|style)[\s\S]*?<\/\1>/g, " ");
for (const stueck of roh.split(/<[^>]*>/)) {
const t = stueck.trim();
if (t.length < 4) continue;
const treffer = ersatzschreibungen(t);
if (treffer.length) {
stellen++;
melde(` ${datei}: [${treffer.join(", ")}] ${t.slice(0, 70)}`);
}
}
}
ok(seiten >= 20, `${seiten} ausgelieferte Seiten durchgesehen`);
ok(stellen === 0, `ihr sichtbarer Text ist frei von Ersatzschreibungen (${stellen} Funde)`);
}
/* =======================================================================
3. GEGENPROBE -- KANN DIE PRUEFUNG UEBERHAUPT ROT WERDEN?
======================================================================= */
melde("");
melde("=== 3. Die Gegenprobe ===");
{
/* WORTWOERTLICH DER TEXT, DER AM 16.09. AUF DEM BRETT STAND. Ohne
diese Zeile beweisen die Abschnitte darueber nichts: Eine Liste,
die nie anschlaegt, meldet immer "in Ordnung". */
const alt = "Was im Livechat passiert, waehrend gesendet wird. "
+ "Loeschen, stummschalten, begruessen, deeskalieren.";
const gefunden = ersatzschreibungen(alt);
ok(gefunden.length >= 3, `der alte Kategorietext schlaegt an (${gefunden.join(", ")})`);
/* UND DIE ANDERE RICHTUNG, genauso wichtig: Der reparierte Text darf
NICHT anschlagen. Sonst waere die Liste einfach zu breit. */
const neu = "Was im Livechat passiert, während gesendet wird. "
+ "Löschen, stummschalten, begrüßen, deeskalieren.";
ok(ersatzschreibungen(neu).length === 0, "der reparierte Text nicht");
/* DIE HAEUFIGSTEN ECHTEN WOERTER, in denen ae/oe/ue/ss korrekt sind.
Sie stehen hier, weil genau sie eine zu grobe Liste verraten
wuerden -- und weil "Feuer" und "neue" in echten Texten vorkommen. */
const echt = "Die neue Steuer ist teuer, das Feuer ein Abenteuer. "
+ "Michael liest Poesie, das Wasser ist nass, und dass es aktuell "
+ "regnet, muss uns nicht weiter stören.";
const falschAlarm = ersatzschreibungen(echt);
ok(falschAlarm.length === 0,
`echte ue/ae/oe/ss-Woerter loesen keinen Alarm aus (${falschAlarm.join(", ") || "keiner"})`);
/* UND DIE ZWEITE GEGENPROBE zum Gedankenstrich, aus demselben Grund. */
ok("Klar umrissen -- und erreichbar.".includes("--"),
"zwei Bindestriche werden als solche erkannt");
}
/* ------------------------------------------------------------------- */
melde("");
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
melde(fehler ? "NICHT IN ORDNUNG" : "ALLES IN ORDNUNG");
process.exit(fehler ? 1 : 0);
+86 -10
View File
@@ -31,6 +31,8 @@ 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";
import { ersatzschreibungen } from "./helfer-deutsch.mjs";
import { fileURLToPath } from "node:url";
await import("./index.js");
notbremse(180_000, "pruef-modi-katalog");
await new Promise((r) => setTimeout(r, 700));
@@ -304,12 +306,41 @@ console.log("\n=== 6. Das Brett im echten Browser ===\n");
/* ZWEI REIHEN SEIT DEM 16.09.2026: oben die Kategorien, darunter
die Stufen. Getrennt gezaehlt -- eine gemeinsame Zahl haette
nicht gesagt, WELCHE der beiden fehlt. */
/* UEBER DIE BESCHRIFTUNG UNTERSCHIEDEN, nicht ueber eine
Hilfsklasse (16.09.2026). Seit die Stufenreihe genauso aussieht
wie die Kategorienreihe -- so wollte Filipe es -- gibt es im
Aussehen keinen Unterschied mehr. Den gibt es aber im SINN, und
der steht ohnehin da: in dem Wort, das ein Vorleseprogramm
ansagt. Eine Klasse nur zum Wiederfinden waere eine zweite
Wahrheit ueber dieselbe Sache. */
kategorien: [...document.querySelectorAll(
".stufenleiter:not(.stufenleiter--fein) .stufenleiter__name")]
'[aria-label="Kategorie wählen"] .stufenleiter__name')]
.map((z) => z.textContent.trim()),
stufen: [...document.querySelectorAll(
".stufenleiter--fein .stufenleiter__name")].map((z) => z.textContent.trim()),
'[aria-label="Stufe wählen"] .stufenleiter__name')]
.map((z) => z.textContent.trim()),
karten: document.querySelectorAll(".vorlagenbrett__karte").length,
/* WIE VIELE ZEILEN BRAUCHT DIE FRIST? Gemessen ueber einen
Bereich um den TEXT, nicht ueber das Element.
ERST FALSCH GEMESSEN, und die Gegenprobe hat es verraten:
`element.getClientRects()` liefert hier IMMER genau ein
Rechteck, weil ein Flex-Kind zu einem Block wird -- die
Pruefung blieb gruen, auch mit dem Fehler wieder eingebaut.
Ein Bereich ueber den Textknoten dagegen gibt pro Zeilenkasten
ein Rechteck, und genau das ist die Frage: Steht "in 2 Tagen"
auf einer Zeile oder als "in / 2 / Tagen" untereinander? */
fristZeilen: [...document.querySelectorAll(".vorlagenbrett__frist")]
.map((z) => {
const b = document.createRange();
b.selectNodeContents(z);
return b.getClientRects().length;
}),
/* Und wie viele Karten tragen ueberhaupt den DRITTEN Eintrag, an
dem es eng wurde. Ohne diese Zahl wuerde die Zeile darueber
auch dann gruen, wenn der enge Fall gar nicht auf dem Schirm
war. */
engeKarten: document.querySelectorAll(".vorlagenbrett__schon").length,
text: document.body.innerText,
kopf: (document.querySelector(".kopfleiste .marke__text") || {}).textContent || "",
}));
@@ -334,9 +365,49 @@ console.log("\n=== 6. Das Brett im echten Browser ===\n");
/* Und der Seitenname dahinter steht noch da -- ihn beim Austausch
zu verlieren waere lautlos passiert. */
ok(/Aufgaben/.test(bild.kopf), "der Seitenname dahinter blieb erhalten");
/* DIE FUSSZEILE DER KARTEN (16.09.2026, auf dem Bildschirmfoto
gefunden). Bei einer schon uebernommenen Aufgabe stehen dort
drei Dinge statt zwei, und "Frist: in 2 Tagen" brach mitten im
Wort auf drei Zeilen um. Die Karten sind alle gleich breit --
eine einzige gequetschte reicht, um den Fehler zu zeigen. */
ok(bild.engeKarten > 0,
`${bild.engeKarten} Karten tragen den dritten Fusseintrag (der enge Fall)`);
const zuViel = bild.fristZeilen.filter((n) => n !== 1).length;
ok(bild.fristZeilen.length > 0 && zuViel === 0,
`jede der ${bild.fristZeilen.length} Fristangaben steht auf einer Zeile`
+ (zuViel ? ` -- ${zuViel} umgebrochen` : ""));
/* UMLAUTE AUF DEM FERTIGEN BILDSCHIRM (16.09.2026).
Am 16.09. stand unter jeder Kategorie eine Erklaerung in ASCII:
"Was im Livechat passiert, waehrend gesendet wird. Loeschen,
stummschalten, begruessen". Alles gruen, niemand hat es gemerkt.
HIER und nicht im Quelltext, weil hier der Unterschied sichtbar
wird, auf den es ankommt: `innerText` ist, was ein Mensch liest.
Feldnamen, Stilklassen und Adressen -- die ASCII sein MUESSEN --
stehen nicht drin. Im Quelltext derselben Skripte schlaegt
dieselbe Liste 71 Mal an, und kein einziges Mal zu Recht.
Die Kataloge und die festen Seitentexte prueft
pruef-deutsche-texte, ohne Browser. */
const ersatz = ersatzschreibungen(bild.text);
ok(bild.text.length > 400 && ersatz.length === 0,
ersatz.length
? `Ersatzschreibungen auf dem Brett: ${ersatz.join(", ")}`
: `der Text auf dem Brett traegt Umlaute (${bild.text.length} Zeichen geprueft)`);
/* GEGENPROBE, sonst hiesse "nichts gefunden" nur, dass nichts
gesucht wurde -- etwa wenn `innerText` leer bliebe. */
ok(ersatzschreibungen(`${bild.text} waehrend`).length === 1,
"und ein eingeschmuggeltes waehrend wuerde auffallen");
ok(konsole.length === 0,
konsole.length ? `Fehler in der Konsole: ${konsole[0]}` : "keine Fehler in der Konsole");
await seite.screenshot({ path: "pruef-modi-katalog.png", fullPage: false });
/* DER PFAD GEHOERT AN DIESE DATEI, nicht ans Arbeitsverzeichnis.
Vorher stand hier ein blosser Dateiname: Das Bild landete dort,
von wo aus gestartet wurde, waehrend die Zeile darunter
"server/..." meldete. Man sucht es dann an der falschen Stelle
-- oder findet ein altes und haelt es fuer das neue. */
const bildPfad = fileURLToPath(new URL("pruef-modi-katalog.png", import.meta.url));
await seite.screenshot({ path: bildPfad, fullPage: false });
console.log(" -- Bildschirmfoto: server/pruef-modi-katalog.png");
await kontext.close();
} finally {
@@ -388,8 +459,8 @@ console.log("");
}
const wahl = await seite.evaluate(() => {
const reihen = [...document.querySelectorAll(".stufenleiter--fein")];
const letzte = reihen[reihen.length - 1];
const reihen = [...document.querySelectorAll(".stufenleiter")];
const letzte = document.querySelector('[aria-label="Person wählen"]');
const zahl = /^[0-9]+$/;
return {
reihen: reihen.length,
@@ -399,14 +470,19 @@ console.log("");
.every((z) => zahl.test(z.textContent.trim())),
zahlen: [...(letzte?.querySelectorAll(".stufenleiter__zahl") || [])]
.map((z) => z.textContent.trim()),
satz: [...document.querySelectorAll(".vorlagenbrett__stand")]
/* Der Satz steht seit dem 16.09.2026 in `stufenleiter__hilfe`
-- derselbe Baustein wie beim anderen Brett. Vorher war es
`vorlagenbrett__stand`, und das ist die Zeile fuer Zahlen. */
satz: [...document.querySelectorAll(".stufenleiter__hilfe")]
.map((z) => z.textContent.trim())
.find((t) => t.includes("Formular oben") || t.includes("gehen an")) || "",
};
});
/* ZWEI FEINE REIHEN: die Stufen und die Personen. Eine einzelne
Zahl haette nicht gesagt, welche der beiden fehlt. */
ok(wahl.reihen === 2, "zwei Auswahlreihen (Stufen und Personen): " + wahl.reihen);
/* DREI REIHEN: Kategorie, Stufe, Person. Die ersten beiden sehen
jetzt aus wie drueben beim anderen Brett. */
ok(wahl.reihen === 3, "drei Auswahlreihen (Kategorie, Stufe, Person): " + wahl.reihen);
ok(wahl.namen.includes("Marina"),
"der Modi steht zur Auswahl (" + wahl.namen.join(", ") + ")");
ok(!wahl.namen.includes("Tili") && !wahl.namen.includes("Schulle"),
@@ -420,14 +496,14 @@ console.log("");
DIESEM Menschen landet. Ein Knopf, den niemand betaetigt hat,
ist kein geprueter Knopf. */
await seite.evaluate(() => {
const reihen = [...document.querySelectorAll(".stufenleiter--fein")];
const letzte = reihen[reihen.length - 1];
const reihen = [...document.querySelectorAll(".stufenleiter")];
const letzte = document.querySelector('[aria-label="Person wählen"]');
[...letzte.querySelectorAll(".stufenleiter__knopf")]
.find((k) => k.textContent.includes("Marina"))?.click();
});
await seite.waitForTimeout(600);
const nachWahl = await seite.evaluate(() =>
[...document.querySelectorAll(".vorlagenbrett__stand")]
[...document.querySelectorAll(".stufenleiter__hilfe")]
.map((z) => z.textContent.trim()).find((t) => t.includes("gehen an")) || "");
ok(nachWahl.includes("Marina"), "nach dem Klick steht es da: " + nachWahl);
+18 -18
View File
@@ -1161,46 +1161,46 @@ const MODI_MARKE = "Team Dogi";
* Anleitung: Er wird dort gebraucht, wo man sich entscheidet. */
export const MODI_KATEGORIEN = [
{ wert: "chat", name: "Chat-Moderation",
text: "Was im Livechat passiert, waehrend gesendet wird. Loeschen, "
+ "stummschalten, begruessen, deeskalieren." },
text: "Was im Livechat passiert, während gesendet wird. Löschen, "
+ "stummschalten, begrüßen, deeskalieren." },
{ wert: "community", name: "Community",
text: "Die Menschen ausserhalb der Sendung: wer wiederkommt, wer neu "
text: "Die Menschen außerhalb der Sendung: wer wiederkommt, wer neu "
+ "ist, wer lange nicht da war." },
{ wert: "events", name: "Events",
text: "Alles mit einem Termin: Matches, Aktionen, Geburtstage, "
+ "besondere Sendungen." },
{ wert: "clipping", name: "Clipping",
text: "Aus einer Sendung viele Videos machen -- schneiden, "
text: "Aus einer Sendung viele Videos machen — schneiden, "
+ "beschriften, hochladen." },
{ wert: "social", name: "Social Media",
text: "Alles ausserhalb des Livestreams: Ankuendigungen, Beitraege, "
text: "Alles außerhalb des Livestreams: Ankündigungen, Beiträge, "
+ "Antworten unter Videos." },
{ wert: "technik", name: "Technik",
text: "Ton, Bild, Verbindung, Geraete. Meistens unsichtbar -- und "
text: "Ton, Bild, Verbindung, Geräte. Meistens unsichtbar — und "
+ "sofort sichtbar, wenn es fehlt." },
{ wert: "planung", name: "Planung",
text: "Was NOCH NICHT ist: Sendeplan, Themen, wer wann kann." },
{ wert: "organisation", name: "Organisation",
text: "Was BEREITS ist, in Ordnung halten: Ablage, Listen, Zugaenge, "
+ "Uebersichten." },
text: "Was BEREITS ist, in Ordnung halten: Ablage, Listen, Zugänge, "
+ "Übersichten." },
{ wert: "team", name: "Team",
text: "Die Zusammenarbeit selbst: Uebergaben, Einarbeitung, "
text: "Die Zusammenarbeit selbst: Übergaben, Einarbeitung, "
+ "Absprachen, Vertretung." },
{ wert: "kommunikation", name: "Kommunikation",
text: "Was nach aussen geht und beantwortet werden muss: "
text: "Was nach außen geht und beantwortet werden muss: "
+ "Nachrichten, Anfragen, Kooperationen." },
{ wert: "analyse", name: "Analyse",
text: "Nachsehen statt schaetzen: Zahlen, Verlaeufe, was sich "
+ "veraendert hat." },
text: "Nachsehen statt schätzen: Zahlen, Verläufe, was sich "
+ "verändert hat." },
{ wert: "wachstum", name: "Wachstum",
text: "Gezielt mehr werden: neue Zuschauer, neue Kanaele, neue "
text: "Gezielt mehr werden: neue Zuschauer, neue Kanäle, neue "
+ "Zeiten ausprobieren." },
{ wert: "branding", name: "Branding",
text: "Wie es aussieht und klingt: Farben, Zeichen, Sprache, "
+ "Wiedererkennung." },
{ wert: "sonstiges", name: "Sonstiges",
text: "Was in keine der dreizehn passt. Bleibt absichtlich klein -- "
+ "wird es gross, fehlt eine Kategorie." },
text: "Was in keine der dreizehn passt. Bleibt absichtlich klein — "
+ "wird es groß, fehlt eine Kategorie." },
];
/** Die drei Stufen einer Modi-Aufgabe.
@@ -1215,12 +1215,12 @@ export const MODI_KATEGORIEN = [
export const MODI_STUFEN = [
{ wert: "neu", name: "Neu dabei",
text: "Die ersten Wochen. Klar umrissen, ohne Folgen, wenn etwas "
+ "schiefgeht -- und jemand ist erreichbar." },
+ "schiefgeht — und jemand ist erreichbar." },
{ wert: "dabei", name: "Eingearbeitet",
text: "Kennt den Laden. Kann allein entscheiden, ohne vorher zu "
+ "fragen, und weiss, wann man doch fragt." },
+ "fragen, und weiß, wann man doch fragt." },
{ wert: "erfahren", name: "Erfahren",
text: "Traegt Verantwortung fuer andere: arbeitet ein, vertritt, "
text: "Trägt Verantwortung für andere: arbeitet ein, vertritt, "
+ "entscheidet im Zweifel." },
];
/**