Explorar o código

📝 docs(planning): 完成 E2E 测试工具包史诗和用户故事分解

- 从 PRD 和架构文档生成完整的史诗和故事分解
- 4 个史诗,19 个用户故事,覆盖所有 50 个功能需求
- Epic 1: 测试工具包基础框架与 Select 支持
- Epic 2: 扩展工具集(文件上传、表单、列表、对话框)
- Epic 3: 在残疾人管理中验证工具包
- Epic 4: 完善文档与开发者体验
- 所有史诗独立可用,故事无前向依赖

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

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname hai 1 semana
pai
achega
a9b96772b3
Modificáronse 1 ficheiros con 747 adicións e 0 borrados
  1. 747 0
      _bmad-output/planning-artifacts/epics.md

+ 747 - 0
_bmad-output/planning-artifacts/epics.md

@@ -0,0 +1,747 @@
+---
+stepsCompleted: ['step-01-validate-prerequisites', 'step-02-design-epics', 'step-03-create-stories']
+inputDocuments:
+  - name: PRD - E2E测试工具包
+    path: _bmad-output/planning-artifacts/prd.md
+    type: prd
+  - name: Architecture - E2E测试工具包
+    path: _bmad-output/planning-artifacts/architecture.md
+    type: architecture
+  - name: E2E Radix UI 测试标准
+    path: docs/standards/e2e-radix-testing.md
+    type: testing-standard
+---
+
+# 188-179-template-6 - Epic Breakdown
+
+## Overview
+
+This document provides the complete epic and story breakdown for 188-179-template-6,从残疾人管理 E2E 测试实践中提取可复用的测试工具包。
+
+## Requirements Inventory
+
+### Functional Requirements
+
+**Radix UI Select 组件测试支持 (FR1-FR6):**
+- FR1: 测试开发者可以使用工具函数选择静态枚举型 Radix UI Select 下拉框的选项
+- FR2: 测试开发者可以使用工具函数选择异步加载型 Radix UI Select 下拉框的选项
+- FR3: 工具函数可以自动处理 Radix UI Select 的 DOM 结构和交互流程
+- FR4: 工具函数可以等待异步加载的选项出现在下拉列表中
+- FR5: 工具函数可以提供清晰的错误提示,包含标签、期望值等上下文信息
+- FR6: 工具函数可以区分"元素未找到"和"超时"错误类型
+
+**文件上传测试支持 (FR7-FR10):**
+- FR7: 测试开发者可以使用工具函数上传文件到指定的文件输入字段
+- FR8: 工具函数可以从 fixtures 目录加载测试文件
+- FR9: 工具函数可以支持多文件上传场景
+- FR10: 工具函数可以验证文件上传是否成功完成
+
+**表单交互测试支持 (FR11-FR15):**
+- FR11: 测试开发者可以使用工具函数填写多步骤表单
+- FR12: 工具函数可以滚动页面到特定的表单区域
+- FR13: 工具函数可以处理表单验证错误场景
+- FR14: 测试开发者可以使用工具函数提交表单并等待响应
+- FR15: 工具函数可以支持常见的表单字段类型(文本、选择器、日期等)
+
+**动态列表测试支持 (FR16-FR20):**
+- FR16: 测试开发者可以使用工具函数向动态列表中添加新项
+- FR17: 测试开发者可以使用工具函数从动态列表中删除项
+- FR18: 工具函数可以支持不同类型的动态列表项(银行卡、备注等)
+- FR19: 工具函数可以验证动态列表项添加或删除后的状态
+- FR20: 工具函数可以处理动态列表的异步更新场景
+
+**对话框操作测试支持 (FR21-FR24):**
+- FR21: 测试开发者可以使用工具函数统一操作对话框(确认、取消、关闭)
+- FR22: 工具函数可以等待对话框完全关闭后再继续执行
+- FR23: 工具函数可以处理对话框内的表单填写和提交
+- FR24: 工具函数可以验证对话框是否按预期打开或关闭
+
+**测试工具包基础设施 (FR25-FR32):**
+- FR25: 测试开发者可以通过 npm workspace 协议安装测试工具包
+- FR26: 工具包可以作为 peer dependency 依赖 Playwright,不增加运行时依赖
+- FR27: 工具包提供完整的 TypeScript 类型定义和类型提示
+- FR28: 工具包的所有导出函数都有完整的 JSDoc 注释
+- FR29: 工具包使用严格类型检查,不使用 any 类型
+- FR30: 工具包支持目标 ES2020+ 的 JavaScript 环境
+- FR31: 工具包的每个工具函数都可以独立导入和使用
+- FR32: 工具包可以与其他测试工具和库兼容使用
+
+**文档和开发者支持 (FR33-FR40):**
+- FR33: 测试开发者可以通过 README 快速了解工具包的用途和安装方法
+- FR34: 文档提供每个工具函数的详细使用示例
+- FR35: 文档提供静态 Select 和异步 Select 的区别说明
+- FR36: 文档提供从现有测试代码迁移到工具函数的指南
+- FR37: 文档提供常见问题和解决方案
+- FR38: 文档提供残疾人管理测试作为完整的使用示例
+- FR39: 测试开发者可以在 30 分钟内使用工具函数编写第一个测试
+- FR40: 工具包的使用示例覆盖所有 6 个核心工具函数
+
+**测试质量和稳定性保障 (FR41-FR45):**
+- FR41: 工具函数使用 Playwright 的 auto-waiting 机制防止时序问题
+- FR42: 工具函数为静态选项设置合理的默认超时配置
+- FR43: 工具函数为异步选项提供可配置的超时参数
+- FR44: 工具函数可以支持重试机制处理不稳定的网络请求
+- FR45: 工具函数可以在测试连续运行 20 次时保持 100% 通过率
+
+**可扩展性和维护性 (FR46-FR50):**
+- FR46: 工具函数支持配置对象参数,允许自定义行为
+- FR47: 工具函数设计支持未来的 Radix UI 版本升级
+- FR48: 工具函数使用稳定的选择器策略(role、data-testid)
+- FR49: 工具包预留扩展接口,支持新增其他 Radix 组件测试模式
+- FR50: 工具包的代码结构清晰,便于团队贡献和维护
+
+### NonFunctional Requirements
+
+**可靠性 (NFR1-NFR7):**
+- NFR1: 工具函数在相同条件下连续运行 20 次,必须保持 100% 通过率,无 flaky 失败
+- NFR2: 工具函数能够正确处理异步加载场景,避免时序问题导致的测试失败
+- NFR3: 当 DOM 元素暂时不可用时,工具函数提供清晰的错误消息,而不是超时无响应
+- NFR4: 工具函数能够区分产品 bug 和测试代码问题,帮助开发者快速定位问题根源
+- NFR5: 当选择操作失败时,错误消息包含:下拉框标签名称、期望选择的值、实际可用的选项列表、失败原因
+- NFR6: 当文件上传失败时,错误消息包含文件路径、选择器、失败原因
+- NFR7: 错误消息格式统一,便于日志分析和问题定位
+
+**性能 (NFR8-NFR14):**
+- NFR8: 单个 Radix UI Select 选择操作(静态)应在 2 秒内完成
+- NFR9: 单个 Radix UI Select 选择操作(异步)应在 5 秒内完成(默认超时)
+- NFR10: 工具函数本身的开销不超过 100ms(不包括 Playwright 操作时间)
+- NFR11: 使用工具函数的测试比手动编写 DOM 操作的测试执行时间差异 < 10%
+- NFR12: 静态选项使用合理的默认超时(2 秒),避免不必要的等待
+- NFR13: 异步选项提供可配置的超时参数,默认值为 5 秒
+- NFR14: 工具函数使用 Playwright 的 auto-waiting 机制,减少显式等待的需要
+
+**集成性 (NFR15-NFR24):**
+- NFR15: 工具包兼容 Playwright 最新稳定版本和上一个 LTS 版本
+- NFR16: 工具包可以作为 peer dependency 引用,不增加运行时依赖
+- NFR17: 工具函数接受标准 Playwright Page 对象作为参数
+- NFR18: 工具包不依赖特定版本的 Playwright,使用灵活的版本范围
+- NFR19: 工具函数可以在任何使用 Playwright 的测试框架中运行(Vitest、Jest 等)
+- NFR20: 工具包不修改全局配置,不需要额外的测试框架配置
+- NFR21: 工具函数可以与现有的 Page Object 模式无缝集成
+- NFR22: 工具包通过 pnpm workspace 协议安装,支持本地开发
+- NFR23: 工具包的构建产物与项目的 TypeScript 配置兼容
+- NFR24: 工具包的类型定义可以自动被 IDE 识别和提示
+
+**代码质量 (NFR25-NFR40):**
+- NFR25: 工具包使用 TypeScript 严格模式,无 `any` 类型
+- NFR26: 所有导出函数都有完整的参数类型和返回值类型
+- NFR27: 类型定义支持 IDE 自动补全和类型检查
+- NFR28: 类型错误在编译时被捕获,不在运行时暴露
+- NFR29: 工具包的代码覆盖率 ≥ 80%
+- NFR30: 每个工具函数都有对应的单元测试
+- NFR31: 代码遵循项目的 ESLint 和 Prettier 配置
+- NFR32: 函数复杂度保持在低水平(圈复杂度 < 10)
+- NFR33: 每个导出函数都有完整的 JSDoc 注释
+- NFR34: README 包含快速入门、安装说明、基本用法
+- NFR35: 每个工具函数至少有 1 个实际使用示例
+- NFR36: 文档说明静态 Select 和异步 Select 的区别和使用场景
+- NFR37: 新测试开发者可以在 30 分钟内使用工具函数编写第一个测试
+- NFR38: 工具函数的命名清晰直观,不需要频繁查看文档
+- NFR39: 函数参数设计简洁,必需参数 ≤ 3 个
+- NFR40: 错误消息对新手友好,包含问题诊断和建议修复步骤
+
+**兼容性 (NFR41-NFR46):**
+- NFR41: 工具函数在 Playwright 支持的所有浏览器中正常工作(Chromium、Firefox、WebKit)
+- NFR42: 工具函数在 headless 和 headed 模式下都能正常工作
+- NFR43: 工具函数在 CI/CD 环境中稳定运行
+- NFR44: 工具包支持 Node.js 当前 LTS 版本和上一个 LTS 版本
+- NFR45: 工具包的设计考虑未来 Radix UI 版本升级,使用稳定的选择器策略
+- NFR46: 重大版本变更时提供迁移指南
+
+### Additional Requirements
+
+**从 Architecture 文档提取的技术需求:**
+
+**包结构需求:**
+- 创建独立包 `packages/e2e-test-utils`,与现有的 `@d8d/shared-test-util`(后端集成测试)分离
+- 按功能分组文件结构:`src/` 分为 `radix-select.ts`, `file-upload.ts`, `form-helper.ts`, `dialog.ts`, `dynamic-list.ts`
+- 共享代码集中在 `types.ts`, `errors.ts`, `constants.ts`
+- 主导出使用 `index.ts`,支持 tree-shaking
+
+**API 设计需求:**
+- 必需参数 ≤ 3 个,复杂配置通过可选对象传递
+- 函数命名:动词+名词,camelCase(如 `selectRadixOption`)
+- 异步函数添加 `Async` 后缀(如 `selectRadixOptionAsync`)
+- 类型命名:接口 PascalCase + `Options` 后缀(如 `AsyncSelectOptions`)
+
+**类型系统需求:**
+- 分层类型:`types.ts` 存放共享类型(`BaseOptions`),各模块文件存放特定类型
+- 所有配置对象继承 `BaseOptions`
+- TypeScript 严格模式,无 `any` 类型
+
+**选择器策略需求:**
+- 混合策略优先级:data-testid → aria-label + role → text content + role
+- 推荐在 Radix 组件上添加 `data-testid`
+
+**错误处理需求:**
+- 使用结构化错误类 `E2ETestError` + `ErrorContext`
+- 错误消息格式:❌ 操作失败、上下文信息、💡 修复建议
+
+**测试策略需求:**
+- 三层测试:单元测试(Vitest)、集成测试(Playwright)、稳定性测试(20次连续运行)
+- 创建独立测试应用 `tests/test-app/` 使用 Vite + React
+- 测试应用提供真实的 `@d8d/shared-ui-components` 组件
+- Playwright 配置自动启动测试应用服务器
+- 单元测试覆盖率 ≥ 80%
+
+**常量定义需求:**
+- 超时常量:`DEFAULT_TIMEOUTS.static = 2000`, `async = 5000`, `networkIdle = 10000`
+- 选择器策略常量:`SELECTOR_STRATEGIES` 数组
+
+**文档需求:**
+- 完整的 JSDoc 注释格式
+- README 包含快速入门、安装说明、基本用法
+- 每个工具函数至少有 1 个实际使用示例
+- 迁移指南:从现有测试代码迁移到工具函数
+
+**遵循项目标准:**
+- 遵循 `docs/standards/testing-standards.md` 中的测试规范
+- 遵循 `docs/standards/web-ui-testing-standards.md` 中的 Web UI 测试规范
+- **遵循 `docs/standards/e2e-radix-testing.md` 中的 Radix UI E2E 测试标准**(核心标准文档)
+
+**从 E2E Radix UI 测试标准提取的详细需求:**
+
+**核心工具函数签名(必须按此实现):**
+```typescript
+// Radix UI Select 工具
+selectRadixOption(page: Page, label: string, value: string): Promise<void>
+selectRadixOptionAsync(page: Page, label: string, value: string, options?: AsyncSelectOptions): Promise<void>
+
+// 文件上传工具
+uploadFileToField(page: Page, selector: string, fileName: string): Promise<void>
+
+// 表单辅助工具
+fillMultiStepForm(page: Page, steps: FormStep[]): Promise<void>
+scrollToSection(page: Page, sectionName: string): Promise<void>
+
+// 动态列表工具
+addDynamicListItem(page: Page, itemType: string, data: Record<string, any>): Promise<void>
+deleteDynamicListItem(page: Page, itemType: string, index: number): Promise<void>
+
+// 对话框工具
+handleDialog(page: Page, action: 'confirm' | 'cancel' | 'close'): Promise<void>
+waitForDialogClosed(page: Page): Promise<void>
+cancelDialog(page: Page): Promise<void>
+```
+
+**DOM 结构理解需求:**
+- 理解 Radix UI Select 的典型 DOM 结构:`data-radix-select-trigger` 触发器,`role="listbox"` 选项列表,`role="option"` 单个选项
+- 理解 Radix UI Dialog 的 DOM 结构:`role="dialog"` 对话框容器
+- 理解数据属性:`data-value` 用于选项值,`data-state` 用于状态跟踪
+
+**选择器策略实现细节:**
+```typescript
+// 触发器选择器优先级
+const TRIGGER_SELECTORS = [
+  `[data-testid="${label}-trigger"]`,  // 最高优先级
+  `text="${label}"`,                     // 文本匹配
+  `[role="combobox"]`                    // 兜底
+];
+
+// 选项选择器优先级
+const OPTION_SELECTORS = [
+  `[role="option"][data-value="${value}"]`,  // data-testid + data-value
+  `[role="option"]:has-text("${value}")`      // 文本匹配兜底
+];
+```
+
+**性能标准(来自测试标准文档):**
+| 操作 | 目标时间 | 最大可接受时间 |
+|------|---------|---------------|
+| 静态 Select 选择 | < 1s | 2s |
+| 异步 Select 选择 | < 3s | 5s |
+| 文件上传 | < 2s | 5s |
+| 表单提交 | < 2s | 5s |
+
+**Fixtures 目录结构标准:**
+```
+web/tests/
+└── fixtures/
+    ├── images/        # 测试图片(身份证照片、残疾证照片等)
+    └── documents/     # 测试文档(PDF 等)
+```
+
+**错误消息格式标准:**
+```
+Error: Radix Select 选项 "xxx" 未找到
+  标签: 残疾类型
+  期望值: xxx
+  可用选项: 视力残疾, 听力残疾, 肢体残疾, 智力残疾
+
+Error: Radix Select 等待超时
+  标签: 省份
+  期望值: 广东省
+  超时时间: 5000ms
+  可能原因: 网络请求过慢或选项未加载
+```
+
+**测试稳定性最佳实践:**
+- 使用 Playwright 的 auto-waiting 机制,不使用 `waitForTimeout`
+- 优先使用 `data-testid` 选择器,谨慎使用文本选择器,避免使用不稳定的 CSS 类
+- 测试隔离:每个测试前清理数据,失败时截图
+- 明确的错误断言:使用具体的选择器和期望的文本内容
+
+**完整示例需求:**
+- 提供残疾人管理 E2E 测试作为完整示例
+- 演示静态 Select、异步 Select、文件上传、动态列表、对话框的综合使用
+- 展示与 Page Object 模式的集成方式
+
+### FR Coverage Map
+
+| FR 范围 | Epic | 描述 |
+|--------|------|------|
+| FR1-FR6 | Epic 1 | Radix UI Select 测试支持(静态和异步) |
+| FR7-FR24 | Epic 2 | 扩展工具集(文件上传、表单、列表、对话框) |
+| FR25-FR32 | Epic 1 | 包基础设施(package.json、类型定义、配置) |
+| FR33-FR40 | Epic 4 | 文档与开发者体验(README、示例、迁移指南) |
+| FR41-FR45 | Epic 3 | 质量与稳定性(残疾人管理验证、稳定性测试) |
+| FR46-FR50 | Epic 2 | 可扩展性设计(配置对象、版本升级兼容) |
+
+## Epic List
+
+### Epic 1: 测试工具包基础框架与 Select 支持
+
+**目标:** 测试开发者可以安装 `@d8d/e2e-test-utils` 包,立即使用 Select 工具测试 Radix UI Select 组件(最常用、最关键的测试场景)。
+
+**交付物:**
+- 完整的包结构和配置(package.json, tsconfig.json, vitest.config.ts)
+- `selectRadixOption()` 和 `selectRadixOptionAsync()` 函数
+- 类型定义和错误处理(E2ETestError, ErrorContext)
+- 选择器策略实现(testid → ARIA → text)
+- 基础文档(README 安装、快速入门)
+- 单元测试(Vitest)
+
+**FRs covered:** FR1-FR6, FR25-FR32
+
+**用户价值:**
+- 可以安装并立即使用 Select 工具
+- 无需深入了解 Radix UI DOM 结构
+- 自动处理时序问题
+- 清晰的错误提示
+
+---
+
+### Epic 2: 扩展工具集(文件上传、表单、列表、对话框)
+
+**目标:** 测试开发者可以使用完整的 6 个核心工具函数,覆盖所有常见 E2E 测试场景。
+
+**交付物:**
+- `uploadFileToField()` - 文件上传工具
+- `fillMultiStepForm()`, `scrollToSection()` - 表单辅助工具
+- `addDynamicListItem()`, `deleteDynamicListItem()` - 动态列表工具
+- `handleDialog()`, `waitForDialogClosed()`, `cancelDialog()` - 对话框工具
+- Fixtures 目录结构示例
+- 单元测试
+
+**FRs covered:** FR7-FR24, FR46-FR50
+
+**用户价值:**
+- 完整的工具集覆盖所有常见测试场景
+- 统一的 API 设计和错误处理
+- 支持可配置和扩展
+
+---
+
+### Epic 3: 在残疾人管理中验证工具包
+
+**目标:** 工具包在真实的残疾人管理 E2E 测试中验证,证明工具函数可用且稳定,提供完整的参考示例。
+
+**交付物:**
+- 残疾人管理 E2E 测试(使用工具函数)
+- 照片上传功能测试
+- 银行卡管理功能测试
+- 备注功能测试
+- 回访功能测试
+- 完整流程测试
+- 稳定性验证(20次连续运行 100% 通过)
+
+**FRs covered:** FR38, FR41-FR45
+
+**用户价值:**
+- 验证工具包的可用性和稳定性
+- 提供完整的参考示例
+- 证明工具包符合性能标准
+
+---
+
+### Epic 4: 完善文档与开发者体验
+
+**目标:** 测试开发者可以在 30 分钟内上手使用工具包,有完整的文档、示例和迁移指南。
+
+**交付物:**
+- 完整的 README(安装、快速入门、API 文档)
+- 每个工具函数的详细使用示例
+- 迁移指南(从现有测试代码到工具函数)
+- 常见问题和解决方案
+- 残疾人管理测试作为完整示例
+- JSDoc 完整注释
+
+**FRs covered:** FR33-FR40
+
+**用户价值:**
+- 快速上手(30 分钟内编写第一个测试)
+- 清晰的文档和示例
+- 降低学习曲线
+- 便于团队采用
+
+---
+
+## Epic 1: 测试工具包基础框架与 Select 支持
+
+**目标:** 测试开发者可以安装 `@d8d/e2e-test-utils` 包,立即使用 Select 工具测试 Radix UI Select 组件(最常用、最关键的测试场景)。
+
+---
+
+### Story 1.1: 创建包基础结构和配置
+
+作为测试开发者,
+我想要可以安装 `@d8d/e2e-test-utils` 包,
+以便在项目中使用测试工具函数。
+
+**验收标准:**
+
+**Given** 项目是 Monorepo 结构
+**When** 创建 `packages/e2e-test-utils/` 目录
+**Then** 目录结构包含 `src/`, `tests/`, `package.json`, `tsconfig.json`, `vitest.config.ts`
+**And** `package.json` 包含正确的包名、版本、peer dependencies(`@playwright/test`)
+**And** `tsconfig.json` 启用严格模式,目标 ES2020+
+**And** 可以通过 `pnpm add -D @d8d/e2e-test-utils@workspace:*` 安装
+
+---
+
+### Story 1.2: 实现类型定义和错误处理
+
+作为测试开发者,
+我想要工具包有完整的类型支持和统一的错误处理,
+以便获得类型安全和清晰的错误提示。
+
+**验收标准:**
+
+**Given** 包结构已创建
+**When** 实现 `src/types.ts`, `src/errors.ts`, `src/constants.ts`
+**Then** `types.ts` 导出 `BaseOptions`, `AsyncSelectOptions`, `FileUploadOptions` 等
+**And** `errors.ts` 导出 `E2ETestError` 类和 `ErrorContext` 接口
+**And** `constants.ts` 定义 `DEFAULT_TIMEOUTS`(static: 2000, async: 5000)
+**And** 所有类型使用 TypeScript 严格模式,无 `any` 类型
+
+---
+
+### Story 1.3: 实现静态 Select 工具函数
+
+作为测试开发者,
+我想要使用 `selectRadixOption()` 函数选择静态枚举型下拉框,
+以便无需理解 Radix UI DOM 结构就能编写测试。
+
+**验收标准:**
+
+**Given** 类型定义已创建
+**When** 实现 `src/radix-select.ts` 中的 `selectRadixOption()` 函数
+**Then** 函数签名:`selectRadixOption(page: Page, label: string, value: string): Promise<void>`
+**And** 选择器策略:`data-testid` → aria-label + role → text content
+**And** 自动处理点击触发器、等待选项列表、点击选项
+**And** 错误时抛出 `E2ETestError`,包含标签、期望值、可用选项
+**And** 操作在 2 秒内完成(NFR8)
+
+---
+
+### Story 1.4: 实现异步 Select 工具函数
+
+作为测试开发者,
+我想要使用 `selectRadixOptionAsync()` 函数选择异步加载的下拉框,
+以便测试省份、城市等动态加载的选项。
+
+**验收标准:**
+
+**Given** 静态 Select 函数已实现
+**When** 实现 `selectRadixOptionAsync(page, label, value, options?)` 函数
+**Then** 支持 `AsyncSelectOptions` 配置(timeout, waitForOption)
+**And** 使用 `waitForLoadState('networkidle')` 等待异步加载
+**And** 默认超时 5 秒,可配置
+**And** 超时时提供清晰错误消息(标签、期望值、超时时间、可能原因)
+
+---
+
+### Story 1.5: 创建主导出和基础文档
+
+作为测试开发者,
+我想要可以导入工具函数并查看快速入门文档,
+以便快速开始使用工具包。
+
+**验收标准:**
+
+**Given** Select 工具函数已实现
+**When** 创建 `src/index.ts` 和 `README.md`
+**Then** `index.ts` 导出所有公共函数和类型(tree-shakeable)
+**And** README 包含:安装说明、快速入门、Select 使用示例
+**And** 所有导出函数有完整的 JSDoc 注释
+**And** 可以 `import { selectRadixOption } from '@d8d/e2e-test-utils'`
+
+---
+
+### Story 1.6: Select 工具函数单元测试
+
+作为测试开发者,
+我想要 Select 工具函数有充分的单元测试,
+以便确保函数的正确性和稳定性。
+
+**验收标准:**
+
+**Given** Select 工具函数已实现
+**When** 创建 `tests/unit/radix-select.test.ts`
+**Then** 测试覆盖率 ≥ 80%(NFR29)
+**And** 测试用例包括:成功选择、选项不存在、超时、错误处理
+**And** 使用 Vitest 运行测试
+**And** 所有测试通过
+
+---
+
+## Epic 2: 扩展工具集(文件上传、表单、列表、对话框)
+
+**目标:** 测试开发者可以使用完整的 6 个核心工具函数,覆盖所有常见 E2E 测试场景。
+
+---
+
+### Story 2.1: 实现文件上传工具
+
+作为测试开发者,
+我想要使用 `uploadFileToField()` 函数上传文件,
+以便测试照片上传、文档上传等功能。
+
+**验收标准:**
+
+**Given** Epic 1 的类型定义已存在
+**When** 实现 `src/file-upload.ts` 中的 `uploadFileToField(page, selector, fileName)` 函数
+**Then** 函数从 fixtures 目录加载测试文件
+**And** 使用 Playwright 的 `setInputFiles()` API
+**And** 支持相对路径(相对于 fixtures 目录)
+**And** 错误时提供清晰消息(文件路径、选择器、失败原因)
+**And** 操作在 5 秒内完成(NFR9)
+
+---
+
+### Story 2.2: 实现表单辅助工具
+
+作为测试开发者,
+我想要使用 `fillMultiStepForm()` 和 `scrollToSection()` 函数,
+以便测试多步骤表单和滚动操作。
+
+**验收标准:**
+
+**Given** 类型定义已存在
+**When** 实现 `src/form-helper.ts` 中的表单辅助函数
+**Then** `fillMultiStepForm(page, steps)` 支持分步填写表单
+**And** `scrollToSection(page, sectionName)` 滚动到特定区域
+**And** 支持常见字段类型(文本、选择器、日期等)
+**And** 自动处理表单验证错误场景
+
+---
+
+### Story 2.3: 实现动态列表工具
+
+作为测试开发者,
+我想要使用 `addDynamicListItem()` 和 `deleteDynamicListItem()` 函数,
+以便测试银行卡管理、备注管理等动态列表功能。
+
+**验收标准:**
+
+**Given** 类型定义已存在
+**When** 实现 `src/dynamic-list.ts` 中的动态列表函数
+**Then** `addDynamicListItem(page, itemType, data)` 添加新列表项
+**And** `deleteDynamicListItem(page, itemType, index)` 删除指定索引的项
+**And** 支持不同类型列表项(银行卡、备注等)
+**And** 验证列表状态变化
+**And** 处理异步更新场景
+
+---
+
+### Story 2.4: 实现对话框操作工具
+
+作为测试开发者,
+我想要使用 `handleDialog()`, `waitForDialogClosed()`, `cancelDialog()` 函数,
+以便统一操作 Radix UI Dialog。
+
+**验收标准:**
+
+**Given** 类型定义已存在
+**When** 实现 `src/dialog.ts` 中的对话框操作函数
+**Then** `handleDialog(page, action)` 支持 confirm/cancel/close 操作
+**And** `waitForDialogClosed(page)` 等待对话框完全关闭
+**And** `cancelDialog(page)` 提供取消操作的快捷方式
+**And** 理解 Radix UI Dialog 的 DOM 结构(`role="dialog"`)
+**And** 等待对话框关闭后再继续后续操作
+
+---
+
+### Story 2.5: 更新主导出和 Fixtures 示例
+
+作为测试开发者,
+我想要可以导入所有新增的工具函数,
+并参考 Fixtures 目录结构示例。
+
+**验收标准:**
+
+**Given** 所有扩展工具函数已实现
+**When** 更新 `src/index.ts` 和创建 Fixtures 目录示例
+**Then** `index.ts` 导出所有新函数(uploadFileToField, fillMultiStepForm 等)
+**And** 创建 `tests/fixtures/` 目录结构示例
+**And** Fixtures 包含 `images/` 和 `documents/` 子目录
+**And** 提供示例测试文件(sample-id-card.jpg 等)
+**And** 所有函数有完整的 JSDoc 注释
+
+---
+
+### Story 2.6: 扩展工具集单元测试
+
+作为测试开发者,
+我想要所有扩展工具函数有充分的单元测试,
+以便确保函数的正确性和稳定性。
+
+**验收标准:**
+
+**Given** 扩展工具函数已实现
+**When** 创建 `tests/unit/` 下的测试文件
+**Then** 测试覆盖率 ≥ 80%(NFR29)
+**And** 测试文件包括:file-upload.test.ts, form-helper.test.ts, dynamic-list.test.ts, dialog.test.ts
+**And** 每个函数的成功和失败场景都有测试
+**And** 使用 Vitest 运行,所有测试通过
+
+---
+
+## Epic 3: 在残疾人管理中验证工具包
+
+**目标:** 工具包在真实的残疾人管理 E2E 测试中验证,证明工具函数可用且稳定,提供完整的参考示例。
+
+---
+
+### Story 3.1: 创建测试应用和集成测试基础设施
+
+作为测试开发者,
+我想要有一个独立的测试应用来验证工具函数,
+以便在真实环境中测试工具包的集成。
+
+**验收标准:**
+
+**Given** Epic 1-2 的工具函数已实现
+**When** 创建 `tests/test-app/` 独立测试应用
+**Then** 测试应用使用 Vite + React
+**And** 包含 Radix UI 组件页面(Select、Dialog、File Upload、Form、Dynamic List)
+**And** Playwright 配置自动启动测试应用服务器
+**And** 可以通过 `pnpm test` 运行集成测试
+
+---
+
+### Story 3.2: 照片上传功能测试
+
+作为测试开发者,
+我想要使用工具函数测试残疾人管理的照片上传功能,
+以便验证文件上传工具的可用性。
+
+**验收标准:**
+
+**Given** 测试基础设施已创建
+**When** 编写照片上传 E2E 测试
+**Then** 使用 `uploadFileToField()` 上传身份证照片
+**And** 使用 `uploadFileToField()` 上传残疾证照片
+**And** 验证文件上传成功
+**And** 测试覆盖多文件上传场景
+**And** 测试使用 fixtures 中的示例文件
+
+---
+
+### Story 3.3: 银行卡管理功能测试
+
+作为测试开发者,
+我想要使用工具函数测试残疾人管理的银行卡管理功能,
+以便验证动态列表和对话框工具的可用性。
+
+**验收标准:**
+
+**Given** 测试基础设施已创建
+**When** 编写银行卡管理 E2E 测试
+**Then** 使用 `handleDialog()` 打开添加银行卡对话框
+**And** 填写银行卡信息(银行名称、卡号、持卡人)
+**And** 使用 `addDynamicListItem()` 添加银行卡
+**And** 使用 `deleteDynamicListItem()` 删除银行卡
+**And** 验证列表状态变化
+
+---
+
+### Story 3.4: 备注和回访功能测试
+
+作为测试开发者,
+我想要使用工具函数测试残疾人管理的备注和回访功能,
+以便验证表单和动态列表工具的综合使用。
+
+**验收标准:**
+
+**Given** 测试基础设施已创建
+**When** 编写备注和回访 E2E 测试
+**Then** 使用 `fillMultiStepForm()` 填写备注表单
+**And** 使用 `scrollToSection()` 滚动到回访区域
+**And** 使用 `addDynamicListItem()` 添加备注
+**And** 验证表单提交和列表更新
+
+---
+
+### Story 3.5: 完整流程测试
+
+作为测试开发者,
+我想要有一个完整的残疾人管理流程测试,
+以便演示所有工具函数的综合使用。
+
+**验收标准:**
+
+**Given** 各功能测试已完成
+**When** 编写完整流程 E2E 测试
+**Then** 测试包含:基本信息填写(使用 `selectRadixOption` 选择静态和异步 Select)
+**And** 照片上传(使用 `uploadFileToField`)
+**And** 银行卡管理(使用 `handleDialog`, `addDynamicListItem`)
+**And** 备注添加(使用 `fillMultiStepForm`)
+**And** 表单提交和验证
+**And** 演示与 Page Object 模式的集成
+
+---
+
+### Story 3.6: 稳定性测试
+
+作为测试开发者,
+我想要有稳定性测试验证工具包的可靠性,
+以便确保工具函数连续运行 20 次 100% 通过。
+
+**验收标准:**
+
+**Given** 完整流程测试已编写
+**When** 创建 `tests/stability/repeat-run.spec.ts`
+**Then** 测试连续运行 20 次完整流程
+**And** 验证 100% 通过率(NFR1)
+**And** 测试执行时间符合性能标准(NFR8-NFR11)
+**And** 无 flaky 失败
+**And** 使用 Playwright 运行稳定性测试
+
+---
+
+## Epic 4: 完善文档与开发者体验
+
+**目标:** 测试开发者可以在 30 分钟内上手使用工具包,有完整的文档、示例和迁移指南。
+
+---
+
+### Story 4.1: 完善 README、API 文档和示例
+
+作为测试开发者,
+我想要有完整的 README 和 API 文档,
+以便快速上手使用工具包。
+
+**验收标准:**
+
+**Given** Epic 1-3 的所有功能已实现
+**When** 完善 `README.md` 和 API 文档
+**Then** README 包含:项目简介、安装说明、快速入门、API 文档
+**And** 每个工具函数都有完整的使用示例
+**And** 说明静态 Select 和异步 Select 的区别和使用场景
+**And** 包含迁移指南(从现有测试代码到工具函数)
+**And** 包含常见问题和解决方案
+**And** 残疾人管理测试作为完整示例
+**And** 所有函数有完整的 JSDoc 注释
+
+