# Story 2.5: 修复发现的问题 Status: ready-for-dev ## 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 { // 使用 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 (完成时添加文件列表)