// ============================================================ // Playwright E2E 冒烟配置(moduleId: web-e2e-config, 可重生 ✅) // 矩阵 118:完整前端 E2E。 // 模式: // preview(默认):npm run build 后起 vite preview(生产构建,行为最接近发布包; // dev 模式 StrictMode 结果捕获缺陷已修复(round-42)并验证,见 docs/development/e2e.md) // dev:起 vite dev(本地调试用;复用已运行 5173 时配合 E2E_REUSE=1) // 默认值仍是 127.0.0.1:8003,但 fail-closed;本地/CI 都应通过 E2E_API_TARGET 指向隔离后端。 // ============================================================ import { defineConfig, devices } from '@playwright/test'; import os from 'node:os'; import path from 'node:path'; const mode = process.env.E2E_MODE || 'preview'; const frontendPort = process.env.E2E_FRONTEND_PORT || (mode === 'preview' ? '43117' : '5173'); const baseURL = process.env.E2E_BASE_URL || `http://localhost:${frontendPort}`; // 未显式配置时会命中现场 8003,并在下方安全检查中拒绝加载 const apiTarget = process.env.E2E_API_TARGET || 'http://127.0.0.1:8003'; // 测试产物(截图/追踪)写到系统临时目录,避免污染仓库工作树 const outputDir = process.env.E2E_OUTPUT_DIR || path.join(os.tmpdir(), 'aps-e2e-artifacts'); // 测试卫生(C-P0):核心路径会在目标后端创建真实会话,因此现场 8003 必须 fail-closed。 // 唯一推荐路径是按 docs/development/e2e.md 启动隔离后端(默认端口 8100)。 const targetUrl = new URL(apiTarget); const usingLiveBackend = ['127.0.0.1', 'localhost'].includes(targetUrl.hostname) && targetUrl.port === '8003'; const allowLiveBackend = process.env.E2E_ALLOW_LIVE_BACKEND === '1'; if (usingLiveBackend && !allowLiveBackend) { throw new Error( '[e2e] 已拒绝连接现场后端 127.0.0.1:8003:核心 E2E 会创建真实会话。' + '请按 docs/development/e2e.md「数据隔离」启动 8100 隔离后端;' + '仅在明确接受现场数据写入时设置 E2E_ALLOW_LIVE_BACKEND=1。', ); } if (usingLiveBackend && allowLiveBackend) { // eslint-disable-next-line no-console console.warn('[e2e] 已显式允许现场 8003:本次运行会创建真实会话。'); } const command = mode === 'preview' ? `npm run preview -- --port ${frontendPort} --strictPort` : `npm run dev -- --port ${frontendPort} --strictPort`; export default defineConfig({ testDir: './e2e', // 冒烟按顺序串行执行:登录 → 排产 → 视口 → 命令面板 共享一条核心路径 fullyParallel: false, workers: 1, timeout: 300_000, expect: { timeout: 20_000 }, retries: process.env.CI ? 1 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never', outputFolder: outputDir }]] : 'list', outputDir, use: { baseURL, viewport: { width: 1440, height: 900 }, trace: 'retain-on-failure', screenshot: 'only-on-failure', video: 'off', }, webServer: { command, url: baseURL, reuseExistingServer: !process.env.CI, timeout: 180_000, env: { ...process.env, VITE_API_TARGET: apiTarget }, }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, ], });