Files
novalon-website/e2e/playwright.config.ts
T
zhangxiang 0ed1331d1f chore(test): jest 全局 lucide mock 兜底 + playwright 显式 outputDir
- jest.setup.js: Proxy 兜底所有 lucide 命名导入,防 P5 CTAButton 后
  未显式 mock 的图标 undefined 导致渲染崩溃(测试内显式 mock 仍可覆盖)
- playwright.config.ts: outputDir 显式指向 e2e/test-results,避免项目根
  test-results 触发 WorkBuddy 沙箱 safe-delete BULK_GUARD(fs.rm ≥50 被拦)
2026-08-31 17:47:26 +08:00

132 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineConfig, devices } from '@playwright/test';
import { config as dotenvConfig } from 'dotenv';
import path from 'path';
// 加载项目根目录的 .env.local,使 Playwright webServer 与测试进程使用相同的 CMS_REVALIDATE_SECRET
// 若 .env.local 不存在则回退到默认测试 secret
dotenvConfig({ path: path.resolve(__dirname, '../.env.local') });
process.env.CMS_REVALIDATE_SECRET = process.env.CMS_REVALIDATE_SECRET || 'e2e-test-secret';
export default defineConfig({
testDir: './',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [
['html', { open: 'never' }],
['list', { printSteps: true }],
['allure-playwright', { outputFolder: 'allure-results' }],
],
snapshotDir: './visual-snapshots',
snapshotPathTemplate: '{snapshotDir}/{projectName}/{testFilePath}/{arg}-{projectName}{ext}',
// 显式 outputDir 绝对路径(e2e/test-results),避免 playwright 在项目根创建 test-results
// 触发 WorkBuddy 沙箱 safe-delete BULK_GUARDnode fs.rm ≥ 50 文件被拦,e2e 直接退出)
outputDir: path.join(__dirname, 'test-results'),
use: {
baseURL: process.env.E2E_BASE_URL || 'http://localhost:3000',
// 路径以配置文件所在目录为基准,兼容 `cd e2e` 与从项目根目录直接调用两种执行方式
storageState: path.resolve(__dirname, 'storageState.json'),
trace: 'on-first-retry',
screenshot: 'only-on-failure',
ignoreHTTPSErrors: true,
actionTimeout: 15000,
navigationTimeout: 30000,
},
expect: {
toHaveScreenshot: {
maxDiffPixels: 200,
maxDiffPixelRatio: 0.005,
threshold: 0.3,
animations: 'disabled',
caret: 'hide',
scale: 'device',
timeout: 20000,
},
timeout: 15000,
},
projects: [
{
name: 'visual-chromium-desktop',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1280, height: 800 },
},
testMatch: 'visual-regression.spec.ts',
},
{
name: 'visual-chromium-tablet',
use: {
...devices['iPad Pro 11'],
viewport: { width: 834, height: 1194 },
},
testMatch: 'visual-regression.spec.ts',
},
{
name: 'visual-chromium-mobile',
use: {
...devices['iPhone 14'],
viewport: { width: 390, height: 844 },
isMobile: true,
hasTouch: true,
},
testMatch: 'visual-regression.spec.ts',
},
{
name: 'visual-firefox-desktop',
use: {
...devices['Desktop Firefox'],
viewport: { width: 1280, height: 800 },
storageState: './storageState.firefox.json',
},
testMatch: 'visual-regression.spec.ts',
},
{
name: 'visual-webkit-desktop',
use: {
...devices['Desktop Safari'],
viewport: { width: 1280, height: 800 },
storageState: './storageState.firefox.json',
},
testMatch: 'visual-regression.spec.ts',
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
testIgnore: 'visual-regression.spec.ts',
},
{
name: 'chromium-mobile',
use: {
...devices['iPhone 14'],
viewport: { width: 390, height: 844 },
isMobile: true,
hasTouch: true,
},
testIgnore: 'visual-regression.spec.ts',
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'], storageState: './storageState.firefox.json' },
testIgnore: 'visual-regression.spec.ts',
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'], storageState: './storageState.firefox.json' },
testIgnore: 'visual-regression.spec.ts',
},
],
webServer: {
// 使用 dev server 以支持 API 路由(admin 用户旅程等测试需要)
// 若只运行非 API 测试(如 @journey @regression),可手动启动 npm run preview 并设置 reuseExistingServer: true
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: true,
timeout: 120000,
cwd: '..',
env: {
CMS_REVALIDATE_SECRET: process.env.CMS_REVALIDATE_SECRET || 'e2e-test-secret',
},
},
});