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>
109 lines
3.4 KiB
TypeScript
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()
|
|
})
|
|
}
|
|
}
|