Vorschau-Mock
`, + }) + } + // ── INBOX-1: Anfragen-Posteingang (vor den generischen Kollektionen) ── if (path === '/requests/sync' && method === 'POST') { return json(route, 200, db.mailConfigured ? { imported: 0, error: null } : { imported: 0, error: 'MailNotConfigured' }) diff --git a/gerbil-manager-web/e2e/webseite-vorschau.spec.ts b/gerbil-manager-web/e2e/webseite-vorschau.spec.ts new file mode 100644 index 0000000..f7f7288 --- /dev/null +++ b/gerbil-manager-web/e2e/webseite-vorschau.spec.ts @@ -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() + }) +}) diff --git a/gerbil-manager-web/src/App.tsx b/gerbil-manager-web/src/App.tsx index 8ab0c6e..017dfb2 100644 --- a/gerbil-manager-web/src/App.tsx +++ b/gerbil-manager-web/src/App.tsx @@ -24,6 +24,7 @@ import VertragWizardPage from './pages/VertragWizardPage' import EinstellungenPage from './pages/EinstellungenPage' import WebseitePage from './pages/WebseitePage' import WebseiteEditorPage from './pages/WebseiteEditorPage' +import WebseiteVorschauPage from './pages/WebseiteVorschauPage' import AnfragenPage from './pages/AnfragenPage' import AnfrageDetailPage from './pages/AnfrageDetailPage' @@ -72,6 +73,8 @@ export default function App() { {/* WEB-0b: CMS-Verwaltung der öffentlichen Webseite */}{t.intro}
+ {/* WEB-3: lokale Vorschau der gerenderten Webseite */} +{de.common.loading}
+ if (pages.error) { + return ( +{t.intro}
+{t.empty}
+ ) : ( + <> +