import { execFileSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; import fs from 'node:fs'; import { chromium } from '@playwright/test'; function parseDotEnvFile(envPath) { if (!fs.existsSync(envPath)) { return {}; } const out = {}; const lines = fs.readFileSync(envPath, 'utf8').split(/\r?\n/); for (const raw of lines) { const line = raw.trim(); if (!line || line.startsWith('#')) { continue; } const idx = line.indexOf('='); if (idx <= 0) { continue; } const key = line.slice(0, idx).trim(); let value = line.slice(idx + 1).trim(); if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { value = value.slice(1, -1); } out[key] = value; } return out; } export default async function globalSetup(config) { const here = path.dirname(fileURLToPath(import.meta.url)); const root = path.resolve(here, '..', '..'); const dotEnv = parseDotEnvFile(path.join(root, 'credentials', '.env')); const remoteEnabled = String(process.env.E2E_REMOTE_ADMIN || dotEnv.E2E_REMOTE_ADMIN || '') === '1'; const baseURL = String( remoteEnabled ? ( process.env.E2E_BASE_URL || process.env.E2E_REMOTE_ADMIN_BASE_URL || dotEnv.E2E_REMOTE_ADMIN_BASE_URL || config?.projects?.[0]?.use?.baseURL || config?.use?.baseURL || 'http://127.0.0.1:8080' ) : ( config?.projects?.[0]?.use?.baseURL || config?.use?.baseURL || process.env.E2E_BASE_URL || 'http://127.0.0.1:8080' ) ); let fixturePort = process.env.FIXTURE_PORT || ''; if (!fixturePort) { try { const parsed = new URL(baseURL); fixturePort = parsed.port || (parsed.protocol === 'https:' ? '443' : '80'); } catch { fixturePort = '8080'; } } if (remoteEnabled) { const user = process.env.E2E_REMOTE_ADMIN_USER || dotEnv.E2E_REMOTE_ADMIN_USER || ''; const pass = process.env.E2E_REMOTE_ADMIN_PASS || dotEnv.E2E_REMOTE_ADMIN_PASS || ''; if (!user || !pass) { throw new Error('E2E remote admin mode requires E2E_REMOTE_ADMIN_USER and E2E_REMOTE_ADMIN_PASS.'); } const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ baseURL }); const page = await context.newPage(); await page.goto('/wp-login.php', { waitUntil: 'domcontentloaded' }); await page.fill('#user_login', user); await page.fill('#user_pass', pass); await Promise.all([ page.waitForNavigation({ waitUntil: 'domcontentloaded' }), page.click('#wp-submit') ]); const currentUrl = page.url(); if (currentUrl.includes('/wp-login.php')) { throw new Error('Remote WordPress login failed. Check E2E_REMOTE_ADMIN credentials.'); } const authPath = path.join(root, 'working', 'e2e-remote-auth.json'); fs.mkdirSync(path.dirname(authPath), { recursive: true }); await context.storageState({ path: authPath }); await context.close(); await browser.close(); process.env.PLAYWRIGHT_AUTH_STATE = authPath; return; } const tunnelScript = path.join(root, 'scripts', 'mysql_tunnel.sh'); const script = path.join(root, 'scripts', 'run_fixture_server.sh'); execFileSync(tunnelScript, ['start'], { cwd: root, stdio: 'inherit', env: { ...process.env } }); execFileSync(script, ['start'], { cwd: root, stdio: 'inherit', env: { ...process.env, FIXTURE_PORT: String(fixturePort) } }); }