diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index 2a3ca41..95f2635 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -20,6 +20,9 @@ export default defineConfig({ ], snapshotDir: './visual-snapshots', snapshotPathTemplate: '{snapshotDir}/{projectName}/{testFilePath}/{arg}-{projectName}{ext}', + // 显式 outputDir 绝对路径(e2e/test-results),避免 playwright 在项目根创建 test-results + // 触发 WorkBuddy 沙箱 safe-delete BULK_GUARD(node fs.rm ≥ 50 文件被拦,e2e 直接退出) + outputDir: path.join(__dirname, 'test-results'), use: { baseURL: process.env.E2E_BASE_URL || 'http://localhost:3000', // 路径以配置文件所在目录为基准,兼容 `cd e2e` 与从项目根目录直接调用两种执行方式 diff --git a/jest.setup.js b/jest.setup.js index f4de7a6..1880621 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -49,6 +49,34 @@ jest.mock('@/lib/cms/data-server', () => ({ getAllPublishedSlugs: jest.fn().mockResolvedValue([]), })); +// 全局 mock lucide-react 防止 missing named export 导致测试渲染崩溃 +// 解决 P5 切换 CTAButton 后暴露的问题:lucide-react 是 ESM,jest 转换默认排除 node_modules, +// 测试中未显式 mock 的 lucide 命名导入会拿到 undefined → 渲染崩。 +// 用 Proxy 兜底所有图标(任何 named import 自动返回 stub 组件), +// 对齐 services-content-v3.test.tsx 等显式 mock 范式(data-testid: icon-{name.toLowerCase()})。 +// 测试内的显式 jest.mock('lucide-react', ...) 会覆盖此兜底(保留细粒度 mock 兼容性)。 +jest.mock('lucide-react', () => { + const React = require('react'); + const makeIcon = (name) => { + const Icon = (props) => + React.createElement('svg', { + 'data-testid': `icon-${name.toLowerCase()}`, + className: props?.className, + }); + Icon.displayName = name; + return Icon; + }; + const lucide = new Proxy({ __esModule: true }, { + get(_target, prop) { + if (prop === '__esModule') return true; + if (prop === 'default') return lucide; + if (typeof prop === 'symbol') return undefined; + return makeIcon(String(prop)); + }, + }); + return lucide; +}); + jest.mock('next/dynamic', () => ({ __esModule: true, default: (_importFn, _options) => {