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.
|
* 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 AZUBI = { email: 'jonas.berger@betrieb.de', pw: 'azubi-start-2026' };
|
||||||
const AUSBILDER = { email: 'fw@wildeflorian.de', pw: 'ausbilder-start' };
|
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(`${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)));
|
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 browser = await chromium.launch();
|
||||||
const seite = await (await browser.newContext({ locale: 'de-DE' })).newPage();
|
const seite = await (await browser.newContext({ locale: 'de-DE' })).newPage();
|
||||||
|
|
||||||
@@ -41,13 +64,19 @@ async function abmelden() {
|
|||||||
await seite.waitForURL(/anmelden/);
|
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) {
|
async function lecksuche(beschriftung) {
|
||||||
const html = await seite.content();
|
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(() =>
|
const rsc = await seite.evaluate(() =>
|
||||||
// Next legt die Server-Nutzlast in self.__next_f ab – dort steht alles,
|
[...document.querySelectorAll('script:not([src])')]
|
||||||
// was der Server an den Browser geschickt hat.
|
.map((element) => element.textContent ?? '')
|
||||||
(globalThis.self?.__next_f ?? []).map((t) => (Array.isArray(t) ? String(t[1] ?? '') : '')).join(''),
|
.filter((text) => text.includes('__next_f'))
|
||||||
|
.join(''),
|
||||||
);
|
);
|
||||||
|
|
||||||
const treffer = bruchstuecke.filter((b) => html.includes(b) || rsc.includes(b));
|
const treffer = bruchstuecke.filter((b) => html.includes(b) || rsc.includes(b));
|
||||||
@@ -55,7 +84,7 @@ async function lecksuche(beschriftung) {
|
|||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
` ${beschriftung.padEnd(34)} Leck: ${treffer.length === 0 ? 'nein' : `JA (${treffer.length})`}` +
|
` ${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;
|
return treffer;
|
||||||
}
|
}
|
||||||
@@ -71,8 +100,17 @@ await abmelden();
|
|||||||
await anmelden(AUSBILDER);
|
await anmelden(AUSBILDER);
|
||||||
await seite.goto(`${BASIS}/kontrollen`);
|
await seite.goto(`${BASIS}/kontrollen`);
|
||||||
await seite.waitForSelector('.kontrollzeile');
|
await seite.waitForSelector('.kontrollzeile');
|
||||||
await seite.locator('.kontrollzeile', { hasText: 'Woche 1' }).locator('button:has-text("Freigeben")').click();
|
const freigeben = seite
|
||||||
await seite.waitForTimeout(1500);
|
.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');
|
console.log('\n3) Nach der Freigabe, vor der Abgabe – der entscheidende Fall');
|
||||||
await abmelden();
|
await abmelden();
|
||||||
|
|||||||
Reference in New Issue
Block a user