# 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`
