import { test, expect, Page } from '@playwright/test'; import path from 'path'; const DEMO_ACCOUNTS = { admin: { email: 'admin@example.com', password: 'demo123' }, organizer: { email: 'organizer@example.com', password: 'demo123' }, staff: { email: 'staff@example.com', password: 'demo123' }, }; async function takeScreenshot(page: Page, name: string) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const fileName = `auth_${name}_${timestamp}.png`; await page.screenshot({ path: path.join('screenshots', fileName), fullPage: true }); return fileName; } async function clearAuthStorage(page: Page) { await page.evaluate(() => { localStorage.removeItem('bct_auth_user'); localStorage.removeItem('bct_auth_remember'); }); } test.describe('Authentication Flows (Realistic)', () => { test.beforeEach(async ({ page }) => { // Clear any existing auth state await clearAuthStorage(page); await page.goto('/'); }); test('should redirect to login when accessing protected route', async ({ page }) => { await page.goto('/dashboard'); // Should redirect to login page await expect(page).toHaveURL('/login'); await expect(page.locator('h1')).toContainText('Black Canyon Tickets'); await expect(page.locator('text=Sign in to your account')).toBeVisible(); await takeScreenshot(page, 'protected-route-redirect'); }); test('should login successfully with valid admin credentials', async ({ page }) => { await page.goto('/login'); await takeScreenshot(page, 'login-page-initial'); // Fill in admin credentials using form elements await page.fill('input[name="email"]', DEMO_ACCOUNTS.admin.email); await page.fill('input[name="password"]', DEMO_ACCOUNTS.admin.password); await takeScreenshot(page, 'login-form-filled'); // Submit login form await page.click('button[type="submit"]'); // Wait for loading state await expect(page.locator('text=Signing in...')).toBeVisible(); await takeScreenshot(page, 'login-loading-state'); // Should redirect to dashboard await expect(page).toHaveURL('/', { timeout: 10000 }); // Verify user is logged in by checking for user name in sidebar await expect(page.locator('text=Sarah Admin')).toBeVisible(); await takeScreenshot(page, 'dashboard-logged-in-admin'); }); test('should login successfully with organizer credentials', async ({ page }) => { await page.goto('/login'); await page.fill('input[name="email"]', DEMO_ACCOUNTS.organizer.email); await page.fill('input[name="password"]', DEMO_ACCOUNTS.organizer.password); await page.click('button[type="submit"]'); await expect(page).toHaveURL('/', { timeout: 10000 }); await expect(page.locator('text=John Organizer')).toBeVisible(); await takeScreenshot(page, 'dashboard-logged-in-organizer'); }); test('should login successfully with staff credentials', async ({ page }) => { await page.goto('/login'); await page.fill('input[name="email"]', DEMO_ACCOUNTS.staff.email); await page.fill('input[name="password"]', DEMO_ACCOUNTS.staff.password); await page.click('button[type="submit"]'); await expect(page).toHaveURL('/', { timeout: 10000 }); await expect(page.locator('text=Emma Staff')).toBeVisible(); await takeScreenshot(page, 'dashboard-logged-in-staff'); }); test('should show error for invalid credentials', async ({ page }) => { await page.goto('/login'); await page.fill('input[name="email"]', 'invalid@example.com'); await page.fill('input[name="password"]', 'wrongpassword'); await page.click('button[type="submit"]'); // Should show error message await expect(page.locator('[role="alert"]')).toBeVisible(); await expect(page.locator('text=Invalid email or password')).toBeVisible(); // Should remain on login page await expect(page).toHaveURL('/login'); await takeScreenshot(page, 'login-error-state'); }); test('should toggle password visibility', async ({ page }) => { await page.goto('/login'); const passwordInput = page.locator('input[name="password"]'); const toggleButton = page.locator('button[type="button"]').filter({ hasText: '' }); // Eye icon button // Password should be hidden initially await expect(passwordInput).toHaveAttribute('type', 'password'); await page.fill('input[name="password"]', 'testpassword'); await takeScreenshot(page, 'password-hidden'); // Click toggle to show password await toggleButton.click(); await expect(passwordInput).toHaveAttribute('type', 'text'); await takeScreenshot(page, 'password-visible'); // Click toggle to hide password again await toggleButton.click(); await expect(passwordInput).toHaveAttribute('type', 'password'); }); test('should remember login when remember me is checked', async ({ page }) => { await page.goto('/login'); await page.fill('input[name="email"]', DEMO_ACCOUNTS.admin.email); await page.fill('input[name="password"]', DEMO_ACCOUNTS.admin.password); // Check remember me await page.check('input[name="rememberMe"]'); await takeScreenshot(page, 'remember-me-checked'); await page.click('button[type="submit"]'); await expect(page).toHaveURL('/', { timeout: 10000 }); // Verify localStorage has auth data const authData = await page.evaluate(() => localStorage.getItem('bct_auth_user')); const rememberMe = await page.evaluate(() => localStorage.getItem('bct_auth_remember')); expect(authData).toBeTruthy(); expect(rememberMe).toBe('true'); // Refresh page - should stay logged in await page.reload(); await expect(page).toHaveURL('/'); await expect(page.locator('text=Sarah Admin')).toBeVisible(); await takeScreenshot(page, 'persistent-login-after-refresh'); }); test('should use demo account buttons', async ({ page }) => { await page.goto('/login'); // Click admin demo account button await page.click('text=Sarah Admin'); // Form should be filled await expect(page.locator('input[name="email"]')).toHaveValue(DEMO_ACCOUNTS.admin.email); await expect(page.locator('input[name="password"]')).toHaveValue('demo123'); await takeScreenshot(page, 'demo-account-filled'); // Submit and verify login await page.click('button[type="submit"]'); await expect(page).toHaveURL('/', { timeout: 10000 }); await expect(page.locator('text=Sarah Admin')).toBeVisible(); await takeScreenshot(page, 'demo-account-login-success'); }); test('should validate empty form submission', async ({ page }) => { await page.goto('/login'); // Try to submit empty form await page.click('button[type="submit"]'); // Should show validation errors await expect(page.locator('text=Email is required')).toBeVisible(); await takeScreenshot(page, 'form-validation-errors'); }); test('should validate password requirement', async ({ page }) => { await page.goto('/login'); // Fill email but not password await page.fill('input[name="email"]', DEMO_ACCOUNTS.admin.email); await page.click('button[type="submit"]'); await expect(page.locator('text=Password is required')).toBeVisible(); await takeScreenshot(page, 'password-required-error'); }); test('should handle redirect after login', async ({ page }) => { // Try to access events page directly await page.goto('/events'); // Should redirect to login await expect(page).toHaveURL('/login'); // Login await page.fill('input[name="email"]', DEMO_ACCOUNTS.admin.email); await page.fill('input[name="password"]', DEMO_ACCOUNTS.admin.password); await page.click('button[type="submit"]'); // Should redirect back to events page (or dashboard for now) await expect(page).toHaveURL(/\/(events|dashboard|$)/, { timeout: 10000 }); await takeScreenshot(page, 'redirect-after-login'); }); test('should show loading screen during initial auth check', async ({ page }) => { // Set up a user in localStorage to trigger auth loading await page.evaluate(() => { localStorage.setItem('bct_auth_user', JSON.stringify({ id: 'test', email: 'admin@example.com', name: 'Test User' })); localStorage.setItem('bct_auth_remember', 'true'); }); await page.goto('/'); // Should briefly show loading state const loading = page.locator('text=Loading...'); if (await loading.isVisible()) { await takeScreenshot(page, 'auth-loading-screen'); } // Should eventually show dashboard or redirect to login await page.waitForTimeout(3000); await takeScreenshot(page, 'auth-check-complete'); }); test('should handle demo account role display', async ({ page }) => { await page.goto('/login'); // Verify all demo accounts are shown with correct roles await expect(page.locator('text=Sarah Admin')).toBeVisible(); await expect(page.locator('text=admin').first()).toBeVisible(); await expect(page.locator('text=John Organizer')).toBeVisible(); await expect(page.locator('text=organizer')).toBeVisible(); await expect(page.locator('text=Emma Staff')).toBeVisible(); await expect(page.locator('text=staff')).toBeVisible(); await takeScreenshot(page, 'demo-accounts-display'); }); });