Pruefskripte: wiederholbar und ehrlich machen
Die Dichtheitspruefung der Musterloesungen las die Server-Nutzlast aus self.__next_f - das Feld leert Next nach der Verarbeitung, es war also immer leer. Die Pruefung lief an dieser Stelle ins Leere, ohne dass es auffiel; nur der HTML-Quelltext wurde wirklich geprueft. Gelesen wird jetzt der Quelltext der eingebetteten Skripte. Damit zeigt die Ausgabe, was sie zeigen soll: vor der Abgabe steht fuenfmal "musterloesung":null in der Nutzlast, danach stehen dort die Loesungen. Ausserdem stellt das Skript seine Ausgangslage selbst her und laeuft gegen den Port, der ueber LERNBAR_BASIS eingestellt ist - vorher war 3311 fest eingetragen und ein zweiter Lauf scheiterte daran, dass die Kontrolle schon abgegeben war. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c61d5711e0
commit
6181ec4bd7
@@ -11,7 +11,7 @@ import path from 'node:path';
|
||||
* im sichtbaren Text.
|
||||
*/
|
||||
|
||||
const BASIS = 'http://localhost:3311';
|
||||
const BASIS = process.env.LERNBAR_BASIS ?? 'http://localhost:3000';
|
||||
const AZUBI = { email: 'jonas.berger@betrieb.de', pw: 'azubi-start-2026' };
|
||||
const AUSBILDER = { email: 'fw@wildeflorian.de', pw: 'ausbilder-start' };
|
||||
|
||||
@@ -26,6 +26,29 @@ const bruchstuecke = loesungen.map((l) => l.slice(40, 110)).filter((b) => b.leng
|
||||
console.log(`${loesungen.length} Musterlösungen aus woche-01.yaml gelesen.`);
|
||||
console.log('Geprüft wird auf Bruchstücke wie:', JSON.stringify(bruchstuecke[0]?.slice(0, 60)));
|
||||
|
||||
// --- Ausgangslage herstellen ----------------------------------------------
|
||||
//
|
||||
// Der entscheidende Fall ist „freigegeben, aber noch nicht abgegeben". Den gibt
|
||||
// es nur einmal je Kontrolle. Damit die Prüfung wiederholbar bleibt, wird die
|
||||
// Kontrolle „woche-01" vorher zurückgesetzt – das ist ein Testaufbau, kein Teil
|
||||
// der Anwendung, und greift deshalb ausdrücklich nur auf die lokale
|
||||
// Beispieldatenbank zu.
|
||||
const { default: Datenbank } = await import('better-sqlite3');
|
||||
const dbPfad = process.env.LERNBAR_DB ?? path.join(process.cwd(), 'daten', 'lernbar.sqlite');
|
||||
|
||||
if (fs.existsSync(dbPfad)) {
|
||||
const db = new Datenbank(dbPfad);
|
||||
const betroffen = db.prepare("select id from kontrolle where kontrolle_id = 'woche-01'").all();
|
||||
for (const eintrag of betroffen) {
|
||||
db.prepare('delete from kontroll_antwort where kontrolle_id = ?').run(eintrag.id);
|
||||
db.prepare('delete from kontrolle where id = ?').run(eintrag.id);
|
||||
}
|
||||
db.close();
|
||||
console.log(`Ausgangslage hergestellt: ${betroffen.length} frühere Bearbeitung(en) von woche-01 entfernt.`);
|
||||
} else {
|
||||
console.log(`Keine Datenbank unter ${dbPfad} – die Ausgangslage wird nicht zurückgesetzt.`);
|
||||
}
|
||||
|
||||
const browser = await chromium.launch();
|
||||
const seite = await (await browser.newContext({ locale: 'de-DE' })).newPage();
|
||||
|
||||
@@ -41,13 +64,19 @@ async function abmelden() {
|
||||
await seite.waitForURL(/anmelden/);
|
||||
}
|
||||
|
||||
/** Sucht im rohen HTML **und** in der RSC-Nutzlast. */
|
||||
/** Sucht im rohen HTML **und** in der Server-Nutzlast. */
|
||||
async function lecksuche(beschriftung) {
|
||||
const html = await seite.content();
|
||||
|
||||
// Die Nutzlast steht in eingebetteten Skripten, die `self.__next_f` füllen.
|
||||
// Dort **nachträglich** nachzusehen bringt nichts: Next leert das Feld, sobald
|
||||
// es verarbeitet ist – es wäre immer leer, und die Prüfung liefe ins Leere,
|
||||
// ohne dass es auffällt. Deshalb wird der Quelltext der Skripte gelesen.
|
||||
const rsc = await seite.evaluate(() =>
|
||||
// Next legt die Server-Nutzlast in self.__next_f ab – dort steht alles,
|
||||
// was der Server an den Browser geschickt hat.
|
||||
(globalThis.self?.__next_f ?? []).map((t) => (Array.isArray(t) ? String(t[1] ?? '') : '')).join(''),
|
||||
[...document.querySelectorAll('script:not([src])')]
|
||||
.map((element) => element.textContent ?? '')
|
||||
.filter((text) => text.includes('__next_f'))
|
||||
.join(''),
|
||||
);
|
||||
|
||||
const treffer = bruchstuecke.filter((b) => html.includes(b) || rsc.includes(b));
|
||||
@@ -55,7 +84,7 @@ async function lecksuche(beschriftung) {
|
||||
|
||||
console.log(
|
||||
` ${beschriftung.padEnd(34)} Leck: ${treffer.length === 0 ? 'nein' : `JA (${treffer.length})`}` +
|
||||
` | RSC-Größe ${rsc.length} | "musterloesung":null ${nullFelder}x`,
|
||||
` | Nutzlast ${rsc.length} Zeichen | "musterloesung":null ${nullFelder}x`,
|
||||
);
|
||||
return treffer;
|
||||
}
|
||||
@@ -71,8 +100,17 @@ await abmelden();
|
||||
await anmelden(AUSBILDER);
|
||||
await seite.goto(`${BASIS}/kontrollen`);
|
||||
await seite.waitForSelector('.kontrollzeile');
|
||||
await seite.locator('.kontrollzeile', { hasText: 'Woche 1' }).locator('button:has-text("Freigeben")').click();
|
||||
await seite.waitForTimeout(1500);
|
||||
const freigeben = seite
|
||||
.locator('.kontrollzeile', { hasText: 'Woche 1' })
|
||||
.locator('button:has-text("Freigeben")');
|
||||
if ((await freigeben.count()) > 0) {
|
||||
await freigeben.click();
|
||||
await seite.waitForTimeout(1500);
|
||||
} else {
|
||||
// Bei einem wiederholten Lauf ist sie schon freigegeben. Das ist kein
|
||||
// Grund abzubrechen – der entscheidende Fall kommt erst danach.
|
||||
console.log(' (war bereits freigegeben)');
|
||||
}
|
||||
|
||||
console.log('\n3) Nach der Freigabe, vor der Abgabe – der entscheidende Fall');
|
||||
await abmelden();
|
||||
|
||||
Reference in New Issue
Block a user