import { defineConfig, devices } from '@playwright/test' export default defineConfig({ testDir: './tests', fullyParallel: false, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 1, workers: 1, reporter: [ ['html', { outputFolder: 'playwright-report' }], ['list'], ['json', { outputFile: 'playwright-results.json' }], ], use: { baseURL: process.env.BASE_URL || 'http://127.0.0.1:8000', trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'retain-on-failure', actionTimeout: 15_000, navigationTimeout: 30_000, ignoreHTTPSErrors: true, }, /* ── 全局测试钩子 ─────────────────────────────────────────────────────────── */ webServer: { command: 'echo "API server must be started manually: uvicorn gateway.api:app --port 8000"', port: 8000, reuseExistingServer: true, timeout: 5_000, }, /* ── 浏览器项目(指纹定制)────────────────────────────────────────────────────── */ projects: [ // ── Chromium(主力,多指纹参数)──────────────────────────────────────────── { name: 'Chromium', use: { ...devices['Desktop Chrome'], viewport: { width: 1920, height: 1080 }, permissions: ['notifications'], launchOptions: { args: [ // 反自动化检测 '--disable-blink-features=AutomationControlled', '--disable-blink-features=ChromeLoadTimes', '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-background-networking', '--disable-default-apps', '--disable-extensions', '--disable-sync', '--disable-translate', '--hide-scrollbars', '--metrics-recording-only', '--mute-audio', '--no-first-run', // 随机化 WebGL 指纹 '--enable-webgl', '--ignore-gpu-blocklist', // 禁用 Headless 特征 '--disable-gpu', ], }, }, }, // ── Firefox ───────────────────────────────────────────────────────────── { name: 'Firefox', use: { ...devices['Desktop Firefox'], launchOptions: { prefs: { 'media.navigator.streams.fake': true, 'media.navigator.permission.disabled': true, 'webgl.disabled': false, }, }, }, }, // ── 移动端模拟(iPhone 14 Pro)───────────────────────────────────────── { name: 'iPhone14Pro', use: { ...devices['iPhone 14 Pro'] }, }, // ── 平板模拟(iPad)──────────────────────────────────────────────────── { name: 'iPad', use: { ...devices['iPad (gen 7)'] }, }, ], })