Files
lernbar/scripts/screenshots.ts
T
Florian WildeandClaude Opus 5 7c4a051347 Baustein 7: Berichtsheft mit Vorschlaegen, Pruefung, Abzeichnen und PDF
- Taegliche Stichworte, je Tag ein eigenes Formular
- Wochenblatt mit Betrieb, Berufsschule und Sonstiges, je mit Stunden
- Vorschlaege aus Tagesnotizen, Aufgaben, Checklisten und Handouts
- Pruefung mitlaufend beim Tippen: fehlende Stunden, Floskeln,
  IP- und MAC-Adressen, E-Mail, Zugangsdaten, Kundennamen
- Warnung, keine Sperre - Einreichen ist immer moeglich
- Formulierungshilfe mit Taetigkeitsverben und Gegenueberstellungen
- Einreichen, zurueckgeben mit Anmerkung, abzeichnen; danach gesperrt
- Fehlende Wochen werden benannt und lassen sich nachtragen; die laufende
  Nummer richtet sich nach dem Zeitraum, nicht nach dem Anlegen
- PDF im IHK-Layout, einzeln oder als ganzer Zeitraum

Behoben: Im PDF-Kopffeld liefen die Spalten auseinander (dokument.y als
Bezugspunkt in der Schleife). Das Abzeichnen-Formular hatte keine action -
gefunden ueber die ESLint-Meldung zur ungenutzten Serveraktion.

55 neue Tests, insgesamt 241.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 23:09:54 +02:00

188 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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');
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);
});