diff --git a/scripts/pruefungen/musterloesung-dichtheit.mjs b/scripts/pruefungen/musterloesung-dichtheit.mjs index 182a12a..64d3aef 100644 --- a/scripts/pruefungen/musterloesung-dichtheit.mjs +++ b/scripts/pruefungen/musterloesung-dichtheit.mjs @@ -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();