docs/ANLEITUNG.md führt einmal durch die ganze Anwendung — von der ersten Anmeldung über das tägliche Abhaken bis zu Universen, Statistik und Verwaltung, mit 18 Aufnahmen aus der laufenden Instanz. Die Bilder entstehen mit npm run screenshots: aufgenommen mit doppelter Pixeldichte für scharfe Schrift, abgelegt als WebP in halber Kantenlänge — 13 MB werden so zu 0,6 MB.
100 lines
3.6 KiB
JavaScript
100 lines
3.6 KiB
JavaScript
import { chromium } from "playwright";
|
|
import fs from "node:fs";
|
|
|
|
const OUT = "docs/screenshots";
|
|
const BASE = "http://localhost:3011";
|
|
fs.mkdirSync(OUT, { recursive: true });
|
|
|
|
const browser = await chromium.launch();
|
|
const errs = [];
|
|
|
|
async function session(width, height, theme) {
|
|
const ctx = await browser.newContext({
|
|
viewport: { width, height },
|
|
deviceScaleFactor: 2,
|
|
colorScheme: theme === "light" ? "light" : "dark",
|
|
locale: "de-DE",
|
|
timezoneId: "Europe/Berlin",
|
|
});
|
|
await ctx.addInitScript((mode) => localStorage.setItem("flimmer-theme", mode), theme);
|
|
// Der Entwicklungs-Indikator von Next hat in einer Anleitung nichts verloren.
|
|
await ctx.addStyleTag?.({ content: "nextjs-portal { display: none !important; }" });
|
|
const page = await ctx.newPage();
|
|
await page.addStyleTag({ content: "nextjs-portal { display: none !important; }" }).catch(() => {});
|
|
page.on("pageerror", (e) => errs.push(String(e).slice(0, 160)));
|
|
return { ctx, page };
|
|
}
|
|
|
|
async function login(page) {
|
|
await page.goto(`${BASE}/anmelden`);
|
|
await page.fill("#email", "demo@flimmer.local");
|
|
await page.fill("#password", "flimmer-demo-2026");
|
|
await Promise.all([page.waitForURL(`${BASE}/`), page.click("button[type=submit]")]);
|
|
}
|
|
|
|
async function shot(page, name, url, opts = {}) {
|
|
await page.goto(`${BASE}${url}`, { waitUntil: "networkidle" });
|
|
await page.addStyleTag({ content: "nextjs-portal { display: none !important; }" }).catch(() => {});
|
|
await page.waitForTimeout(opts.wait ?? 900);
|
|
if (opts.before) await opts.before(page);
|
|
await page.screenshot({ path: `${OUT}/${name}.png`, fullPage: Boolean(opts.full) });
|
|
console.log(" ", name);
|
|
}
|
|
|
|
// --- Anmeldung (ohne Sitzung) ---
|
|
{
|
|
const { ctx, page } = await session(1280, 800, "dark");
|
|
await shot(page, "01-anmeldung", "/anmelden");
|
|
await ctx.close();
|
|
}
|
|
|
|
// --- Angemeldet, dunkel ---
|
|
{
|
|
const { ctx, page } = await session(1400, 900, "dark");
|
|
await login(page);
|
|
|
|
await shot(page, "02-uebersicht", "/", { full: true });
|
|
await shot(page, "03-suche", "/suche?q=sternenpfad");
|
|
await shot(page, "05-bibliothek", "/bibliothek");
|
|
await shot(page, "09-kalender", "/kalender");
|
|
await shot(page, "10-statistik", "/statistik", { full: true });
|
|
await shot(page, "11-einstellungen", "/einstellungen");
|
|
await shot(page, "12-benachrichtigungen", "/einstellungen/benachrichtigungen");
|
|
await shot(page, "13-api", "/einstellungen/api");
|
|
await shot(page, "14-daten", "/einstellungen/daten");
|
|
await shot(page, "15-verwaltung", "/verwaltung", { full: true });
|
|
await shot(page, "16-papierkorb", "/papierkorb");
|
|
|
|
// Detailseite und Universum brauchen IDs aus der Bibliothek
|
|
await page.goto(`${BASE}/bibliothek?q=nordlicht`, { waitUntil: "networkidle" });
|
|
const titleHref = await page.locator("a[href^='/titel/']").first().getAttribute("href");
|
|
if (titleHref) await shot(page, "04-serie", titleHref, { full: true });
|
|
|
|
await page.goto(`${BASE}/universen`, { waitUntil: "networkidle" });
|
|
await shot(page, "06-universen", "/universen");
|
|
const uniHref = await page.locator("a[href^='/universen/']").first().getAttribute("href");
|
|
if (uniHref) await shot(page, "07-universum", uniHref, { full: true });
|
|
|
|
await ctx.close();
|
|
}
|
|
|
|
// --- Hell ---
|
|
{
|
|
const { ctx, page } = await session(1400, 900, "light");
|
|
await login(page);
|
|
await shot(page, "08-hell", "/bibliothek");
|
|
await ctx.close();
|
|
}
|
|
|
|
// --- Mobil ---
|
|
{
|
|
const { ctx, page } = await session(430, 900, "dark");
|
|
await login(page);
|
|
await shot(page, "17-mobil-uebersicht", "/");
|
|
await shot(page, "18-mobil-serie", "/bibliothek");
|
|
await ctx.close();
|
|
}
|
|
|
|
console.log("Fehler:", errs.length ? [...new Set(errs)].slice(0, 5) : "keine");
|
|
await browser.close();
|