import { defineConfig, devices } from '@playwright/test' import fs from 'node:fs' import path from 'node:path' function loadLocalEnvironment() { const filename = process.env.E2E_ENV_FILE?.trim() || path.resolve('.env') if (!fs.existsSync(filename)) return for (const line of fs.readFileSync(filename, 'utf8').split(/\r?\n/)) { const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/) if (!match || process.env[match[1]!]) continue const raw = match[2]! process.env[match[1]!] = raw.length >= 2 && ((raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'"))) ? raw.slice(1, -1) : raw } } loadLocalEnvironment() const safeRunId = (process.env.APE2E_RUN_ID || 'manual') .replace(/[^A-Za-z0-9._-]+/g, '-') .slice(0, 80) || 'manual' const runDirectory = path.resolve('artifacts', 'runs', safeRunId) const baseURL = (process.env.BASE_URL ?? 'http://127.0.0.1:8003').replace(/\/$/, '') const browserChannel = process.env.E2E_BROWSER_CHANNEL?.trim() export default defineConfig({ testDir: './tests', outputDir: path.join(runDirectory, 'test-results'), fullyParallel: false, workers: 1, retries: process.env.CI ? 1 : 0, timeout: 90_000, expect: { timeout: 12_000 }, reporter: [ ['list'], ['html', { outputFolder: path.join(runDirectory, 'html-report'), open: 'never' }], ['json', { outputFile: path.join(runDirectory, 'results.json') }], ], use: { baseURL, locale: 'zh-CN', timezoneId: 'Asia/Shanghai', actionTimeout: 12_000, navigationTimeout: 30_000, screenshot: 'off', // 测试使用真实密码、API Key 与一次性密钥;不生成可能包含输入快照的 trace/video。 // 成功与失败场景都由 fixtures.ts 生成经过遮罩控制的截图。 trace: 'off', video: 'off', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'], ...(browserChannel ? { channel: browserChannel } : {}), }, }], })