import { chromium, FullConfig } from '@playwright/test'; import { TEST_CONFIG, TEST_USERS } from './utils/test-helpers'; // Load test user credentials from environment or use defaults const getTestUser = () => { const email = process.env.TEST_EMAIL || TEST_USERS.default.email; const password = process.env.TEST_PASSWORD || TEST_USERS.default.password; return { email, password }; }; /** * Global Setup for Playwright E2E Tests * * This setup runs ONCE before all tests to: * 1. Log in as a test user * 2. Save the authenticated session state to storageState.json * 3. All subsequent tests will use this saved state (no need to login again) * * This eliminates: * - Rate limiting issues (only 1 login instead of N logins) * - Test execution time (no login overhead per test) * - Flaky authentication failures */ async function globalSetup(config: FullConfig) { console.log('🔧 [GLOBAL SETUP] Starting global setup...'); // Use the first project's browser (usually chromium) const project = config.projects[0]; const browser = await chromium.launch({ headless: true, }); const context = await browser.newContext(); const page = await context.newPage(); try { // Navigate to login page console.log('🔧 [GLOBAL SETUP] Navigating to login page...'); await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`, { waitUntil: 'networkidle', }); // Wait for login form to be visible await page.waitForSelector('input[type="email"], input[name="email"]', { timeout: 10000, }); // Fill login form console.log('🔧 [GLOBAL SETUP] Filling login form...'); const emailInput = page.locator('input[type="email"], input[name="email"]').first(); const passwordInput = page.locator('input[type="password"], input[name="password"]').first(); const testUser = getTestUser(); console.log(`🔧 [GLOBAL SETUP] Using test user: ${testUser.email}`); await emailInput.fill(testUser.email); await passwordInput.fill(testUser.password); // Submit form console.log('🔧 [GLOBAL SETUP] Submitting login form...'); const form = page.locator('form').first(); await form.evaluate((form) => (form as HTMLFormElement).requestSubmit()); // Wait for navigation after login (dashboard or home) console.log('🔧 [GLOBAL SETUP] Waiting for login to complete...'); await page.waitForURL( (url) => url.pathname === '/dashboard' || url.pathname === '/', { timeout: 20000 } ); // Wait for auth state to be persisted await page.waitForTimeout(2000); // Verify authentication by checking for auth-storage in localStorage const authStorage = await page.evaluate(() => { return localStorage.getItem('auth-storage'); }); if (!authStorage) { throw new Error('Authentication failed: auth-storage not found in localStorage'); } const authData = JSON.parse(authStorage); if (!authData.state?.isAuthenticated) { throw new Error('Authentication failed: isAuthenticated is false'); } console.log('✅ [GLOBAL SETUP] Login successful!'); // Verify token is stored const accessToken = await page.evaluate(() => { return localStorage.getItem('veza_access_token'); }); if (!accessToken) { console.warn('⚠️ [GLOBAL SETUP] Access token not found in localStorage (may be in memory)'); } else { console.log('✅ [GLOBAL SETUP] Access token stored in localStorage'); } // Save the authenticated state to storageState.json const storageStatePath = config.projects[0]?.use?.storageState as string || 'e2e/.auth/user.json'; console.log(`💾 [GLOBAL SETUP] Saving authenticated state to: ${storageStatePath}`); await context.storageState({ path: storageStatePath }); console.log('✅ [GLOBAL SETUP] Global setup completed successfully!'); } catch (error) { console.error('❌ [GLOBAL SETUP] Global setup failed:', error); throw error; } finally { await browser.close(); } } export default globalSetup;