Files
planer/screenshots/bilder.spec.ts
T
Florian WildeandClaude Opus 5 5bbbdd5209 chore: Demo-Daten und Bildaufnahme fuer Benachrichtigungen
Die Aufnahme kann jetzt einen einzelnen Ausschnitt statt der ganzen Seite
festhalten. Ein Bild der kompletten Einstellungsseite zeigt im Kapitel zu
den Benachrichtigungen zu wenig vom Eigentlichen.

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

109 lines
3.4 KiB
TypeScript

import { mkdir } from 'node:fs/promises'
import { test, type Page } from '@playwright/test'
/**
* Nimmt die Bilder für das Handbuch auf.
*
* Je Seite vier Bilder: hell und dunkel, Schreibtisch und Handy. Die Uhr steht
* auf einem festen Zeitpunkt, damit sich zwischen zwei Läufen nur das ändert,
* was sich wirklich geändert hat.
*/
const ZIEL = 'docs/bilder'
const SCHREIBTISCH = { width: 1440, height: 900 }
const HANDY = { width: 390, height: 844 }
// Dienstag, 17. März 2026, 09:20 Uhr in Berlin.
const FESTE_ZEIT = new Date('2026-03-17T08:20:00.000Z')
const EMAIL = 'martina.beispiel@planer.invalid'
const PASSWORT = 'demo-instanz-nur-fuer-bilder'
type Aufnahme = {
name: string
pfad: string
/** Wird vor der Aufnahme ausgeführt, z. B. um ein Formular aufzuklappen. */
vorbereiten?: (seite: Page) => Promise<void>
/**
* Nur diesen Ausschnitt aufnehmen statt der ganzen Seite.
*
* Für Themen, die auf einer gemeinsamen Seite wohnen: ein Bild der ganzen
* Einstellungsseite zeigt im Handbuchkapitel zu wenig vom Eigentlichen.
*/
ausschnitt?: string
}
const AUFNAHMEN: Aufnahme[] = [
{ name: 'anmelden', pfad: '/anmelden' },
{ name: 'start', pfad: '/' },
{ name: 'inbox', pfad: '/inbox' },
{ name: 'aufgaben', pfad: '/aufgaben' },
{ name: 'woche', pfad: '/woche' },
{ name: 'projekte', pfad: '/projekte' },
{ name: 'ideen', pfad: '/ideen' },
{ name: 'bereiche', pfad: '/bereiche' },
{ name: 'kalenderkonten', pfad: '/kalenderkonten' },
{ name: 'einstellungen', pfad: '/einstellungen' },
{
name: 'benachrichtigungen',
pfad: '/einstellungen',
ausschnitt: '[data-bild="benachrichtigungen"]',
},
{ name: 'protokoll', pfad: '/verwaltung/protokoll' },
]
async function anmelden(seite: Page): Promise<void> {
await seite.goto('/anmelden')
await seite.getByLabel('E-Mail-Adresse').fill(EMAIL)
await seite.getByLabel('Passwort').fill(PASSWORT)
await seite.getByRole('button', { name: 'Mit Passwort anmelden' }).click()
await seite.waitForURL('/')
}
test.beforeAll(async () => {
await mkdir(ZIEL, { recursive: true })
})
for (const schema of ['hell', 'dunkel'] as const) {
for (const [geraet, groesse] of [
['schreibtisch', SCHREIBTISCH],
['handy', HANDY],
] as const) {
test(`Bilder: ${schema}, ${geraet}`, async ({ browser }) => {
const kontext = await browser.newContext({
viewport: groesse,
colorScheme: schema === 'dunkel' ? 'dark' : 'light',
deviceScaleFactor: 2,
})
const seite = await kontext.newPage()
await seite.clock.setFixedTime(FESTE_ZEIT)
for (const aufnahme of AUFNAHMEN) {
if (aufnahme.pfad !== '/anmelden') {
// Für alles außer der Anmeldeseite braucht es eine Sitzung.
if (
!(await seite.context().cookies()).some((k) => k.name.includes('session'))
) {
await anmelden(seite)
}
}
await seite.goto(aufnahme.pfad)
await seite.waitForLoadState('networkidle')
await aufnahme.vorbereiten?.(seite)
// Der Farbschema-Umschalter und Schriften sollen fertig sein.
await seite.waitForTimeout(300)
const ziel = `${ZIEL}/${aufnahme.name}-${schema}-${geraet}.png`
if (aufnahme.ausschnitt) {
await seite.locator(aufnahme.ausschnitt).screenshot({ path: ziel })
} else {
await seite.screenshot({ path: ziel, fullPage: true })
}
}
await kontext.close()
})
}
}