- Ausbilder gibt frei; vorher sieht der Azubi die Fragen nicht - Freigabe laesst sich zuruecknehmen, solange nicht abgegeben wurde - Antworten werden beim Tippen je Frage zwischengespeichert - Musterloesungen erst nach dem Absenden: sichtbareKontrolle() entfernt sie serverseitig, bevor die Daten in die Ausgabe gelangen - Korrektur mit Punkten und Anmerkung je Frage, Summe und Note laufen mit - Notenschluessel der IHK; solange eine Frage offen ist, bleibt das Ergebnis vorlaeufig und die Kontrolle gilt nicht als korrigiert - Ergebnis bei beiden sichtbar, Schnitt ueber alle Kontrollen - Abgegebene Kontrollen unter "Was auf dich wartet" und im Wochenfortschritt - scripts/pruefungen/musterloesung-dichtheit.mjs prueft die Sperre gegen den echten Wortlaut aus der Inhaltsdatei im rohen Seitenquelltext 36 neue Tests, davon 21 fuer die Sichtbarkeit der Musterloesung. Insgesamt 277. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
196 lines
6.2 KiB
TypeScript
196 lines
6.2 KiB
TypeScript
/**
|
||
* Nimmt die Bildschirmfotos für die Anleitung auf.
|
||
*
|
||
* npm run build && npm run start (in einer zweiten Konsole)
|
||
* npm run screenshots
|
||
*
|
||
* Die Bilder landen unter docs/bilder/ und werden bei jedem Lauf überschrieben.
|
||
* So veralten sie nicht – wer die Oberfläche ändert, lässt das Skript neu laufen.
|
||
*
|
||
* Umgebungsvariablen:
|
||
* LERNBAR_BASIS Adresse der laufenden Anwendung (Vorgabe http://localhost:3000)
|
||
* LERNBAR_AUSBILDER E-Mail des Ausbilderkontos
|
||
* LERNBAR_AZUBI E-Mail des Azubikontos
|
||
* LERNBAR_PASSWORT_* zugehörige Passwörter
|
||
*/
|
||
import fs from 'node:fs';
|
||
import path from 'node:path';
|
||
import { chromium, type Page } from '@playwright/test';
|
||
|
||
const BASIS = process.env.LERNBAR_BASIS ?? 'http://localhost:3000';
|
||
const ZIEL = path.join(process.cwd(), 'docs', 'bilder');
|
||
|
||
const AUSBILDER = {
|
||
email: process.env.LERNBAR_AUSBILDER ?? 'ausbilder@betrieb.de',
|
||
passwort: process.env.LERNBAR_PASSWORT_AUSBILDER ?? 'ausbilder-start',
|
||
};
|
||
const AZUBI = {
|
||
email: process.env.LERNBAR_AZUBI ?? 'azubi@betrieb.de',
|
||
passwort: process.env.LERNBAR_PASSWORT_AZUBI ?? 'azubi-start-2026',
|
||
};
|
||
|
||
const SCHREIBTISCH = { width: 1280, height: 900 };
|
||
const HANDY = { width: 390, height: 844 };
|
||
|
||
async function anmelden(seite: Page, konto: { email: string; passwort: string }) {
|
||
await seite.goto(`${BASIS}/anmelden`);
|
||
await seite.waitForSelector('#email');
|
||
await seite.fill('#email', konto.email);
|
||
await seite.fill('#passwort', konto.passwort);
|
||
await seite.click('button[type=submit]');
|
||
await seite.waitForURL(`${BASIS}/`);
|
||
}
|
||
|
||
async function abmelden(seite: Page) {
|
||
await seite.click('button:has-text("Abmelden")');
|
||
await seite.waitForURL(/anmelden/);
|
||
}
|
||
|
||
async function bild(seite: Page, name: string, ganzeSeite = true) {
|
||
const datei = path.join(ZIEL, `${name}.png`);
|
||
await seite.screenshot({ path: datei, fullPage: ganzeSeite });
|
||
console.log(` ${path.relative(process.cwd(), datei)}`);
|
||
}
|
||
|
||
async function main() {
|
||
fs.mkdirSync(ZIEL, { recursive: true });
|
||
|
||
const browser = await chromium.launch();
|
||
const umgebung = await browser.newContext({ viewport: SCHREIBTISCH, locale: 'de-DE', colorScheme: 'light' });
|
||
const seite = await umgebung.newPage();
|
||
|
||
console.log('Bildschirmfotos werden aufgenommen …');
|
||
|
||
// --- Anmeldung ---
|
||
await seite.goto(`${BASIS}/anmelden`);
|
||
await seite.waitForSelector('#email');
|
||
await bild(seite, '01-anmelden');
|
||
|
||
// --- Ausbilder ---
|
||
await anmelden(seite, AUSBILDER);
|
||
await bild(seite, '02-ausbilder-ueberblick');
|
||
|
||
await seite.goto(`${BASIS}/verwaltung`);
|
||
await seite.waitForSelector('#neu-name');
|
||
await bild(seite, '03-verwaltung');
|
||
|
||
await seite.goto(`${BASIS}/wochenplan`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '04-wochenplan');
|
||
|
||
await seite.goto(`${BASIS}/aufgaben`);
|
||
await seite.waitForSelector('h1');
|
||
const abnahme = await seite.$('a[href*="/aufgaben/1.1?azubi="]');
|
||
if (abnahme) {
|
||
await abnahme.click();
|
||
await seite.waitForSelector('#abnahme');
|
||
await bild(seite, '05-aufgabe-abnahme');
|
||
}
|
||
|
||
await abmelden(seite);
|
||
|
||
// --- Azubi ---
|
||
await anmelden(seite, AZUBI);
|
||
await bild(seite, '10-azubi-woche');
|
||
|
||
await seite.goto(`${BASIS}/handouts`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '11-handouts-liste');
|
||
|
||
await seite.goto(`${BASIS}/handouts?suche=subnetting`);
|
||
await seite.waitForSelector('h2');
|
||
await bild(seite, '12-handouts-suche');
|
||
|
||
await seite.goto(`${BASIS}/handouts/N3`);
|
||
await seite.waitForSelector('h1');
|
||
await seite.click('.pruefungsfrage > summary');
|
||
await bild(seite, '13-handout-n3');
|
||
|
||
await seite.goto(`${BASIS}/karten`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '14-merkkarten');
|
||
|
||
await seite.goto(`${BASIS}/aufgaben`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '16-aufgaben-liste');
|
||
|
||
await seite.goto(`${BASIS}/aufgaben/1.1`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '17-aufgabe-azubi');
|
||
|
||
await seite.goto(`${BASIS}/checklisten`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '18-checklisten');
|
||
|
||
await seite.goto(`${BASIS}/berichtsheft`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '21-berichtsheft');
|
||
|
||
await seite.goto(`${BASIS}/kontrollen`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '23-kontrollen');
|
||
|
||
await seite.goto(`${BASIS}/kontrollen/woche-03`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '24-kontrolle-ergebnis');
|
||
|
||
const blatt = await seite.$('.blattzeile-link');
|
||
if (blatt) {
|
||
await blatt.click();
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '22-wochenblatt');
|
||
}
|
||
|
||
const lauf = await seite.$('.laufzeile-haupt');
|
||
if (lauf) {
|
||
await lauf.click();
|
||
await seite.waitForSelector('.schrittliste');
|
||
await bild(seite, '19-checklisten-lauf');
|
||
}
|
||
|
||
await seite.goto(`${BASIS}/glossar`);
|
||
await seite.waitForSelector('h1');
|
||
await bild(seite, '15-glossar');
|
||
|
||
// --- Dunkle Darstellung ---
|
||
await seite.goto(`${BASIS}/handouts/N3`);
|
||
await seite.waitForSelector('button[aria-pressed]');
|
||
await seite.click('button[aria-pressed="false"]');
|
||
await seite.waitForTimeout(200);
|
||
await bild(seite, '20-dunkel');
|
||
await seite.click('button[aria-pressed="true"]');
|
||
|
||
// --- Handy ---
|
||
const handy = await browser.newContext({
|
||
viewport: HANDY,
|
||
locale: 'de-DE',
|
||
isMobile: true,
|
||
hasTouch: true,
|
||
deviceScaleFactor: 2,
|
||
});
|
||
const handySeite = await handy.newPage();
|
||
await anmelden(handySeite, AZUBI);
|
||
await handySeite.goto(`${BASIS}/handouts/N3`);
|
||
await handySeite.waitForSelector('h1');
|
||
await bild(handySeite, '30-handy-handout');
|
||
|
||
await handySeite.goto(`${BASIS}/karten/lernen`);
|
||
await handySeite.waitForSelector('.lernkarte, h1');
|
||
if (await handySeite.$('.lernkarte')) {
|
||
await bild(handySeite, '31-handy-lernmodus-frage', false);
|
||
await handySeite.tap('.lernkarte');
|
||
await handySeite.waitForSelector('.lernkarte-antwort');
|
||
await bild(handySeite, '32-handy-lernmodus-antwort', false);
|
||
}
|
||
|
||
await browser.close();
|
||
console.log('Fertig.');
|
||
}
|
||
|
||
main().catch((fehler) => {
|
||
console.error('Die Bildschirmfotos konnten nicht aufgenommen werden.');
|
||
console.error(fehler instanceof Error ? fehler.message : fehler);
|
||
console.error(`Läuft die Anwendung unter ${BASIS}? Stimmen LERNBAR_AUSBILDER und LERNBAR_AZUBI?`);
|
||
process.exit(1);
|
||
});
|