WEB-3: lokale Webseiten-Vorschau - GET /api/preview/{**path} (rendert live, korrekte Content-Types, nur Veroeffentlichte) + /webseite/vorschau (iframe, Seiten-Wechsler, Smartphone/Desktop-Umschalter, Neu laden) + Einstiege auf der Uebersicht + Fix: pages.ts rief /pages statt /api/pages (live-404, vom Mock kaschiert) + 1 Backend-Roundtrip + 4 e2e-Specs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 12:18:07 +02:00
parent aa345aa796
commit d5544412bd
10 changed files with 398 additions and 8 deletions

View File

@@ -0,0 +1,66 @@
/**
* WEB-3: Lokale Vorschau der öffentlichen Webseite — iframe lädt die
* gerenderte Seite, Seiten-Wechsler (nur Veröffentlichte), Smartphone/
* Desktop-Umschalter, Einstiege von der Übersicht.
* Mock-gebunden (Seed-Seiten) → skipUnlessMock.
*/
import { de, expect, skipUnlessMock, test } from './fixtures'
const tw = de.pages.webseite
const tv = tw.vorschau
test.describe('Webseiten-Vorschau', () => {
test('Vorschau öffnet die gerenderte Startseite im iframe', async ({ page }) => {
skipUnlessMock()
await page.goto('/webseite')
await page.getByRole('link', { name: tv.button }).click()
await expect(page.getByRole('heading', { name: tv.title })).toBeVisible()
await expect(page.getByText(tv.intro)).toBeVisible()
// Inhalt der gerenderten Seite (Mock-HTML) ist im iframe sichtbar
const frame = page.frameLocator('.vorschau-iframe')
await expect(frame.getByRole('heading', { name: 'Startseite' })).toBeVisible()
})
test('Seiten-Wechsler listet nur Veröffentlichte und wechselt die Vorschau', async ({ page }) => {
skipUnlessMock()
await page.goto('/webseite/vorschau')
const select = page.getByLabel(tv.pageSelect)
// 2 veröffentlichte Seed-Seiten; Entwürfe (z. B. „Über die Zucht“) fehlen
await expect(select.locator('option')).toHaveCount(2)
await expect(select.locator('option', { hasText: 'Über die Zucht' })).toHaveCount(0)
await select.selectOption({ label: 'Abgabetiere' })
const frame = page.frameLocator('.vorschau-iframe')
await expect(frame.getByRole('heading', { name: 'Abgabetiere' })).toBeVisible()
})
test('Smartphone/Desktop-Umschalter ändert die Rahmenbreite', async ({ page }) => {
skipUnlessMock()
await page.goto('/webseite/vorschau')
// Standard: Smartphone-Rahmen
await expect(page.locator('.vorschau-frame--phone')).toBeVisible()
await page.getByRole('button', { name: tv.viewDesktop }).click()
await expect(page.locator('.vorschau-frame--phone')).toHaveCount(0)
await page.getByRole('button', { name: tv.viewPhone }).click()
await expect(page.locator('.vorschau-frame--phone')).toBeVisible()
})
test('Übersicht: „Ansehen“ nur bei Veröffentlichten, öffnet die richtige Seite', async ({ page }) => {
skipUnlessMock()
await page.goto('/webseite')
// Veröffentlichte Karte hat den Ansehen-Link, Entwurf nicht
const abgabeCard = page.locator('.webseite-card', { hasText: 'Abgabetiere' })
const draftCard = page.locator('.webseite-card', { hasText: 'Über die Zucht' })
await expect(abgabeCard.getByRole('link', { name: tv.openPage })).toBeVisible()
await expect(draftCard.getByRole('link', { name: tv.openPage })).toHaveCount(0)
await abgabeCard.getByRole('link', { name: tv.openPage }).click()
await expect(page).toHaveURL(/\/webseite\/vorschau\?seite=abgabetiere/)
const frame = page.frameLocator('.vorschau-iframe')
await expect(frame.getByRole('heading', { name: 'Abgabetiere' })).toBeVisible()
})
})