import { test, expect } from '@playwright/test'; /** * EventDetailPage E2E Tests * * Tests for the event detail page header actions: * - Add Ticket Type button functionality * - Publish button behavior (disabled when already published) * - Open Scanner button functionality * - Payment warning chip display */ test.describe('EventDetailPage', () => { test.beforeEach(async ({ page }) => { // Navigate to login and authenticate as organizer await page.goto('/login'); await page.waitForLoadState('networkidle'); // Login with organizer credentials (has unpublished events) await page.fill('input[name="email"]', 'organizer@example.com'); await page.fill('input[name="password"]', 'password123'); await page.click('button[type="submit"]'); // Wait for redirect to dashboard await page.waitForURL('/dashboard'); await page.waitForLoadState('networkidle'); // Navigate to events page await page.goto('/events'); await page.waitForLoadState('networkidle'); // Click on first event to go to detail page const firstEventLink = page.locator('[data-testid="event-card"]').first(); await firstEventLink.click(); // Wait for event detail page to load await page.waitForSelector('[data-testid="event-detail-page"]'); }); test('renders action buttons with correct data-testids', async ({ page }) => { // Verify all required buttons are present with correct test ids await expect(page.locator('[data-testid="addTicketTypeBtn"]')).toBeVisible(); await expect(page.locator('[data-testid="publishBtn"]')).toBeVisible(); await expect(page.locator('[data-testid="openScannerBtn"]')).toBeVisible(); }); test('Add Ticket Type button opens modal', async ({ page }) => { // Click the add ticket type button await page.click('[data-testid="addTicketTypeBtn"]'); // Verify the modal opens await expect(page.locator('.modal')).toBeVisible(); await expect(page.getByText('Create Ticket Type')).toBeVisible(); // Close modal await page.keyboard.press('Escape'); }); test('Publish button shows correct state and opens modal', async ({ page }) => { const publishBtn = page.locator('[data-testid="publishBtn"]'); // For draft events, button should be enabled and say "Publish" const eventStatus = await page.locator('[data-testid="event-status-badge"]').textContent(); if (eventStatus?.includes('draft')) { await expect(publishBtn).toBeEnabled(); await expect(publishBtn).toContainText('Publish'); // Click to open publish modal await publishBtn.click(); await expect(page.getByText('Publish Event')).toBeVisible(); // Close modal await page.keyboard.press('Escape'); } else if (eventStatus?.includes('published')) { // For published events, button should be disabled and say "Published" await expect(publishBtn).toBeDisabled(); await expect(publishBtn).toContainText('Published'); } }); test('Open Scanner button navigates to scanner with eventId', async ({ page }) => { // Get current URL to extract eventId const currentUrl = page.url(); const eventIdMatch = currentUrl.match(/\/events\/([^\/]+)/); const eventId = eventIdMatch?.[1]; expect(eventId).toBeTruthy(); // Click the scanner button await page.click('[data-testid="openScannerBtn"]'); // Verify navigation to scanner with eventId query parameter await page.waitForURL(`/scan?eventId=${eventId}`); // Verify we're on the scanner page await expect(page.locator('text=Scanner')).toBeVisible(); }); test('displays payment banner for organization without connected payment', async ({ page }) => { // Check if payment banner is visible (depends on mock user data) const paymentBanner = page.locator('[data-testid="payment-banner"]'); // The organizer mock user has payment.connected: false, so banner should show await expect(paymentBanner).toBeVisible(); // Verify banner contains link to payment settings const paymentLink = paymentBanner.locator('a'); await expect(paymentLink).toContainText(/connect|payment/i); }); test('ticket type section shows add button when user can edit', async ({ page }) => { // Verify the ticket types section has an add button const ticketTypesCard = page.locator('text=Ticket Types').locator('..'); await expect(ticketTypesCard.locator('[data-testid="addTicketTypeBtn"]')).toBeVisible(); }); test('event stats display correctly', async ({ page }) => { // Verify the three stat cards are displayed await expect(page.getByText('Tickets Sold')).toBeVisible(); await expect(page.getByText('Revenue')).toBeVisible(); await expect(page.getByText('Ticket Types')).toBeVisible(); // Verify numeric values are displayed const ticketsSoldValue = page.locator('text=Tickets Sold').locator('..').locator('.text-2xl'); const revenueValue = page.locator('text=Revenue').locator('..').locator('.text-2xl'); const ticketTypesValue = page.locator('text=Ticket Types').locator('..').locator('.text-2xl'); await expect(ticketsSoldValue).toBeVisible(); await expect(revenueValue).toBeVisible(); await expect(ticketTypesValue).toBeVisible(); }); }); test.describe('EventDetailPage - Published Event', () => { test.beforeEach(async ({ page }) => { // Login as admin (has published events) await page.goto('/login'); await page.fill('input[name="email"]', 'admin@example.com'); await page.fill('input[name="password"]', 'password123'); await page.click('button[type="submit"]'); await page.waitForURL('/dashboard'); await page.goto('/events'); await page.waitForLoadState('networkidle'); // Look for a published event or navigate to first event await page.locator('[data-testid="event-card"]').first().click(); await page.waitForSelector('[data-testid="event-detail-page"]'); }); test('publish button is disabled for published events', async ({ page }) => { // Check if this event is published const statusBadge = page.locator('[data-testid="event-status-badge"]'); const status = await statusBadge.textContent(); if (status?.includes('published')) { const publishBtn = page.locator('[data-testid="publishBtn"]'); await expect(publishBtn).toBeDisabled(); await expect(publishBtn).toContainText('Published'); } }); });