# E2E 测试工具包 - 开发者自查清单 > 本清单基于 Epic 1 和 Epic 2 的回顾总结,确保代码质量和一致性。 > 参见: _bmad-output/implementation-artifacts/epic-1-retrospective.md, epic-2-retrospective.md --- ## 代码质量 ### JSDoc 文档 - [ ] **所有导出函数都有完整的 JSDoc** - 包含 `@param` - 参数说明 - 包含 `@returns` - 返回值说明 - 包含 `@throws {E2ETestError}` - 可能抛出的错误 - 包含 `@example` - 使用示例 - [ ] **内部函数使用 `@internal` 标记** ```typescript /** * @internal * 内部辅助函数,不导出 */ ``` ### 错误处理 - [ ] **使用 `E2ETestError` 而非原生 `Error`** ```typescript // ✅ 正确 throwError({ operation: 'selectRadixOption', target: label, expected: value, }); // ❌ 错误 throw new Error('Select failed'); ``` --- ## 选择器策略 ### 文本匹配 - [ ] **使用 `:text-is()` 而非 `:has-text()` 进行精确匹配** ```typescript // ✅ 精确匹配 page.locator(`.option:text-is("广东省")`) // ❌ 部分匹配 - 可能误选 page.locator(`.option:has-text("广东省")`) ``` ### DOM 结构验证 - [ ] **DOM 结构假设必须基于真实组件验证** - 不能基于理想模型开发工具 - 必须在真实 Radix UI 组件上验证 - 单元测试无法发现真实 DOM 问题,必须添加集成测试 --- ## 配置和超时 ### 配置对象 - [ ] **配置对象继承 `BaseOptions`** ```typescript export interface AsyncSelectOptions extends BaseOptions { waitForOption?: boolean; waitForNetworkIdle?: boolean; } ``` ### 超时配置 - [ ] **超时值使用 `DEFAULT_TIMEOUTS` 常量** ```typescript import { DEFAULT_TIMEOUTS } from './constants.js'; await page.waitForTimeout(DEFAULT_TIMEOUTS.static); ``` - [ ] **网络空闲等待使用用户自定义的超时值** ```typescript // ✅ 正确 - 使用用户自定义的 timeout await page.waitForLoadState('networkidle', { timeout: options.timeout ?? DEFAULT_TIMEOUTS.async }); // ❌ 错误 - 使用固定的 networkIdle 超时 await page.waitForLoadState('networkidle', { timeout: DEFAULT_TIMEOUTS.networkIdle }); ``` --- ## DOM 操作 ### 避免使用 page.evaluate - [ ] **避免使用 `page.evaluate()` 处理 DOM 操作** ```typescript // ❌ 不推荐 - TypeScript 类型问题 const text = await page.evaluate(el => el.textContent, element); // ✅ 推荐 - 使用 Playwright API const text = await element.textContent(); // ✅ 推荐 - 使用 locator 获取多个文本 const texts = await page.locator(selector).allTextContents(); ``` --- ## 测试策略(Epic 2 关键发现) ### 集成测试重要性 - [ ] **单元测试无法发现真实 DOM 结构问题** - 单元测试使用模拟 DOM,覆盖率 93.65% 仍然无法发现 DOM 问题 - 必须添加集成测试级别 - [ ] **使用真实组件验证工具** - 使用真实的 Radix UI 组件进行测试 - 不能仅依赖模拟 DOM --- ## ESLint 检查 运行以下命令确保代码符合规范: ```bash # 类型检查 pnpm typecheck # ESLint 检查 pnpm lint # 单元测试 pnpm test:unit # 覆盖率检查 pnpm test:coverage ``` --- ## 提交前检查 在提交代码或创建 PR 之前,确保: - [ ] 所有 ESLint 检查通过 - [ ] 所有单元测试通过 - [ ] 测试覆盖率 ≥ 80% - [ ] 类型检查通过(无 `any` 类型) - [ ] 所有导出函数有完整 JSDoc - [ ] 错误处理使用 `E2ETestError` - [ ] 选择器使用精确匹配 `:text-is()` - [ ] 超时值使用 `DEFAULT_TIMEOUTS` --- ## 快速参考 ### 常见错误模式 | 模式 | 正确 | 错误 | |------|------|------| | 文本匹配 | `:text-is("value")` | `:has-text("value")` | | 错误处理 | `E2ETestError` | `Error` | | DOM 操作 | `element.textContent()` | `page.evaluate()` | | 超时配置 | `DEFAULT_TIMEOUTS.static` | `2000` (硬编码) | | 网络等待 | `options.timeout` | `DEFAULT_TIMEOUTS.networkIdle` | ### 相关文档 - 架构文档: `_bmad-output/planning-artifacts/architecture.md` - Epic 1 回顾: `_bmad-output/implementation-artifacts/epic-1-retrospective.md` - Epic 2 回顾: `_bmad-output/implementation-artifacts/epic-2-retrospective.md`