Update Playwright staging flows and Paddle sandbox checkout

This commit is contained in:
Codex Agent
2026-01-03 17:04:32 +01:00
parent 43b626cbfc
commit ef05822b70
10 changed files with 341 additions and 203 deletions

View File

@@ -1,7 +1,8 @@
import { test, expectFixture as expect } from '../helpers/test-fixtures';
test.describe('Tenant admin add-on upgrades', () => {
test.beforeEach(async ({ signInTenantAdmin }) => {
test.beforeEach(async ({ tenantAdminCredentials, signInTenantAdmin }) => {
test.skip(!tenantAdminCredentials, 'Provide E2E_TENANT_EMAIL and E2E_TENANT_PASSWORD to run admin tests.');
await signInTenantAdmin();
});
@@ -125,7 +126,7 @@ test.describe('Tenant admin add-on upgrades', () => {
});
});
await page.goto('/event-admin/events/limit-event/photos');
await page.goto('/event-admin/mobile/events/limit-event/photos');
await expect(page.getByText(/Upload-Limit erreicht/i)).toBeVisible();
@@ -134,7 +135,6 @@ test.describe('Tenant admin add-on upgrades', () => {
await purchaseButton.click();
await expect(page).toHaveURL(/addon_success=1/);
await expect(page.getByText(/Add-on angewendet/i)).toBeVisible();
await expect(page.getByText(/Upload-Limit erreicht/i)).not.toBeVisible({ timeout: 10000 });
await expect(page.getByText(/\+500\s*Fotos/i)).toBeVisible();

View File

@@ -9,128 +9,115 @@ const futureDate = (daysAhead = 10): string => {
};
async function ensureOnDashboard(page: Page): Promise<void> {
await page.goto('/event-admin/dashboard');
await page.goto('/event-admin/mobile/dashboard');
await page.waitForLoadState('networkidle');
if (page.url().includes('/event-admin/welcome')) {
const directButton = page.getByRole('button', { name: /Direkt zum Dashboard/i });
if (page.url().includes('/event-admin/mobile/welcome')) {
const directButton = page.getByRole('button', { name: /Direkt zum Dashboard|Jump to dashboard|Dashboard/i });
if (await directButton.isVisible()) {
await directButton.click();
await page.waitForURL(/\/event-admin\/dashboard$/, { timeout: 15_000 });
await page.waitForURL(/\/event-admin\/mobile\/dashboard$/, { timeout: 15_000 });
}
}
}
test.describe('Tenant Admin PWA end-to-end coverage', () => {
test.beforeEach(async ({ signInTenantAdmin }) => {
test.beforeEach(async ({ tenantAdminCredentials, signInTenantAdmin }) => {
test.skip(!tenantAdminCredentials, 'Provide E2E_TENANT_EMAIL and E2E_TENANT_PASSWORD to run admin tests.');
await signInTenantAdmin();
});
test('dashboard highlights core stats and quick actions', async ({ page }) => {
await ensureOnDashboard(page);
await expect(page.getByRole('heading', { name: /Hallo/i })).toBeVisible();
await expect(page.getByRole('button', { name: /Neues Event/i })).toBeVisible();
await expect(page.getByText(/Schnellaktionen/i)).toBeVisible();
await expect(page.getByText(/Kommende Events/i)).toBeVisible();
await expect(page.getByText(/Dashboard/i)).toBeVisible();
await expect(page.getByRole('button', { name: /Event erstellen|Create event/i })).toBeVisible();
});
test('event creation flow and detail subsections', async ({ page }) => {
const eventName = `Playwright Event ${Date.now()}`;
const eventDate = futureDate(14);
await page.goto('/event-admin/events/new');
await page.goto('/event-admin/mobile/events/new');
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: /Eventdetails/i })).toBeVisible();
await expect(page.getByText(/Event/i)).toBeVisible();
await page.getByLabel(/Eventname/i).fill(eventName);
await page.getByLabel(/Datum/i).fill(eventDate);
await page.getByPlaceholder(/Sommerfest|Summer Party/i).fill(eventName);
await page.locator('input[type="datetime-local"]').fill(`${eventDate}T18:00`);
const eventTypeTrigger = page.getByRole('combobox', { name: /Event-Typ/i });
await eventTypeTrigger.click();
const firstOption = page.getByRole('option').first();
await expect(firstOption).toBeVisible({ timeout: 5_000 });
await firstOption.click();
const typeSelect = page.locator('select').first();
await typeSelect.selectOption({ index: 1 });
await page.getByRole('button', { name: /^Speichern/i }).click();
await expect(page).toHaveURL(/\/event-admin\/events\/[a-z0-9-]+$/, { timeout: 20_000 });
const createdSlug = page.url().split('/').pop() ?? '';
await page.getByRole('button', { name: /Event erstellen|Create event/i }).click();
await expect(page).toHaveURL(/\/event-admin\/mobile\/events\/[a-z0-9-]+$/, { timeout: 20_000 });
await expect(page.getByRole('heading', { name: /Eventdetails/i })).toBeVisible();
const createdSlug = new URL(page.url()).pathname.split('/').pop() ?? '';
await expect(page.getByText(eventName)).toBeVisible();
await page.goto('/event-admin/events');
await page.goto('/event-admin/mobile/events');
await page.waitForLoadState('networkidle');
await expect(page.getByText(eventName, { exact: false })).toBeVisible();
await page.goto(`/event-admin/events/${createdSlug}/photos`);
await expect(page.getByRole('heading', { name: /Fotos moderieren/i })).toBeVisible();
await expect(page.getByText(/Noch keine Fotos vorhanden/i)).toBeVisible();
await page.goto(`/event-admin/mobile/events/${createdSlug}/photos`);
await expect(page.getByText(/Foto-Moderation|Photo moderation/i)).toBeVisible();
await page.goto(`/event-admin/events/${createdSlug}/members`);
await expect(page.getByRole('heading', { name: /Event-Mitglieder/i })).toBeVisible();
await page.goto(`/event-admin/mobile/events/${createdSlug}/members`);
await expect(page.getByText(/Event-Mitglieder|Event members/i)).toBeVisible();
await page.goto(`/event-admin/events/${createdSlug}/tasks`);
await expect(page.getByRole('heading', { name: /Event-Tasks/i })).toBeVisible();
await expect(page.getByText(/Noch keine Tasks zugewiesen/i)).toBeVisible();
await page.goto(`/event-admin/mobile/events/${createdSlug}/tasks`);
await expect(page.getByText(/Aufgaben & Missionen|Tasks & Checklists/i)).toBeVisible();
});
test('task library allows creating custom tasks', async ({ page }) => {
await page.goto('/event-admin/tasks');
await page.goto('/event-admin/mobile/tasks');
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: /Task Bibliothek/i })).toBeVisible();
await expect(page.getByText(/Tasks|Aufgaben/i)).toBeVisible();
const taskTitle = `Playwright Task ${Date.now()}`;
await page.getByRole('button', { name: /^Neu$/i }).click();
await page.getByLabel(/Titel/i).fill(taskTitle);
await page.getByLabel(/Beschreibung/i).fill('Automatisierter Testfall');
await page.getByRole('button', { name: /^Speichern$/i }).click();
const addTaskButton = page.getByRole('button', { name: /Aufgabe hinzufügen|Add task/i }).first();
test.skip((await addTaskButton.count()) === 0, 'No active event available to add tasks.');
await addTaskButton.click();
await page.getByPlaceholder(/Gruppenfoto|Group photo/i).fill(taskTitle);
await page.getByPlaceholder(/Optionale Hinweise|Optional/i).fill('Automatisierter Testfall');
await page.getByRole('button', { name: /Aufgabe speichern|Save task/i }).click();
await expect(page.getByText(taskTitle)).toBeVisible({ timeout: 10_000 });
await page.goto('/event-admin/task-collections');
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: /Aufgabenvorlagen/i })).toBeVisible();
});
test('supporting sections (emotions, billing, settings) load successfully', async ({ page }) => {
await page.goto('/event-admin/emotions');
test('supporting sections (billing, settings, profile) load successfully', async ({ page }) => {
await page.goto('/event-admin/mobile/billing');
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: /Emotionen/i })).toBeVisible();
await expect(page.getByText(/Pakete|Billing|Abrechnung/i)).toBeVisible();
await page.goto('/event-admin/billing');
await page.goto('/event-admin/mobile/settings');
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: /Pakete & Abrechnung/i })).toBeVisible();
await expect(page.getByText(/Einstellungen|Settings/i)).toBeVisible();
await page.goto('/event-admin/settings');
await page.goto('/event-admin/mobile/profile');
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: /Einstellungen/i })).toBeVisible();
await expect(page.getByText(/Profil|Profile/i)).toBeVisible();
});
test('wedding event workflow assigns tasks and exposes join token', async ({ page, fetchJoinToken }) => {
const eventName = `Playwright Hochzeit ${Date.now()}`;
const eventDate = futureDate(21);
await page.goto('/event-admin/events/new');
await page.goto('/event-admin/mobile/events/new');
await page.waitForLoadState('networkidle');
await page.getByLabel(/Eventname/i).fill(eventName);
await page.getByLabel(/Datum/i).fill(eventDate);
await page.getByPlaceholder(/Sommerfest|Summer Party/i).fill(eventName);
await page.locator('input[type="datetime-local"]').fill(`${eventDate}T12:00`);
const eventTypeCombo = page.getByRole('combobox', { name: /Event-Typ/i });
await eventTypeCombo.click();
const weddingOption = page.getByRole('option', { name: /Hochzeit|Wedding/i }).first();
await expect(weddingOption).toBeVisible();
await weddingOption.click();
const eventTypeCombo = page.locator('select').first();
await eventTypeCombo.selectOption({ index: 1 });
await page.getByRole('button', { name: /^Speichern/i }).click();
await page.waitForURL(/\/event-admin\/events\/[a-z0-9-]+$/i, { timeout: 20_000 });
const createdSlug = page.url().split('/').pop() ?? '';
await page.getByRole('button', { name: /Event erstellen|Create event/i }).click();
await page.waitForURL(/\/event-admin\/mobile\/events\/[a-z0-9-]+$/i, { timeout: 20_000 });
const createdSlug = new URL(page.url()).pathname.split('/').pop() ?? '';
await expect(page.getByText(/Hochzeit|Wedding/i)).toBeVisible();
await page.goto(`/event-admin/events/${createdSlug}/tasks`);
await expect(page.getByRole('heading', { name: /Event-Tasks/i })).toBeVisible();
await page.goto(`/event-admin/mobile/events/${createdSlug}/tasks`);
await expect(page.getByText(/Aufgaben & Missionen|Tasks & Checklists/i)).toBeVisible();
const librarySection = page
.locator('section')

View File

@@ -10,9 +10,9 @@ import { test, expectFixture as expect } from '../helpers/test-fixtures';
*/
test.describe('Tenant Onboarding Welcome Flow', () => {
test('redirects unauthenticated users to login', async ({ page }) => {
await page.goto('/event-admin/welcome');
await page.goto('/event-admin/mobile/welcome');
await expect(page).toHaveURL(/\/event-admin\/login/);
await expect(page.getByText('Bitte warten', { exact: false })).toBeVisible();
await expect(page.getByText(/Team Login|Fotospiel Event Admin|Login/i)).toBeVisible();
});
test('tenant admin can progress through welcome, packages, summary, and setup', async ({
@@ -28,15 +28,15 @@ test.describe('Tenant Onboarding Welcome Flow', () => {
await signInTenantAdmin();
// If guard redirects to dashboard, hop to welcome manually.
if (!page.url().includes('/event-admin/welcome')) {
await page.goto('/event-admin/welcome');
if (!page.url().includes('/event-admin/mobile/welcome')) {
await page.goto('/event-admin/mobile/welcome');
}
await expect(page.getByRole('heading', { name: /Willkommen im Event-Erlebnisstudio/i })).toBeVisible();
// Open package selection via CTA.
await page.getByRole('button', { name: /Pakete entdecken/i }).click();
await expect(page).toHaveURL(/\/event-admin\/welcome\/packages/);
await expect(page).toHaveURL(/\/event-admin\/mobile\/welcome\/packages/);
await expect(page.getByRole('heading', { name: /Wähle dein Eventpaket/i })).toBeVisible();
// Choose the first available package and ensure we land on the summary step.
@@ -44,7 +44,7 @@ test.describe('Tenant Onboarding Welcome Flow', () => {
await choosePackageButton.waitFor({ state: 'visible', timeout: 10_000 });
await choosePackageButton.click();
await expect(page).toHaveURL(/\/event-admin\/welcome\/summary/);
await expect(page).toHaveURL(/\/event-admin\/mobile\/welcome\/summary/);
await expect(page.getByRole('heading', { name: /Bestellübersicht/i })).toBeVisible();
// Validate Paddle payment section.
@@ -52,7 +52,7 @@ test.describe('Tenant Onboarding Welcome Flow', () => {
// Continue to the setup step without completing a purchase.
await page.getByRole('button', { name: /Weiter zum Setup/i }).click();
await expect(page).toHaveURL(/\/event-admin\/welcome\/event/);
await expect(page).toHaveURL(/\/event-admin\/mobile\/welcome\/event/);
await expect(page.getByRole('heading', { name: /Bereite dein erstes Event vor/i })).toBeVisible();
});
});