/** * Global setup for Playwright tests * Creates test users and saves authentication state */ import { chromium, type FullConfig } from '@playwright/test'; import { prisma } from '@/lib/prisma'; import { cleanupAllTestData } from '@/__tests__/test-utils'; import path from 'path'; import fs from 'fs'; // Load .env file first, then .env.development (which will override .env) const envPath = path.resolve(process.cwd(), '.env'); const envDevPath = path.resolve(process.cwd(), '.env.development'); // Load base .env file if (fs.existsSync(envPath)) { require('dotenv').config({ path: envPath }); } // Load .env.development file (will override .env settings) if (fs.existsSync(envDevPath)) { require('dotenv').config({ path: envDevPath, override: true }); } const authFile = 'playwright/.auth/user.json'; const adminAuthFile = 'playwright/.auth/admin.json'; // Check if we're using the dev database function isDevDatabase(): boolean { const dbUrl = process.env.DATABASE_URL || ''; return dbUrl.includes('euchre_camp_dev'); } function isProductionDatabase(): boolean { const dbUrl = process.env.DATABASE_URL || ''; return dbUrl.includes('euchre_camp') && !dbUrl.includes('_dev'); } // Strict check - fail if using production database if (isProductionDatabase()) { console.error(''); console.error('='.repeat(80)); console.error('CRITICAL ERROR: Tests are attempting to run against PRODUCTION database!'); console.error('='.repeat(80)); console.error(''); console.error('Current DATABASE_URL:', process.env.DATABASE_URL); console.error(''); console.error('Tests MUST run against the development database (euchre_camp_dev)'); console.error(''); console.error('To fix this:'); console.error(' 1. Run: npm run test:acceptance'); console.error(' 2. Or set: DATABASE_URL environment variable to dev database URL'); console.error(' 3. Or load .env.development: source .env.development && npm run test:acceptance'); console.error(''); console.error('Aborting test execution to prevent data corruption.'); console.error(''); process.exit(1); } if (!isDevDatabase()) { console.warn('⚠️ WARNING: DATABASE_URL does not contain euchre_camp_dev'); console.warn(' Current DATABASE_URL:', process.env.DATABASE_URL); } export default async function globalSetup(config: FullConfig) { const baseURL = config.projects[0]?.use?.baseURL || 'http://localhost:3000'; const browser = await chromium.launch(); const context = await browser.newContext(); const page = await context.newPage(); // Log all responses for debugging page.on('response', response => { if (response.url().includes('/api/auth')) { console.log('API Response:', response.status(), response.url()); } }); // Generate unique test credentials const timestamp = Date.now(); const testEmail = `setup-user-${timestamp}@example.com`; const testPassword = 'TestPassword1234!'; const testName = 'Setup User'; try { // Navigate to registration page console.log('Navigating to registration page...'); await page.goto(`${baseURL}/auth/register`); // Fill in registration form await page.fill('input[name="name"]', testName); await page.fill('input[name="email"]', testEmail); await page.fill('input[name="password"]', testPassword); // Submit the form console.log('Submitting registration form...'); await page.click('button[type="submit"]'); // Wait for the sign-up API call to complete console.log('Waiting for sign-up API call...'); try { await page.waitForResponse(response => response.url().includes('/api/auth/sign-up/email') && response.status() === 200, { timeout: 10000 } ); console.log('Sign-up API call successful'); } catch { console.log('Sign-up API call failed or timed out'); } // Wait a bit for session to be established console.log('Waiting for session establishment...'); await page.waitForTimeout(2000); // Check if we're already authenticated const currentUrl = page.url(); console.log('Current URL after registration:', currentUrl); // Save the authentication state await context.storageState({ path: authFile }); console.log(`Created and authenticated test user: ${testEmail}`); // Now create admin user const adminTimestamp = timestamp + 1; const adminEmail = `setup-admin-${adminTimestamp}@example.com`; const adminPassword = 'AdminPassword123!'; const adminName = 'Setup Admin'; // Navigate to registration page again console.log('Navigating to registration page for admin...'); await page.goto(`${baseURL}/auth/register`); // Fill in registration form await page.fill('input[name="name"]', adminName); await page.fill('input[name="email"]', adminEmail); await page.fill('input[name="password"]', adminPassword); // Submit the form console.log('Submitting admin registration form...'); await page.click('button[type="submit"]'); // Wait for the sign-up API call to complete console.log('Waiting for admin sign-up API call...'); try { await page.waitForResponse(response => response.url().includes('/api/auth/sign-up/email') && response.status() === 200, { timeout: 10000 } ); console.log('Admin sign-up API call successful'); } catch { console.log('Admin sign-up API call failed or timed out'); } // Wait a bit for session to be established console.log('Waiting for admin session establishment...'); await page.waitForTimeout(2000); // Update user role to admin via database const user = await prisma.user.findUnique({ where: { email: adminEmail } }); if (user) { await prisma.user.update({ where: { id: user.id }, data: { role: 'club_admin' } }); console.log('Updated user role to club_admin'); } // Navigate to admin page to refresh session console.log('Navigating to admin page for admin user...'); await page.goto(`${baseURL}/admin`); await page.waitForLoadState('networkidle'); console.log('Admin page loaded:', page.url()); // Wait a bit to ensure session is refreshed await page.waitForTimeout(2000); // Refresh the page to force session reload await page.reload(); await page.waitForLoadState('networkidle'); console.log('Page reloaded'); // Save the authentication state await context.storageState({ path: adminAuthFile }); console.log(`Created and authenticated admin user: ${adminEmail}`); } catch (error) { console.error('Global setup error:', error); throw error; } finally { await browser.close(); } // Return teardown function return async () => { console.log('\n=== Global Teardown ==='); // Clean up all test data try { await cleanupAllTestData(); } catch (error) { console.error('Error cleaning up test data:', error); } finally { await prisma.$disconnect(); } }; }