Przeglądaj źródła

docs(e2e-test-utils): 创建 Story 2.5 修复发现的问题

创建 Story 2.5 用于验证和修复 Story 2.4 中发现的问题。
Story 2.4 已经应用了多项修复,本 Story 主要验证修复效果。

验收标准:
- 验证 listbox → option 修复效果
- 验证下拉框关闭等待逻辑
- 检查是否有遗留问题
- 运行 E2E 测试确认

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 tydzień temu
rodzic
commit
bf5d2375c0

+ 301 - 0
_bmad-output/implementation-artifacts/2-5-fix-found-issues.md

@@ -0,0 +1,301 @@
+# Story 2.5: 修复发现的问题
+
+Status: ready-for-dev
+
+<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
+
+## Story
+
+作为测试开发者,
+我想要修复 Story 2.4 中发现的问题,
+以便工具可以正常使用。
+
+## Background
+
+在 Epic 2 的前四个 Story 中:
+- **Story 2.1**: 已安装 E2E 测试工具包并验证类型安全
+- **Story 2.2**: 已将静态 Select 操作迁移到新工具
+- **Story 2.3**: 已将异步 Select 操作迁移到新工具
+- **Story 2.4**: 运行了测试并收集了问题和改进建议
+
+Story 2.4 在测试过程中发现并已经修复了多个问题,但需要验证修复效果,并处理可能遗留的问题。
+
+## Acceptance Criteria
+
+1. **验证 Story 2.4 的修复效果**
+   - 确认 listbox → option 修复工作正常
+   - 确认下拉框关闭等待逻辑工作正常
+   - 确认超时配置优化合理
+
+2. **检查是否有遗留问题**
+   - 检查 Story 2.4 完成笔记中记录的问题
+   - 确定哪些问题需要在本 Story 中处理
+   - 确定哪些问题可以推迟或已解决
+
+3. **运行测试验证**
+   - 运行 E2E 测试确认所有功能正常
+   - 记录测试结果
+
+4. **更新文档**
+   - 更新工具包 README(如有需要)
+   - 记录修复的问题
+
+## Tasks / Subtasks
+
+- [ ] 分析 Story 2.4 完成笔记 (AC: #1, #2)
+  - [ ] 审查已应用的修复(listbox → option、下拉框关闭、超时配置)
+  - [ ] 确定是否需要额外修复
+- [ ] 运行测试验证修复效果 (AC: #3)
+  - [ ] 运行 `timeout 60 pnpm test:e2e:chromium disability-person-complete`
+  - [ ] 记录测试结果
+- [ ] 处理遗留问题 (AC: #2)
+  - [ ] 如有 HIGH 优先级问题,立即修复
+  - [ ] 如有 MEDIUM 优先级问题,评估是否需要修复
+  - [ ] LOW 优先级问题记录到待办事项
+- [ ] 更新文档 (AC: #4)
+  - [ ] 如有需要,更新 README
+  - [ ] 记录修复的问题到 Story 完成笔记
+
+## Dev Notes
+
+### Story 2.4 发现的问题回顾
+
+根据 Story 2.4 的完成笔记,以下问题已被发现和修复:
+
+#### 已应用的修复 (2026-01-10)
+
+1. **[工具 Bug - HIGH] listbox 依赖问题**
+   - 问题:工具等待 `[role="listbox"]` 元素,但 Radix UI Select v2.2.5 不使用此角色
+   - 修复:改用 `getByRole("option")` 代替 `waitForSelector("[role=listbox]")`
+   - 文件:`packages/e2e-test-utils/src/radix-select.ts`
+
+2. **下拉框关闭等待逻辑**
+   - 问题:选项点击后下拉框未关闭,下一个选择器被遮挡
+   - 修复:
+     - 点击选项后等待 200ms
+     - 等待 `getByRole("option")` 变为 `hidden` 状态
+
+3. **超时配置优化**
+   - 问题:超时时间过长,失败反馈慢
+   - 修复:将 `findTrigger` 和 `findAndClickOption` 中的超时从 5000ms 减少到 2000ms
+
+### 本 Story 需要完成的工作
+
+由于 Story 2.4 已经应用了修复,本 Story 主要工作是:
+
+1. **验证修复效果**:运行 E2E 测试确认修复有效
+2. **检查遗留问题**:确定是否还有需要处理的问题
+3. **文档更新**:如有需要,更新相关文档
+
+### Project Structure Notes
+
+**主要文件:**
+```
+packages/e2e-test-utils/
+└── src/
+    └── radix-select.ts          # 包含修复的工具函数
+
+web/tests/e2e/
+├── specs/admin/
+│   └── disability-person-complete.spec.ts    # 验证测试
+└── playwright.config.ts                       # 超时配置
+```
+
+### References
+
+- [Story 2.4 - 运行测试并收集问题][1]
+- [Story 2.3 - 异步 Select 重写][2]
+- [Story 2.2 - 静态 Select 重写][3]
+- [E2E 测试工具包 README][4]
+- [E2E Radix UI 测试标准][5]
+
+[1]: /mnt/code/188-179-template-6/_bmad-output/implementation-artifacts/2-4-run-tests-collect-feedback.md
+[2]: /mnt/code/188-179-template-6/_bmad-output/implementation-artifacts/2-3-rewrite-async-select.md
+[3]: /mnt/code/188-179-template-6/_bmad-output/implementation-artifacts/2-2-rewrite-static-select.md
+[4]: /mnt/code/188-179-template-6/packages/e2e-test-utils/README.md
+[5]: /mnt/code/188-179-template-6/docs/standards/e2e-radix-testing.md
+
+---
+
+## Developer Context
+
+> **重要提示:** 本部分包含开发者实现此故事所需的所有关键上下文和约束条件。
+
+### 当前状态
+
+Story 2.4 已经完成以下修复:
+
+1. **selectRadixOption 修复**:
+   - 使用 `getByRole("option", { name: value })` 定位选项
+   - 移除 `exact: true` 允许模糊匹配
+   - 添加下拉框关闭等待逻辑
+
+2. **selectRadixOptionAsync 修复**:
+   - 同样使用 `getByRole` 策略
+   - 应用相同的下拉框关闭等待逻辑
+
+3. **超时配置**:
+   - `findTrigger` 和 `findAndClickOption` 超时从 5000ms 改为 2000ms
+
+### 技术需求
+
+#### 1. 修复后的选择器策略
+
+```typescript
+// packages/e2e-test-utils/src/radix-select.ts
+
+// 新的选项定位策略(更可靠)
+async function findAndClickOption(page: Page, value: string): Promise<void> {
+  // 使用 getByRole 而非 waitForSelector
+  const option = page.getByRole("option", { name: value });
+  await option.click({ timeout: 2000 });
+
+  // 等待下拉框关闭
+  await page.waitForTimeout(200);
+  await page.getByRole("option").first().waitFor({ state: 'hidden' });
+}
+```
+
+#### 2. 验证步骤
+
+运行以下测试验证修复效果:
+
+```bash
+cd web
+timeout 60 pnpm test:e2e:chromium disability-person-complete
+```
+
+**预期结果**:
+- 所有表单字段成功填写
+- 静态 Select(残疾类型、残疾等级)正常工作
+- 异步 Select(省份、城市)正常工作
+- 无超时或元素未找到错误
+
+#### 3. 可能的遗留问题
+
+基于 Story 2.4 的完成笔记,以下问题可能需要关注:
+
+| 优先级 | 问题 | 状态 |
+|--------|------|------|
+| HIGH | listbox 依赖 | ✅ 已修复 |
+| HIGH | 下拉框关闭 | ✅ 已修复 |
+| MEDIUM | 错误消息清晰度 | ⚠️ 可能需要改进 |
+| LOW | 性能优化 | ⚠️ 已部分修复(超时缩短) |
+
+### 架构合规性
+
+#### 工具包设计原则
+
+**Playwright API 使用**:
+- ✅ 使用 `getByRole()` 进行角色定位(推荐方式)
+- ✅ 使用 `waitFor({ state: 'hidden' })` 等待元素隐藏
+- ⚠️ 使用 `waitForTimeout(200)` 作为最小等待(可接受,用于等待 UI 响应)
+
+**错误处理**:
+- 所有错误应使用 `E2ETestError` 抛出
+- 错误消息应包含:操作类型、目标、期望值、可用选项、修复建议
+
+### 库和框架要求
+
+#### Playwright 版本
+
+| 包 | 版本 | 要求 |
+|---|------|------|
+| @playwright/test (web) | 1.55.0 | ✅ 满足 ^1.40.0 |
+| @d8d/e2e-test-utils | - | peer dependency: ^1.40.0 |
+
+#### 测试超时配置
+
+```typescript
+// web/tests/e2e/playwright.config.ts
+timeout: 60000  // 60秒,单个测试的默认超时
+```
+
+### 测试要求
+
+#### 验证步骤
+
+**1. 运行完整测试:**
+```bash
+cd web
+timeout 60 pnpm test:e2e:chromium disability-person-complete
+```
+
+**2. 观察点:**
+- ✅ 所有表单字段成功填写
+- ✅ 静态 Select 工作正常
+- ✅ 异步 Select 工作正常
+- ✅ 无超时或元素未找到错误
+- ✅ 下拉框关闭逻辑工作正常
+
+**3. 性能检查:**
+- 总测试时间应在合理范围内(< 60 秒)
+- 单个 Select 操作应快速完成(< 2 秒静态,< 5 秒异步)
+
+### 上一个故事的经验(Story 2.4)
+
+#### Story 2.4 关键经验
+
+**1. DOM 结构理解**:
+- Radix UI Select v2.2.5 使用 `[role="combobox"]` 而非 `[role="listbox"]`
+- 选项使用 `[role="option"]`,可通过 `getByRole` 定位
+
+**2. 修复验证**:
+- Story 2.4 完成笔记中确认所有表单字段都成功填写
+- 包括:姓名、性别、身份证号、残疾类型、残疾等级、省份、城市
+
+**3. 测试命令**:
+- 使用 `timeout` 命令限制总运行时间
+- 示例:`timeout 60 pnpm test:e2e:chromium`
+
+### Epic 1 回顾经验
+
+#### TypeScript + Playwright 最佳实践 [来源: epic-1-retrospective.md]
+
+**1. 使用 getByRole 优先**:
+- ✅ 推荐:`page.getByRole("option", { name: value })`
+- ❌ 避免:`page.waitForSelector("[role=listbox]")`
+
+**2. 精确文本匹配**:
+- 使用 `name: value` 而非 `exact: true` 进行模糊匹配
+- 这可以处理选项包含额外空格或格式的情况
+
+**3. 等待元素隐藏**:
+- ✅ 推荐:`await element.waitFor({ state: 'hidden' })`
+- ❌ 避免:假设元素立即消失
+
+### 项目上下文引用
+
+**完整项目上下文:** `_bmad-output/project-context.md`
+
+**关键规范:**
+- 测试框架:Playwright 1.55.0
+- 包管理:pnpm workspace 协议
+- TypeScript:严格模式,无 `any` 类型
+- 测试命令:`pnpm test:e2e:chromium`
+
+**相关文档:**
+- Epic 2 详情:`_bmad-output/planning-artifacts/epics.md#Epic-2`
+- Story 2.4:`_bmad-output/implementation-artifacts/2-4-run-tests-collect-feedback.md`
+- 工具包源码:`packages/e2e-test-utils/src/radix-select.ts`
+- 测试标准:`docs/standards/e2e-radix-testing.md`
+
+---
+
+## Dev Agent Record
+
+### Agent Model Used
+
+Claude Opus 4.5 (claude-opus-4-5-20251101)
+
+### Debug Log References
+
+(开发过程中添加调试日志引用)
+
+### Completion Notes List
+
+(完成时添加笔记)
+
+### File List
+
+(完成时添加文件列表)

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

@@ -57,7 +57,7 @@ development_status:
   2-2-rewrite-static-select: done
   2-3-rewrite-async-select: done
   2-4-run-tests-collect-feedback: done  # 完成 - 修复了 listbox 依赖、超时配置、下拉框关闭逻辑
-  2-5-fix-found-issues: backlog
+  2-5-fix-found-issues: ready-for-dev
   2-6-stability-verification: backlog
   epic-2-retrospective: optional