Ver código fonte

docs(e2e-test-utils): 创建 Story 2.1 安装 e2e-utils 包

- 创建 Story 2.1: 在 web 目录安装 @d8d/e2e-test-utils
- Epic 2 状态更新为 in-progress
- Story 2.1 状态更新为 ready-for-dev
- 包含完整的开发者上下文、技术需求和验证步骤

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 semana atrás
pai
commit
35bde407ae

+ 331 - 0
_bmad-output/implementation-artifacts/2-1-install-e2e-utils.md

@@ -0,0 +1,331 @@
+# Story 2.1: 在 web 目录安装 @d8d/e2e-test-utils
+
+Status: ready-for-dev
+
+<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
+
+## Story
+
+作为测试开发者,
+我想要在 web 目录安装 `@d8d/e2e-test-utils` 包,
+以便在 E2E 测试中使用 Select 工具。
+
+## Acceptance Criteria
+
+1. **Given** Epic 1 已完成,`@d8d/e2e-test-utils` 包已构建
+2. **When** 在 `web/package.json` 中添加 workspace 依赖
+3. **Then** 可以在 `web/tests/e2e/` 中导入 Select 工具
+4. **And** TypeScript 类型检查通过
+5. **And** 运行时无依赖错误
+
+## Tasks / Subtasks
+
+- [ ] 安装 @d8d/e2e-test-utils 包到 web 目录 (AC: #1, #2)
+  - [ ] 使用 `pnpm add -D @d8d/e2e-test-utils@workspace:*` 安装
+  - [ ] 验证 package.json 已正确添加依赖
+- [ ] 验证工具函数可以正确导入 (AC: #3)
+  - [ ] 在测试文件中添加 `import { selectRadixOption } from '@d8d/e2e-test-utils'`
+  - [ ] 确认 TypeScript 类型检查通过
+- [ ] 验证运行时无依赖错误 (AC: #4, #5)
+  - [ ] 运行 `pnpm typecheck` 确认类型检查通过
+  - [ ] 确认 @playwright/test 版本兼容性
+
+## Dev Notes
+
+### Epic Context
+
+**Epic 2 目标:** 在 `web/tests/e2e/` 的现有残疾人管理测试中使用 Select 工具,验证工具在真实场景中的可用性和稳定性。
+
+**Epic 2 范围:**
+- ✅ 使用现有 `web/tests/e2e/` 测试基础设施
+- ✅ 使用现有的残疾人管理测试场景
+- ❌ 不创建新的测试应用
+- ❌ 不添加新功能(仅验证现有功能)
+
+### 依赖关系
+
+**前置依赖:**
+- Epic 1: ✅ 已完成(`@d8d/e2e-test-utils` 包已构建)
+- Story 1.5: ✅ 主导出和基础文档已完成
+- Story 1.6: ✅ 单元测试已通过(覆盖率 93.65%)
+
+**后续故事:**
+- Story 2.2: 使用 selectRadixOption 重写残疾类型选择
+- Story 2.3: 使用 selectRadixOptionAsync 重写省份/城市选择
+
+### 实现要点
+
+1. **使用 pnpm workspace 协议安装:**
+   ```bash
+   cd web
+   pnpm add -D @d8d/e2e-test-utils@workspace:*
+   ```
+
+2. **验证导入正常:**
+   ```typescript
+   // web/tests/e2e/pages/admin/disability-person.page.ts
+   import { selectRadixOption, selectRadixOptionAsync } from '@d8d/e2e-test-utils';
+   ```
+
+3. **TypeScript 类型检查:**
+   - 确认 IDE 可以自动补全工具函数
+   - 运行 `pnpm typecheck` 确认无类型错误
+
+### Package 版本兼容性
+
+**@d8d/e2e-test-utils peer dependencies:**
+```json
+{
+  "peerDependencies": {
+    "@playwright/test": "^1.40.0"
+  }
+}
+```
+
+**web 当前 Playwright 版本:**
+```json
+{
+  "devDependencies": {
+    "@playwright/test": "1.55.0"
+  }
+}
+```
+
+✅ **版本兼容确认:** 1.55.0 满足 ^1.40.0 要求
+
+### 测试位置
+
+**现有 E2E 测试文件:**
+```
+web/tests/e2e/
+├── specs/
+│   └── admin/
+│       └── disability-person-complete.spec.ts
+├── pages/
+│   └── admin/
+│       └── disability-person.page.ts
+└── playwright.config.ts
+```
+
+**将在下一个故事(2.2)中修改的文件:**
+- `web/tests/e2e/pages/admin/disability-person.page.ts`
+
+## Dev Agent Record
+
+### Agent Model Used
+
+Claude Opus 4.5 (claude-opus-4-5-20251101)
+
+### Debug Log References
+
+### Completion Notes List
+
+### File List
+
+- `web/package.json` - 添加 devDependency
+- `web/tests/e2e/pages/admin/disability-person.page.ts` - 验证导入(不修改实现,仅测试导入)
+
+---
+
+## Developer Context
+
+> **重要提示:** 本部分包含开发者实现此故事所需的所有关键上下文和约束条件。
+
+### 技术需求
+
+#### 1. 安装命令
+
+在 web 目录执行以下命令安装工具包:
+
+```bash
+cd web
+pnpm add -D @d8d/e2e-test-utils@workspace:*
+```
+
+#### 2. 验证依赖安装正确
+
+安装后,`web/package.json` 的 `devDependencies` 应包含:
+
+```json
+{
+  "devDependencies": {
+    "@d8d/e2e-test-utils": "workspace:*",
+    "@playwright/test": "1.55.0"
+  }
+}
+```
+
+#### 3. 验证导入语句
+
+在 E2E 测试文件中,应该能够成功导入工具函数:
+
+```typescript
+// web/tests/e2e/pages/admin/disability-person.page.ts
+import { selectRadixOption, selectRadixOptionAsync } from '@d8d/e2e-test-utils';
+```
+
+#### 4. TypeScript 类型检查
+
+运行类型检查确保无错误:
+
+```bash
+pnpm typecheck
+```
+
+### 架构合规性
+
+#### Monorepo Workspace 协议
+
+- 使用 `workspace:*` 协议引用内部包
+- 开发时自动链接到 `packages/e2e-test-utils`
+- 构建时使用构建后的产物
+
+#### Peer Dependency 约束
+
+`@d8d/e2e-test-utils` 声明 `@playwright/test` 为 peer dependency:
+
+```json
+{
+  "peerDependencies": {
+    "@playwright/test": "^1.40.0"
+  }
+}
+```
+
+**含义:**
+- 工具包不打包 Playwright,由使用方提供
+- web 项目已有 `@playwright/test@1.55.0`,满足要求
+- 无需额外安装 Playwright
+
+### 库和框架要求
+
+#### Playwright 版本兼容性
+
+| 包 | 版本 | 状态 |
+|---|---|---|
+| @playwright/test (web) | 1.55.0 | ✅ 满足 ^1.40.0 |
+| @playwright/test (工具包要求) | ^1.40.0 | - |
+
+#### TypeScript 配置
+
+确保 `web/tsconfig.json` 支持导入工具包类型:
+
+```json
+{
+  "compilerOptions": {
+    "strict": true,
+    "moduleResolution": "bundler",
+    "esModuleInterop": true
+  }
+}
+```
+
+### 文件结构要求
+
+#### 工具包导出结构
+
+`packages/e2e-test-utils/src/index.ts` 导出以下内容:
+
+```typescript
+// Select 工具
+export { selectRadixOption } from './radix-select.js';
+export { selectRadixOptionAsync } from './radix-select.js';
+
+// 类型
+export type { BaseOptions } from './types.js';
+export type { AsyncSelectOptions } from './radix-select.js';
+
+// 错误
+export { E2ETestError } from './errors.js';
+export type { ErrorContext } from './errors.js';
+```
+
+#### 可导入的工具函数
+
+| 函数名 | 用途 | 参数 |
+|---|---|---|
+| `selectRadixOption` | 静态 Select 选择 | (page, label, value) |
+| `selectRadixOptionAsync` | 异步 Select 选择 | (page, label, value, options?) |
+
+### 测试要求
+
+#### 验证步骤
+
+1. **安装后立即验证:**
+   ```bash
+   cd web
+   pnpm list @d8d/e2e-test-utils
+   ```
+
+2. **TypeScript 类型检查:**
+   ```bash
+   pnpm typecheck
+   ```
+
+3. **导入测试(临时添加到测试文件):**
+   ```typescript
+   // 在文件顶部添加
+   import { selectRadixOption, selectRadixOptionAsync } from '@d8d/e2e-test-utils';
+   // 保存后确认 IDE 无错误提示
+   ```
+
+#### 不需要运行测试
+
+本故事仅安装和验证导入,不需要:
+- 修改现有测试代码
+- 运行 E2E 测试
+- 实现新的测试逻辑
+
+这些将在 Story 2.2 和 2.3 中完成。
+
+### 上一个故事的经验(Epic 1 Retrospective)
+
+#### 关键经验
+
+1. **代码审查发现的问题类型:**
+   - HIGH: DOM 类型问题、精确文本匹配
+   - MEDIUM: 错误消息不清晰
+   - LOW: 代码风格
+
+2. **TypeScript + Playwright 陷阱:**
+   - 避免使用 `page.evaluate()` 获取文本
+   - 使用 `:text-is()` 而非 `:has-text()` 进行精确匹配
+   - 网络空闲等待使用用户自定义的超时值
+
+3. **测试覆盖率目标:**
+   - ≥80% 覆盖率
+   - 单元测试使用 Vitest
+   - E2E 测试使用 Playwright
+
+#### 需要注意的技术决策
+
+1. **选择器策略优先级:**
+   1. `data-testid` - 最高优先级
+   2. `aria-label` + role - 无障碍标准
+   3. Text content + role - 兜底方案
+
+2. **错误处理模式:**
+   - 使用 `E2ETestError` 而非原生 `Error`
+   - 提供结构化的错误上下文
+
+### 项目上下文引用
+
+**完整项目上下文:** `_bmad-output/project-context.md`
+
+**关键规范:**
+- 测试框架:Playwright 1.55.0
+- 包管理:pnpm workspace 协议
+- TypeScript:严格模式
+- 测试命令:`pnpm test:e2e:chromium`
+
+**相关文档:**
+- 架构文档:`_bmad-output/planning-artifacts/architecture.md`
+- Epic 1 回顾:`_bmad-output/implementation-artifacts/epic-1-retrospective.md`
+- Epic 详情:`_bmad-output/planning-artifacts/epics.md`
+
+### 下一步
+
+完成本故事后,继续:
+- Story 2.2: 使用 selectRadixOption 重写残疾类型选择
+- Story 2.3: 使用 selectRadixOptionAsync 重写省份/城市选择
+

+ 2 - 2
_bmad-output/implementation-artifacts/sprint-status.yaml

@@ -52,8 +52,8 @@ development_status:
 
   # Epic 2: 在现有 E2E 测试中验证 Select 工具 (新 Epic - 来自回顾会议)
   # 详情参见: _bmad-output/implementation-artifacts/epic-1-retrospective.md
-  epic-2: backlog
-  2-1-install-e2e-utils: backlog
+  epic-2: in-progress
+  2-1-install-e2e-utils: ready-for-dev
   2-2-rewrite-static-select: backlog
   2-3-rewrite-async-select: backlog
   2-4-run-tests-collect-feedback: backlog