import { expect, test } from '@playwright/test'; /** * First-run setup wizard (issue #81). Runs only against the dedicated fresh * stack (empty database, setup still pending) that CI provisions on its own * ports — the regular e2e stack is seeded and long past setup. The tests * advance one shared instance's state, so they run serially. */ test.skip(!process.env.E2E_SETUP, 'requires the fresh setup stack (E2E_SETUP=1)'); test.describe.configure({ mode: 'serial' }); const SMTP_HOST = process.env.E2E_SMTP_HOST ?? 'mailpit'; const SMTP_PORT = process.env.E2E_SMTP_PORT ?? '1025'; test('while setup is pending, every route shows the pending screen', async ({ page }) => { await page.goto('/'); await page.getByRole('link', { name: /start setup|einrichtung starten/i }).click(); await expect(page).toHaveURL(/\/setup$/); await expect(page.getByRole('heading', { name: /welcome|willkommen/i })).toBeVisible(); }); test('a full wizard run configures the instance and ends signed in', async ({ page }) => { await page.goto('/setup'); // Language step — both languages must carry the wizard (AC): look at // German first, come back, then continue in English. await page.getByRole('button', { name: 'Deutsch' }).click(); await expect(page.getByRole('heading', { name: 'Site-Admin-Konto anlegen' })).toBeVisible(); await page.getByRole('button', { name: 'Zurück' }).click(); await page.getByRole('button', { name: 'English' }).click(); await expect(page.getByRole('heading', { name: 'Create the Site Admin account' })).toBeVisible(); // The admin step validates before advancing. await page.getByRole('button', { name: 'Create account & continue' }).click(); await expect(page.getByRole('alert').first()).toBeVisible(); await expect(page.getByRole('heading', { name: 'Create the Site Admin account' })).toBeVisible(); await page.getByLabel('Username').fill('wizard-admin'); await page.getByLabel('E-mail address').fill('wizard-admin@dorfteich.test'); await page.getByLabel('Display name').fill('Wizard Admin'); await page.getByLabel(/^Password/).fill('ein sehr langes wizard passwort'); await page.getByRole('button', { name: 'Create account & continue' }).click(); // Instance step; Back must preserve what was typed (AC). await expect(page.getByRole('heading', { name: 'Name your instance' })).toBeVisible(); await page.getByLabel('Instance name').fill('Wizard Pond'); await page.getByRole('button', { name: 'Continue' }).click(); await expect(page.getByRole('heading', { name: 'E-mail delivery' })).toBeVisible(); await page.getByRole('button', { name: 'Back' }).click(); await expect(page.getByLabel('Instance name')).toHaveValue('Wizard Pond'); await page.getByRole('button', { name: 'Continue' }).click(); // SMTP step: a dead relay blocks the step with the transport error… await page.getByLabel('SMTP server').fill('127.0.0.1'); await page.getByLabel('Port').fill('2525'); await page.getByLabel('Sender address').fill('dorfteich@dorfteich.test'); await page.getByRole('button', { name: 'Send test mail & continue' }).click(); await expect(page.getByText(/SMTP test failed/i)).toBeVisible(); await expect(page.getByRole('heading', { name: 'E-mail delivery' })).toBeVisible(); // …the real one (Mailpit in CI) lets it advance. await page.getByLabel('SMTP server').fill(SMTP_HOST); await page.getByLabel('Port').fill(SMTP_PORT); await page.getByRole('button', { name: 'Send test mail & continue' }).click(); // Registration step. await expect(page.getByRole('heading', { name: 'Who may join?' })).toBeVisible(); await page.getByRole('radio', { name: /open registration/i }).check(); await page.getByRole('button', { name: 'Continue' }).click(); // The summary shows the collected values; finishing unlocks the app. await expect(page.getByRole('heading', { name: 'Summary' })).toBeVisible(); await expect(page.getByText('Wizard Pond')).toBeVisible(); await expect(page.getByText('wizard-admin@dorfteich.test')).toBeVisible(); await page.getByRole('button', { name: 'Finish setup' }).click(); // Logged-in-ready (AC): the regular app loads with the admin's session. await expect(page).toHaveURL(/\/$/); await expect(page.getByRole('button', { name: 'Wizard Admin' })).toBeVisible(); }); test('the wizard url just goes home once setup completed', async ({ page }) => { // A fresh anonymous context: the app is unlocked, /setup redirects home, // and the regular login navigation is available again. await page.goto('/setup'); await expect(page).toHaveURL(/\/$/); await expect(page.getByRole('link', { name: /sign in|anmelden/i })).toBeVisible(); });