---
stepsCompleted: ['step-01-validate-prerequisites', 'step-02-design-epics', 'step-03-create-stories', 'step-04-final-validation', 'revision-2025-01-10', 'step-01-revalidate-2025-01-10', 'revision-2026-01-12']
inputDocuments:
  - name: PRD - Web E2E 测试覆盖
    path: _bmad-output/planning-artifacts/prd.md
    type: prd
    loadedAt: '2026-01-10T11:30:00.000Z'
  - name: Architecture Decision Document
    path: _bmad-output/planning-artifacts/architecture.md
    type: architecture
    loadedAt: '2026-01-08T02:10:00.000Z'
revisedAt: '2026-01-12'
revisionNotes: '修订范围：根据修订后的 PRD，从"E2E测试工具包开发"更新为"Web E2E 测试覆盖"，业务测试为主，工具包为支持手段；增加 Epic C: 订单管理 E2E 测试；新增 Epic D/E/F: 小程序相关测试（用户管理、跨端同步、基础配置）'
---

# 188-179-template-6 - Epic Breakdown

## Overview

本文档提供了 188-179-template-6 的完整 Epic 和 Story 分解，将 PRD 和 Architecture 要求分解为可实现的 Story。

**项目定位（修订后）：** 为 Web 管理后台的业务功能建立完整的 E2E 测试覆盖，在测试过程中将通用模式抽象到 `@d8d/e2e-test-utils` 包中。

**Epic 组织：**
- **Epic A: 残疾人管理 E2E 测试** ✅ 已完成
- **Epic B: 区域管理 E2E 测试** 🔄 待开发
- **Epic C: 订单管理 E2E 测试** 📋 待开发
- **Epic D: 用户管理与小程序登录测试** 🆕 待开发
- **Epic E: 跨端数据同步测试** 🆕 待开发
- **Epic F: 基础配置管理测试** 🆕 待开发
- **Epic G: e2e-test-utils 包维护** 🌟 支持性任务

## 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 测试支持（静态和异步） |
| FR25-FR32 | Epic 1 | 包基础设施（package.json、类型定义、配置） |
| FR7-FR10 | Epic 3 | 文件上传测试支持（文件上传工具与验证） |
| FR11-FR15 | Epic 4 | 表单交互测试支持（表单工具与验证） |
| FR16-FR24 | Epic 5 | 列表和对话框测试支持（列表和对话框工具与验证） |
| FR41-FR45 | Epic 2, 3, 4, 5, 6, 8 | 质量与稳定性（各工具验证、全面验证、稳定性测试） |
| FR33-FR40 | Epic 7 | 文档与开发者体验（README、示例、迁移指南） |
| FR46-FR50 | Epic 3, 4, 5, 8 | 可扩展性（各工具的配置和扩展支持） |
| FR1-FR50 | Epic 8 | 区域管理 E2E 测试（复用现有工具，必要时扩展级联选择/树形结构工具） |

**Epic 规划变更说明（2026-01-11）：**
- Epic 1: ✅ 已完成（Select 工具基础框架）
- Epic 2: ✅ 已完成（在现有 E2E 测试中验证 Select 工具）
- Epic 3: 🆕 文件上传工具开发与验证（遵循 Epic 2 成功模式）
- Epic 4: 🆕 表单工具开发与验证（遵循 Epic 2 成功模式）
- Epic 5: 🆕 列表和对话框工具开发与验证（遵循 Epic 2 成功模式）
- Epic 6: 完整验证（残疾人管理）
- Epic 7: 文档与开发者体验
- Epic 8: 🆕 区域管理 E2E 测试 (Epic B - 业务测试 Epic)
- Epic 9: ✅ 已完成（残疾人管理完整 E2E 测试覆盖）
- Epic 10: 🆕 订单管理 E2E 测试 (Epic C - 业务测试 Epic)

**"先验证再扩展"策略：**
基于 Epic 2 的成功经验，每个工具都遵循"开发 → E2E 验证 → 稳定性验证"的模式：
- Epic 3: 文件上传工具（优先解决当前测试超时问题）
- Epic 4: 表单工具
- Epic 5: 列表和对话框工具

## Epic List

### Epic 1: 测试工具包基础框架与 Select 支持

**目标：** 测试开发者可以安装 `@d8d/e2e-test-utils` 包，立即使用 Select 工具测试 Radix UI Select 组件（最常用、最关键的测试场景）。

**状态:** ✅ Done

**交付物：**
- 完整的包结构和配置（package.json, tsconfig.json, vitest.config.ts）
- `selectRadixOption()` 和 `selectRadixOptionAsync()` 函数
- 类型定义和错误处理（E2ETestError, ErrorContext）
- 选择器策略实现（testid → ARIA → text）
- 基础文档（README 安装、快速入门）
- 单元测试（Vitest）

**FRs covered:** FR1-FR6, FR25-FR32

---

### Epic 2: 在现有 E2E 测试中验证 Select 工具

**目标：** 在 `web/tests/e2e/` 的残疾人管理测试中使用 Select 工具，验证工具在真实场景中的可用性和稳定性。

**状态:** ✅ Done

**交付物：**
- Select 工具在残疾人管理测试中的实际应用
- 5 处静态 Select 迁移（残疾类型、等级等）
- 2 处异步 Select 迁移（省份、城市）
- DOM 结构问题修复（listbox → option）

**FRs covered:** FR41-FR45 (部分)

**关键经验：**
- DOM 结构假设必须验证
- 真实 E2E 测试不可替代
- "先验证再扩展"策略有效

---

### Epic 3: 文件上传工具开发与验证

**目标：** 遵循 Epic 2 成功模式，开发文件上传工具并在真实 E2E 测试中验证，解决当前测试超时阻塞问题。

**状态:** 🆕 Backlog

**模式：** 工具开发 → 真实 E2E 测试验证 → 问题修复 → 稳定性验证

**交付物：**
- `uploadFileToField()` 文件上传工具
- 单元测试（Vitest）
- 在残疾人管理测试中验证（至少 3 处文件上传）
- 稳定性验证（10次连续运行）

**FRs covered:** FR7-FR10, FR46-FR50 (部分), FR41-FR45 (部分)

---

### Epic 4: 表单工具开发与验证

**目标：** 开发表单辅助工具并在真实 E2E 测试中验证。

**状态:** Backlog (等待 Epic 3 完成)

**模式：** 工具开发 → 真实 E2E 测试验证 → 稳定性验证

**交付物：**
- `fillMultiStepForm()`, `scrollToSection()` - 表单辅助工具
- 单元测试
- 在残疾人管理测试中验证
- 稳定性验证

**FRs covered:** FR11-FR15, FR46-FR50 (部分), FR41-FR45 (部分)

---

### Epic 5: 列表和对话框工具开发与验证

**目标：** 开发动态列表和对话框工具并在真实 E2E 测试中验证。

**状态:** Backlog (等待 Epic 4 完成)

**模式：** 工具开发 → 真实 E2E 测试验证 → 稳定性验证

**交付物：**
- `addDynamicListItem()`, `deleteDynamicListItem()` - 动态列表工具
- `handleDialog()`, `waitForDialogClosed()` - 对话框工具
- 单元测试
- 在残疾人管理测试中验证
- 稳定性验证

**FRs covered:** FR16-FR24, FR46-FR50 (部分), FR41-FR45 (部分)

---

### Epic 6: 完整验证（残疾人管理）

**目标：** 工具包在真实的残疾人管理 E2E 测试中完整验证，证明所有工具函数可用且稳定。

**状态:** Backlog (等待 Epic 5 完成)

**交付物：**
- 残疾人管理完整流程测试（使用所有工具）
- 稳定性验证（20次连续运行 100% 通过）

**FRs covered:** FR38, FR41-FR45

---

### Epic 7: 完善文档与开发者体验

**目标：** 测试开发者可以在 30 分钟内上手使用工具包，有完整的文档、示例和迁移指南。

**状态:** Backlog (等待 Epic 6 完成)

**交付物：**
- 完整的 README（安装、快速入门、API 文档）
- VS Code snippets
- 迁移指南

**FRs covered:** FR33-FR40

---

## 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: 在现有 E2E 测试中验证 Select 工具

**目标：** 在 `web/tests/e2e/` 的现有残疾人管理测试中使用 Select 工具，验证工具在真实场景中的可用性和稳定性，收集实际使用反馈，为后续工具设计提供指导。

**背景：** Epic 1 已完成 Select 工具的开发和单元测试，但尚未在真实 E2E 测试场景中验证。通过在现有测试中使用这些工具，我们可以：
1. 验证工具在实际业务场景中的可用性
2. 发现并修复潜在问题
3. 收集使用体验反馈，改进 API 设计
4. 为后续工具开发建立信心和经验

**范围：**
- ✅ 使用现有 `web/tests/e2e/` 测试基础设施
- ✅ 使用现有的残疾人管理测试场景
- ✅ 替换 Page Object 中现有的 Select 操作
- ❌ 不创建新的测试应用
- ❌ 不添加新功能（仅验证现有功能）

**依赖：**
- Epic 1: ✅ 已完成（Select 工具已开发）

**验收标准：**
1. Select 工具在至少 2 个真实 E2E 测试场景中使用
2. 所有测试连续运行 10 次，100% 通过率
3. 发现的问题已记录并修复（或列入待办）
4. 收集的使用反馈已整理

---

### Story 2.1: 在 web 目录安装 @d8d/e2e-test-utils

作为测试开发者，
我想要在 web 目录安装 `@d8d/e2e-test-utils` 包，
以便在 E2E 测试中使用 Select 工具。

**验收标准：**

**Given** Epic 1 已完成，`@d8d/e2e-test-utils` 包已构建
**When** 在 `web/package.json` 中添加 workspace 依赖
**Then** 可以在 `web/tests/e2e/` 中导入 Select 工具
**And** TypeScript 类型检查通过
**And** 运行时无依赖错误

**实现要点：**
- 使用 `pnpm add -D @d8d/e2e-test-utils@workspace:*` 安装
- 验证 `web/tests/e2e/` 中可以导入：`import { selectRadixOption } from '@d8d/e2e-test-utils'`

---

### Story 2.2: 使用 selectRadixOption 重写残疾类型选择

作为测试开发者，
我想要使用 `selectRadixOption()` 替换 Page Object 中的 Select 操作，
以便验证工具在静态 Select 场景中的可用性。

**验收标准：**

**Given** @d8d/e2e-test-utils 已安装
**When** 修改 `web/tests/e2e/pages/admin/disability-person.page.ts`
**Then** `fillBasicForm()` 中的残疾类型选择使用 `selectRadixOption()`
**And** `fillBasicForm()` 中的残疾等级选择使用 `selectRadixOption()`
**And** 移除原有的 `selectRadixOption()` 方法
**And** 测试通过，功能正常

**验证场景：**
- 残疾类型：视力残疾、听力残疾、肢体残疾、言语残疾等（静态选项）
- 残疾等级：一级、二级、三级、四级（静态选项）

---

### Story 2.3: 使用 selectRadixOptionAsync 重写省份/城市选择

作为测试开发者，
我想要使用 `selectRadixOptionAsync()` 处理异步加载的 Select，
以便验证工具在异步 Select 场景中的可用性。

**验收标准：**

**Given** @d8d/e2e-test-utils 已安装
**When** 修改 `web/tests/e2e/pages/admin/disability-person.page.ts`
**Then** `fillBasicForm()` 中的省份选择使用 `selectRadixOptionAsync()`
**And** `fillBasicForm()` 中的城市选择使用 `selectRadixOptionAsync()`
**And** 移除 `waitForTimeout(500)` 等待城市加载的 hack
**And** 测试通过，功能正常

**验证场景：**
- 省份选择（异步加载选项）
- 城市选择（根据省份动态加载）

**配置要点：**
- 使用 `waitForOption: true` 等待选项加载
- 使用合理的超时配置（5-10 秒）

---

### Story 2.4: 运行测试并收集问题和改进建议

作为测试开发者，
我想要运行使用新工具的测试并收集反馈，
以便发现潜在问题并改进工具。

**验收标准：**
1. 运行 `web/tests/e2e/specs/admin/disability-person-complete.spec.ts`
2. 记录所有问题（包括失败的测试、错误消息、使用体验）
3. 分类问题：工具 bug vs 使用错误 vs 改进建议
4. 整理成问题清单

**关注点：**
- 工具是否按预期工作？
- 错误消息是否清晰？
- API 是否简洁易用？
- 是否有性能问题？

---

### Story 2.5: 修复发现的问题

作为测试开发者，
我想要修复 Story 2.4 中发现的问题，
以便工具可以正常使用。

**验收标准：**
- 所有标记为"工具 bug"的问题已修复
- 所有测试通过
- 修复已记录到 story 文件

**优先级：**
- HIGH: 影响测试结果的问题（如选择失败、超时）
- MEDIUM: 影响开发体验的问题（如错误消息不清晰）
- LOW: 优化建议（如性能改进）

---

### Story 2.6: 稳定性验证

作为测试开发者，
我想要验证测试的稳定性，
以便确保工具可以可靠地使用。

**验收标准：**

**Given** 所有问题已修复
**When** 连续运行测试 10 次
**Then** 所有测试 100% 通过
**And** 无 flaky 失败
**And** 平均执行时间 < 5 分钟

**测试场景：**
- `pnpm test:e2e:chromium disability-person-complete.spec.ts` 运行 10 次

**成功标准：**
- 10/10 次通过 = 100% 稳定性 ✅
- 9/10 次通过 = 90% 稳定性，需要分析失败原因 ⚠️
- < 9/10 次通过 = 稳定性不足，需要修复 ❌

**Epic 2 状态:** ✅ Done
**回顾文档:** `_bmad-output/implementation-artifacts/epic-2-retrospective.md`

---

## Epic 3: 文件上传工具开发与验证

**目标：** 遵循 Epic 2 的成功模式，开发文件上传工具并在 `web/tests/e2e/` 的真实测试中验证，解决当前测试超时阻塞问题。

**背景：**
- Epic 1 和 Epic 2 已证明"先验证再扩展"策略的有效性
- 当前残疾人管理测试在文件上传阶段超时（60秒），阻塞了完整验证
- 优先开发文件上传工具，解决当前阻塞问题

**范围：**
- ✅ 开发文件上传工具 `uploadFileToField()`
- ✅ 编写单元测试（Vitest）
- ✅ 在 `web/tests/e2e/` 中验证工具
- ✅ 收集反馈并修复问题
- ✅ 稳定性验证（10次连续运行）

**模式：** 工具开发 → 真实 E2E 测试验证 → 问题修复 → 稳定性验证

**依赖：**
- Epic 1: ✅ 已完成（类型定义、错误处理、基础设施）

**验收标准：**
1. 文件上传工具在至少 3 处真实 E2E 测试中使用
2. 所有测试连续运行 10 次，100% 通过率
3. 测试超时问题已解决

---

### Story 3.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）
**And** 配置对象继承 `BaseOptions`

**函数签名：**
```typescript
export async function uploadFileToField(
  page: Page,
  selector: string,
  fileName: string,
  options?: FileUploadOptions
): Promise<void>

export interface FileUploadOptions extends BaseOptions {
  /** fixtures 目录路径，默认为 'tests/fixtures' */
  fixturesDir?: string;
  /** 是否等待上传完成，默认为 true */
  waitForUpload?: boolean;
}
```

**参考架构决策：**
- 遵循 `docs/standards/e2e-radix-testing.md` 中的文件上传规范
- 使用 `DEFAULT_TIMEOUTS` 常量定义超时
- 错误处理使用 `E2ETestError` 和 `ErrorContext`

---

### Story 3.2: 编写文件上传单元测试

作为测试开发者，
我想要文件上传工具有充分的单元测试，
以便确保函数的正确性和稳定性。

**验收标准：**

**Given** 文件上传工具函数已实现
**When** 创建 `tests/unit/file-upload.test.ts`
**Then** 测试覆盖率 ≥ 80%（NFR29）
**And** 测试用例包括：成功上传、文件不存在、选择器无效、超时
**And** 使用 Vitest 运行测试
**And** 所有测试通过

**⚠️ Epic 2 关键经验应用：**
- 单元测试无法发现真实 DOM 问题，但可验证基本逻辑
- 必须添加集成测试使用真实 Playwright API
- 使用 Playwright Page mock 验证文件上传逻辑

---

### Story 3.3: 在 web/tests/e2e 中验证文件上传工具

作为测试开发者，
我想要在 `web/tests/e2e/` 的残疾人管理测试中使用文件上传工具，
以便验证工具在真实场景中的可用性。

**验收标准：**

**Given** 文件上传工具和单元测试已完成
**When** 在 `web/tests/e2e/specs/admin/disability-person-complete.spec.ts` 中使用工具
**Then** 至少迁移 3 处文件上传操作（身份证照片、残疾证照片）
**And** 移除原有的自定义文件上传方法
**And** 测试在真实浏览器中通过
**And** 无测试超时问题

**验证场景：**
- 身份证照片上传（正面、反面）
- 残疾证照片上传
- 个人照片上传（如果有）

**参考 Epic 2.2-2.3 的迁移模式：**
- 渐进式迁移：先迁移部分测试
- 保留原有方法作为 TODO 备份
- 验证通过后再完全替换

---

### Story 3.4: 收集反馈并修复问题

作为测试开发者，
我想要运行使用文件上传工具的测试并收集反馈，
以便发现潜在问题并改进工具。

**验收标准：**

**Given** 文件上传工具已在真实测试中使用
**When** 运行完整的 E2E 测试套件
**Then** 记录所有问题（失败的测试、错误消息、使用体验）
**Then** 分类问题：工具 bug vs 使用错误 vs 改进建议
**And** 所有标记为"工具 bug"的问题已修复
**And** 测试连续运行 5 次通过
**And** 无 flaky 失败

**优先级：**
- HIGH: 影响测试结果的问题（如上传失败、超时）
- MEDIUM: 影响开发体验的问题（如错误消息不清晰）
- LOW: 优化建议（如性能改进）

---

### Story 3.5: 支持多文件同时上传

作为测试开发者，
我想要 `uploadFileToField()` 函数支持一次上传多个文件，
以便测试前端 `<input type="file" multiple>` 的多文件选择功能。

**验收标准：**

**Given** `uploadFileToField()` 函数已实现（单文件上传）
**When** 扩展函数支持多文件上传
**Then** 函数接受文件名数组或字符串
**And** 使用 Playwright 的 `setInputFiles([path1, path2, ...])` API
**And** 支持相对路径数组（相对于 fixtures 目录）
**And** 错误时提供清晰消息（包含所有文件路径）
**And** 保持向后兼容（单文件上传仍然工作）

**函数签名扩展：**
```typescript
// 支持单文件（向后兼容）
uploadFileToField(page, selector, fileName, options?): Promise<void>

// 支持多文件
uploadFileToField(page, selector, fileNames: string[], options?): Promise<void>
```

**实现要点：**
- 使用函数重载或联合类型支持两种签名
- 多文件时调用 `setInputFiles(filePathArray)`
- 保持所有文件路径验证逻辑
- 错误消息包含所有文件路径

**测试用例：**
- 上传 3 张照片（身份证、残疾证正反面）
- 混合格式（JPG、PNG、WEBP）
- 一次性选择与分次上传的结果一致性验证

---

### Story 3.6: 文件上传稳定性验证

作为测试开发者，
我想要验证文件上传工具的稳定性，
以便确保工具可以可靠地使用。

**验收标准：**

**Given** 所有问题已修复
**When** 连续运行文件上传相关测试 10 次
**Then** 所有测试 100% 通过
**And** 无超时失败
**And** 平均执行时间 ≤ 5 秒/文件

**测试场景：**
- `pnpm test:e2e:chromium disability-person-complete.spec.ts` 运行 10 次
- 重点验证文件上传相关步骤

**成功标准：**
- 10/10 次通过 = 100% 稳定性 ✅
- 9/10 次通过 = 90% 稳定性，需要分析失败原因 ⚠️
- < 9/10 次通过 = 稳定性不足，需要修复 ❌

**Epic 3 回顾：**
- 如果 100% 通过，可以进入 Epic 4
- 如果 < 100%，需要分析并修复问题后再验证

---

## Epic 4: 表单工具开发与验证

**目标：** 开发表单辅助工具并在 `web/tests/e2e/` 的真实测试中验证。

**说明：** 遵循 Epic 2 和 Epic 3 的成功模式。

**依赖：** Epic 3 完成

**模式：** 工具开发 → 真实 E2E 测试验证 → 稳定性验证

---

### Story 4.1: 开发表单辅助工具函数

作为测试开发者，
我想要使用 `fillMultiStepForm()` 和 `scrollToSection()` 函数，
以便测试多步骤表单和滚动操作。

**验收标准：**

**Given** 类型定义已存在
**When** 实现 `src/form-helper.ts` 中的表单辅助函数
**Then** `fillMultiStepForm(page, steps)` 支持分步填写表单
**And** `scrollToSection(page, sectionName)` 滚动到特定区域
**And** 支持常见字段类型（文本、选择器、日期等）
**And** 自动处理表单验证错误场景

---

### Story 4.2: 编写表单工具单元测试

作为测试开发者，
我想要表单工具有充分的单元测试，
以便确保函数的正确性和稳定性。

**验收标准：**

**Given** 表单辅助工具函数已实现
**When** 创建 `tests/unit/form-helper.test.ts`
**Then** 测试覆盖率 ≥ 80%（NFR29）
**And** 测试用例包括：成功填写、滚动操作、验证错误等
**And** 使用 Vitest 运行测试
**And** 所有测试通过

---

### Story 4.3: 在 web/tests/e2e 中验证表单工具

作为测试开发者，
我想要在残疾人管理测试中使用表单辅助工具，
以便验证工具在真实场景中的可用性。

**验收标准：**

**Given** 表单工具和单元测试已完成
**When** 在残疾人管理测试中使用工具
**Then** 验证多步骤表单填写
**And** 验证滚动操作
**And** 测试在真实浏览器中通过

---

### Story 4.4: 表单稳定性验证

作为测试开发者，
我想要验证表单工具的稳定性，
以便确保工具可以可靠地使用。

**验收标准：**

**Given** 所有问题已修复
**When** 连续运行表单相关测试 10 次
**Then** 所有测试 100% 通过

---

## Epic 5: 列表和对话框工具开发与验证

**目标：** 开发动态列表和对话框工具并在 `web/tests/e2e/` 的真实测试中验证。

**说明：** 遵循 Epic 2-4 的成功模式。

**依赖：** Epic 4 完成

**模式：** 工具开发 → 真实 E2E 测试验证 → 稳定性验证

---

### Story 5.1: 开发动态列表和对话框工具函数

作为测试开发者，
我想要使用 `addDynamicListItem()`、`deleteDynamicListItem()` 和对话框工具，
以便测试银行卡管理、备注管理等动态列表功能。

**验收标准：**

**Given** 类型定义已存在
**When** 实现 `src/dynamic-list.ts` 和 `src/dialog.ts` 中的函数
**Then** `addDynamicListItem(page, itemType, data)` 添加新列表项
**And** `deleteDynamicListItem(page, itemType, index)` 删除指定索引的项
**And** `handleDialog(page, action)` 支持 confirm/cancel/close 操作
**And** `waitForDialogClosed(page)` 等待对话框完全关闭
**And** 支持不同类型列表项（银行卡、备注等）

---

### Story 5.2: 编写列表和对话框单元测试

作为测试开发者，
我想要列表和对话框工具有充分的单元测试，
以便确保函数的正确性和稳定性。

**验收标准：**

**Given** 列表和对话框工具函数已实现
**When** 创建 `tests/unit/dynamic-list.test.ts` 和 `dialog.test.ts`
**Then** 测试覆盖率 ≥ 80%（NFR29）
**And** 测试用例包括：添加、删除、打开/关闭对话框等
**And** 使用 Vitest 运行测试
**And** 所有测试通过

---

### Story 5.3: 在 web/tests/e2e 中验证列表和对话框工具

作为测试开发者，
我想要在残疾人管理测试中使用列表和对话框工具，
以便验证工具在真实场景中的可用性。

**验收标准：**

**Given** 列表和对话框工具及单元测试已完成
**When** 在残疾人管理测试中使用工具
**Then** 验证银行卡管理（添加、删除）
**And** 验证备注管理
**And** 测试在真实浏览器中通过

---

### Story 5.4: 列表和对话框稳定性验证

作为测试开发者，
我想要验证列表和对话框工具的稳定性，
以便确保工具可以可靠地使用。

**验收标准：**

**Given** 所有问题已修复
**When** 连续运行列表和对话框相关测试 10 次
**Then** 所有测试 100% 通过

---

## Epic 6: 完整验证（残疾人管理）

**目标：** 工具包在真实的残疾人管理 E2E 测试中完整验证，证明所有工具函数可用且稳定。

**依赖：** Epic 5 完成

---

### Story 6.1: 完整流程测试

作为测试开发者，
我想要在残疾人管理完整流程测试中使用所有工具，
以便演示所有工具函数的综合使用。

**验收标准：**

**Given** Epic 1-5 的所有工具已实现并验证
**When** 确保 `disability-person-complete.spec.ts` 使用所有工具
**Then** 基本信息：使用 `selectRadixOption` 和 `selectRadixOptionAsync`
**And** 照片上传：使用 `uploadFileToField` (来自 Epic 3)
**And** 表单操作：使用 `fillMultiStepForm`, `scrollToSection` (来自 Epic 4)
**And** 银行卡管理：使用 `handleDialog`, `addDynamicListItem`, `deleteDynamicListItem` (来自 Epic 5)
**And** 备注添加：使用 `addDynamicListItem` (来自 Epic 5)
**And** 所有测试通过

---

### Story 6.2: 稳定性测试

作为测试开发者，
我想要有稳定性测试验证工具包的可靠性，
以便确保工具函数连续运行 20 次 100% 通过。

**验收标准：**

**Given** 完整流程测试已编写
**When** 创建稳定性测试或运行现有测试 20 次
**Then** 测试连续运行 20 次完整流程
**And** 验证 100% 通过率（NFR1）
**And** 测试执行时间符合性能标准（NFR8-NFR11）
**And** 无 flaky 失败
**And** 使用 Playwright 运行稳定性测试

---

## Epic 7: 完善文档与开发者体验

**目标：** 测试开发者可以在 30 分钟内上手使用工具包，有完整的文档、示例和迁移指南。

**依赖：** Epic 6 完成

---

### Story 7.1: 完善 README、API 文档和示例

作为测试开发者，
我想要有完整的 README 和 API 文档，
以便快速上手使用工具包。

**验收标准：**

**Given** Epic 1-6 的所有功能已实现
**When** 完善 `README.md` 和 API 文档
**Then** README 包含：项目简介、安装说明、快速入门、API 文档
**And** 每个工具函数都有完整的使用示例
**And** 说明静态 Select 和异步 Select 的区别和使用场景
**And** 包含迁移指南（从现有测试代码到工具函数）
**And** 包含常见问题和解决方案
**And** 残疾人管理测试作为完整示例
**And** 所有函数有完整的 JSDoc 注释

---

### Story 7.2: VS Code Snippets 和开发体验

作为测试开发者，
我想要有 VS Code 代码片段，
以便加速测试开发。

**验收标准：**

**Given** README 和 API 文档已完成
**When** 创建 VS Code snippets 配置
**Then** 提供常用代码片段（selectRadixOption, uploadFileToField 等）
**And** 片段有清晰的触发词和描述
**And** 文档说明如何安装和使用 snippets
**And** 开发者可以在 30 分钟内使用工具包编写第一个测试

---

## Epic 8: 区域管理 E2E 测试 (Epic B)

**目标：** 测试开发者可以为区域管理功能编写完整的 E2E 测试，验证省/市/区/街道的添加、编辑、删除和级联选择功能。

**业务分组：** Epic B（业务测试 Epic）

**背景：**
- Epic A（残疾人管理）已完成 Select 工具在真实 E2E 测试中的验证
- 区域管理是下一个需要建立 E2E 测试覆盖的核心业务模块
- 涉及四级级联选择（省/市/区/街道）和树形结构展示
- 可能需要扩展现有工具或新增专用工具

**范围：**
- ✅ 区域列表查看测试
- ✅ 添加区域测试（省/市/区/街道）
- ✅ 编辑区域测试
- ✅ 删除区域测试
- ✅ 级联选择测试（省市区街道四级联动）
- ✅ 完整流程测试
- ✅ 稳定性验证（10次连续运行）
- ❌ 不修改后端业务逻辑
- ❌ 不修改前端 UI 组件

**模式：** 业务测试为主，工具包支持为辅（遵循 Epic A 成功模式）

**依赖：**
- Epic 1: ✅ 已完成（Select 工具基础框架）
- Epic 2: ✅ 已完成（Select 工具在真实 E2E 测试中验证）

**验收标准：**
1. 区域管理核心功能有完整的 E2E 测试覆盖
2. 所有测试连续运行 10 次，100% 通过率
3. 必要时扩展 e2e-test-utils 工具包（级联选择、树形结构等）
4. 测试可作为其他业务模块 E2E 测试的参考

**交付物：**
- 区域列表 Page Object
- 添加区域测试用例
- 编辑区域测试用例
- 删除区域测试用例
- 级联选择测试用例
- 稳定性验证报告
- 工具包扩展文档（如有）

**FRs covered:** FR1-FR50（复用现有工具，必要时扩展）

---

### Story 8.1: 创建区域管理 Page Object

作为测试开发者，
我想要创建区域管理的 Page Object，
以便组织区域管理相关的页面元素和操作。

**验收标准：**

**Given** Epic 2 的 Page Object 模式已验证
**When** 创建 `web/tests/e2e/pages/admin/region-management.page.ts`
**Then** 定义区域列表页面的选择器和操作方法
**And** 定义添加区域对话框的选择器和操作方法
**And** 定义编辑区域对话框的选择器和操作方法
**And** 遵循现有 Page Object 设计模式
**And** 所有方法有完整的 TypeScript 类型定义

**参考：**
- `web/tests/e2e/pages/admin/disability-person.page.ts` 作为参考
- 遵循项目的 Page Object 设计模式

---

### Story 8.2: 编写区域列表查看测试

作为测试开发者，
我想要编写区域列表查看的 E2E 测试，
以便验证区域列表的基本功能和数据展示。

**验收标准：**

**Given** 区域管理 Page Object 已创建
**When** 编写区域列表查看测试用例
**Then** 验证区域列表按预期加载
**And** 验证区域数据的正确展示（名称、层级、状态等）
**And** 验证分页功能（如适用）
**And** 验证搜索功能（如适用）
**And** 测试在真实浏览器中通过

---

### Story 8.3: 编写添加区域测试

作为测试开发者，
我想要编写添加区域的 E2E 测试，
以便验证省/市/区/街道的添加功能。

**验收标准：**

**Given** 区域列表查看测试已通过
**When** 编写添加区域测试用例
**Then** 验证添加省级区域的流程
**And** 验证添加市级区域的流程（需选择父级省份）
**And** 验证添加区级区域的流程（需选择父级城市）
**And** 验证添加街道级区域的流程（需选择父级区域）
**And** 使用 `selectRadixOption` 或 `selectRadixOptionAsync` 选择父级区域
**And** 验证添加成功后列表中显示新区域
**And** 测试在真实浏览器中通过

**级联选择测试点：**
- 选择省份后，市级下拉框的选项是否正确过滤
- 选择城市后，区级下拉框的选项是否正确过滤
- 选择区域后，街道下拉框的选项是否正确过滤

---

### Story 8.4: 编写编辑区域测试

作为测试开发者，
我想要编写编辑区域的 E2E 测试，
以便验证区域信息的修改功能。

**验收标准：**

**Given** 添加区域测试已通过
**When** 编写编辑区域测试用例
**Then** 验证编辑区域名称的流程
**And** 验证修改区域状态的流程（如启用/禁用）
**And** 验证编辑后列表中正确显示更新后的信息
**And** 验证必填字段的验证规则
**And** 测试在真实浏览器中通过

---

### Story 8.5: 编写删除区域测试

作为测试开发者，
我想要编写删除区域的 E2E 测试，
以便验证区域的删除功能和相关约束。

**验收标准：**

**Given** 编辑区域测试已通过
**When** 编写删除区域测试用例
**Then** 验证删除无子级区域的流程
**And** 验证删除有子级区域时的错误提示
**And** 验证删除确认对话框的正确操作
**And** 验证删除成功后列表中不再显示该区域
**And** 测试在真实浏览器中通过

---

### Story 8.6: 编写级联选择完整流程测试

作为测试开发者，
我想要编写完整的四级级联选择测试，
以便验证省/市/区/街道联动的完整场景。

**验收标准：**

**Given** 单独的区域操作测试已通过
**When** 编写完整的级联选择流程测试
**Then** 从选择省份开始，依次选择市、区、街道
**And** 验证每级选择后，下一级选项正确加载
**And** 验证上级变更时，下级选择被清空
**And** 验证完整的添加流程（省份→城市→区域→街道）
**And** 测试在真实浏览器中通过

**工具需求评估：**
- 评估现有 `selectRadixOptionAsync` 是否满足需求
- 如不满足，记录到 Story 8.8 进行工具扩展

---

### Story 8.7: 运行测试并收集问题和改进建议

作为测试开发者，
我想要运行区域管理测试并收集反馈，
以便发现潜在问题并改进测试或工具。

**验收标准：**

**Given** 所有区域管理测试用例已编写
**When** 运行完整的区域管理 E2E 测试套件
**Then** 记录所有问题（失败的测试、错误消息、使用体验）
**Then** 分类问题：业务逻辑 bug vs 测试代码问题 vs 工具不足
**And** 整理成问题清单
**And** 识别是否需要扩展 e2e-test-utils 工具包

**关注点：**
- 现有 Select 工具是否满足级联选择需求？
- 是否需要级联选择专用工具？
- 是否需要树形结构操作工具？
- 错误消息是否清晰？

---

### Story 8.8: 扩展工具包（如需要）

作为测试开发者，
我想要根据 Story 8.7 的发现扩展 e2e-test-utils 工具包，
以便更好地支持区域管理等业务模块的测试。

**验收标准：**

**Given** Story 8.7 已识别工具扩展需求
**When** 实现必要的工具扩展
**Then** 如需级联选择工具：实现 `selectCascadeOptions()` 函数
**And** 如需树形结构工具：实现 `selectTreeNode()` 函数
**And** 编写工具函数的单元测试
**And** 在区域管理测试中验证新工具
**And** 更新工具包文档

**可能的工具扩展：**
```typescript
// 级联选择工具（示例）
export async function selectCascadeOptions(
  page: Page,
  levels: Array<{label: string, value: string}>
): Promise<void>

// 树形结构选择工具（示例）
export async function selectTreeNode(
  page: Page,
  treeLabel: string,
  nodePath: string[]
): Promise<void>
```

**依赖：**
- 仅在 Story 8.7 确认需要时才执行此 Story
- 如无需扩展，此 Story 可标记为 N/A

---

### Story 8.9: 区域管理稳定性验证

作为测试开发者，
我想要验证区域管理测试的稳定性，
以便确保测试可以可靠地使用。

**验收标准：**

**Given** 所有问题已修复（包括工具扩展）
**When** 连续运行区域管理相关测试 10 次
**Then** 所有测试 100% 通过
**And** 无 flaky 失败
**And** 平均执行时间符合预期

**测试场景：**
- `pnpm test:e2e:chromium region-management.spec.ts` 运行 10 次

**成功标准：**
- 10/10 次通过 = 100% 稳定性 ✅
- 9/10 次通过 = 90% 稳定性，需要分析失败原因 ⚠️
- < 9/10 次通过 = 稳定性不足，需要修复 ❌

**Epic 8 回顾：**
- 如果 100% 通过，Epic B 完成，可进入下一个业务模块
- 如果 < 100%，需要分析并修复问题后再验证

---

## Epic 9: 残疾人管理完整 E2E 测试覆盖（含并行隔离）

**目标：** 为残疾人管理功能编写完整的、真正验证业务功能的 E2E 测试，并确保测试可以与未来的区域管理测试并行运行。

**背景：**
- Epic 1-3 已完成基础工具开发（Select、文件上传、级联选择）
- 现有 `disability-person-complete.spec.ts` 只是组件验证，没有真正测试业务功能
- 需要补充完整的业务功能测试（新增、编辑、删除、查看）
- 必须确保测试隔离，支持与区域管理测试并行运行

**范围：**
- ✅ 编写真实的业务功能测试（非组件验证）
- ✅ 测试数据隔离（每个测试创建/清理自己的数据）
- ✅ 支持并行执行（与区域管理测试同时运行）
- ❌ 不开发新工具（复用现有工具，按需扩展）
- ❌ 不修改业务逻辑

**模式：** 业务测试优先，工具按需扩展（遵循新 PRD 方向）

**依赖：**
- Epic 1: ✅ 已完成（Select 工具）
- Epic 2: ✅ 已完成（Select 工具验证）
- Epic 3: ✅ 已完成（文件上传工具、级联选择工具）

**验收标准：**
1. 所有业务功能有完整的 E2E 测试覆盖
2. 测试连续运行 10 次，100% 通过率
3. 测试可以与区域管理测试并行运行（无数据冲突）

**FRs covered:** FR7-FR10（文件上传）、FR41-FR45（测试质量和稳定性）

**业务功能覆盖清单：**

| 业务功能 | 当前状态 | 目标状态 | 测试场景数 |
|---------|---------|---------|-----------|
| **照片上传** | 组件验证 | 真实上传测试 | 5 |
| **银行卡管理** | 组件验证 | 增删改查测试 | 4 |
| **备注管理** | 组件验证 | 增删改测试 | 3 |
| **回访记录管理** | 组件验证 | 增删改查测试 | 4 |
| **残疾人信息** | 基础测试 | 完整 CRUD | 6 |
| **完整流程** | 组件验证 | 端到端测试 | 3 |
| **并行隔离** | 未验证 | 验证通过 | 1 |

**总计：** 26 个测试场景

---

### Story 9.1: 照片上传功能完整测试

作为测试开发者，
我想要编写照片上传功能的完整测试，
以便验证照片上传的真实业务逻辑。

**验收标准：**

**Given** 文件上传工具 (Epic 3) 已完成
**When** 编写照片上传功能测试
**Then** 包含以下测试场景：

1. **单张照片上传**
   - 上传身份证正面
   - 上传身份证反面
   - 上传残疾证照片
   - 验证预览显示正确

2. **多张照片上传**
   - 同时上传身份证正反面
   - 同时上传多张照片
   - 验证所有照片都显示

3. **照片格式支持**
   - JPG 格式上传
   - PNG 格式上传
   - WEBP 格式上传

4. **照片删除**
   - 删除已上传的照片
   - 验证删除后预览消失

5. **照片大小限制**
   - 验证超大文件的处理
   - 验证不支持的格式

**测试文件:** `web/tests/e2e/specs/admin/disability-person-photo.spec.ts`

---

### Story 9.2: 银行卡管理功能测试

作为测试开发者，
我想要编写银行卡管理功能的测试，
以便验证银行卡的添加、编辑、删除功能。

**验收标准：**

**Given** 残疾人管理 Page Object 已存在
**When** 编写银行卡管理测试
**Then** 包含以下测试场景：

1. **添加银行卡**
   - 添加单张银行卡
   - 验证银行卡信息保存正确
   - 验证银行卡列表显示

2. **编辑银行卡**
   - 修改银行卡信息
   - 验证修改后数据更新

3. **删除银行卡**
   - 删除单张银行卡
   - 验证删除后列表更新

4. **多张银行卡管理**
   - 添加多张银行卡
   - 验证列表顺序
   - 验证默认银行卡设置

**测试文件:** `web/tests/e2e/specs/admin/disability-person-bankcard.spec.ts`

---

### Story 9.3: 备注管理功能测试

作为测试开发者，
我想要编写备注管理功能的测试，
以便验证备注的添加、修改、删除功能。

**验收标准：**

**Given** 残疾人管理 Page Object 已存在
**When** 编写备注管理测试
**Then** 包含以下测试场景：

1. **添加备注**
   - 添加简单备注
   - 添加长文本备注
   - 验证备注保存成功

2. **修改备注**
   - 编辑已有备注
   - 验证修改后内容更新

3. **删除备注**
   - 删除备注
   - 验证删除后备注消失

**测试文件:** `web/tests/e2e/specs/admin/disability-person-note.spec.ts`

---

### Story 9.4: 回访记录管理测试

作为测试开发者，
我想要编写回访记录管理的测试，
以便验证回访记录的创建、查看、编辑功能。

**验收标准：**

**Given** 残疾人管理 Page Object 已存在
**When** 编写回访记录测试
**Then** 包含以下测试场景：

1. **创建回访记录**
   - 创建电话回访记录
   - 创建上门回访记录
   - 验证记录保存成功

2. **查看回访历史**
   - 查看残疾人的所有回访记录
   - 验证记录按时间排序

3. **编辑回访记录**
   - 修改回访内容
   - 验证修改后内容更新

4. **回访记录状态管理**
   - 标记回访为已完成
   - 验证状态更新

**测试文件:** `web/tests/e2e/specs/admin/disability-person-visit.spec.ts`

---

### Story 9.5: 完整流程测试（CRUD）

作为测试开发者，
我想要编写残疾人信息的完整 CRUD 测试，
以便验证整个业务流程的正确性。

**验收标准：**

**Given** 所有子功能测试已完成
**When** 编写完整流程测试
**Then** 包含以下测试场景：

1. **新增残疾人完整流程**
   - 填写基本信息
   - 上传照片
   - 添加银行卡
   - 添加备注
   - 提交并验证保存

2. **编辑残疾人信息**
   - 打开已有残疾人信息
   - 修改基本信息
   - 更新照片
   - 保存并验证更新

3. **删除残疾人**
   - 删除残疾人记录
   - 验证删除后列表不显示
   - 验证关联数据清理

4. **查看残疾人详情**
   - 打开详情页面
   - 验证所有信息显示完整

5. **列表查询与筛选**
   - 按姓名搜索
   - 按残疾类型筛选
   - 验证筛选结果

6. **数据导出**
   - 导出残疾人列表
   - 验证导出数据正确性

**测试文件:** `web/tests/e2e/specs/admin/disability-person-crud.spec.ts`

---

### Story 9.6: 测试隔离与并行执行验证

作为测试开发者，
我想要确保测试隔离和并行执行，
以便残疾人管理和区域管理测试可以同时运行。

**验收标准：**

**Given** 所有业务测试已完成
**When** 验证测试隔离和并行执行
**Then** 包含以下验证：

1. **数据隔离策略**
   - 每个测试使用唯一 ID（时间戳）
   - 测试执行后清理数据
   - 使用事务或回滚（如可能）

2. **并行执行验证**
   - 同时运行残疾人和区域测试（模拟）
   - 验证无数据冲突
   - 验证无测试相互影响

3. **测试顺序独立性**
   - 单独运行每个测试
   - 随机顺序运行测试
   - 验证结果一致

**测试隔离示例：**
```typescript
test.beforeEach(async ({ adminLoginPage, disabilityPersonPage }) => {
  // 登录（全局状态，需谨慎）
  await adminLoginPage.goto();
  await adminLoginPage.login('admin', 'admin123');
});

test.afterEach(async ({ disabilityPersonPage }) => {
  // 清理测试数据
  await disabilityPersonPage.deleteTestData();
});

test('应该成功创建残疾人', async ({ disabilityPersonPage }) => {
  // 使用时间戳确保数据唯一
  const timestamp = Date.now();
  const uniqueId = `test_${timestamp}`;

  await disabilityPersonPage.create({
    name: uniqueId,
    idCard: generateUniqueIdCard(timestamp),
    // ...
  });
});
```

**验证命令：**
```bash
# 并行运行测试（使用 4 个 worker）
cd web
pnpm test:e2e:chromium --workers=4

# 验证测试顺序独立
pnpm test:e2e:chromium --shuffle
```

---

### Story 9.7: 稳定性验证（10 次连续运行）

作为测试开发者，
我想要验证所有测试的稳定性，
以便确保测试可以可靠地运行。

**验收标准：**

**Given** 所有业务测试已完成并隔离
**When** 连续运行测试 10 次
**Then** 验收标准如下：

1. **测试通过率 100%**
   - 10/10 次运行全部通过
   - 无 flaky 失败
   - 无超时失败

2. **性能指标达标**
   - 平均执行时间 ≤ 10 分钟/次
   - 无明显性能衰减

3. **并行执行稳定**
   - 并行模式（4 workers）10 次运行 100% 通过
   - 串行模式 10 次运行 100% 通过

**稳定性测试脚本：**
```bash
#!/bin/bash
# run-stability-test.sh

PASSED=0
FAILED=0
TIMES=()

for i in {1..10}; do
  echo "=== 运行 #$i ==="
  START=$(date +%s)

  if pnpm test:e2e:chromium --workers=4; then
    PASSED=$((PASSED + 1))
    echo "✅ 运行 #$i 通过"
  else
    FAILED=$((FAILED + 1))
    echo "❌ 运行 #$i 失败"
  fi

  END=$(date +%s)
  DURATION=$((END - START))
  TIMES+=($DURATION)
  echo "⏱️  耗时: ${DURATION}s"
  echo ""
done

echo "=== 稳定性测试结果 ==="
echo "通过: $PASSED/10"
echo "失败: $FAILED/10"
echo "平均时间: $(awk '{sum+=$1} END {print sum/NR}' <<< "${TIMES[@]}")s"

if [ $PASSED -eq 10 ]; then
  echo "✅ 100% 稳定性通过！"
  exit 0
else
  echo "❌ 稳定性不足，需要修复"
  exit 1
fi
```

**成功标准：**
- 10/10 通过 = Epic 9 完成 ✅
- < 10/10 通过 = 分析失败原因并修复

**Epic 9 回顾：**
- Epic 9 完成后，Epic A（残疾人管理）完整测试覆盖达成
- 可以开始 Epic B（区域管理）测试
- 两个 Epic 可以并行运行

---

## Epic 10: 订单管理 E2E 测试 (Epic C)

**目标：** 测试开发者可以为订单管理功能编写完整的 E2E 测试，验证订单的 CRUD、状态流转、人员关联和附件管理功能。

**业务分组：** Epic C（业务测试 Epic）

**背景：**
- Epic A（残疾人管理）已完成 E2E 测试覆盖
- Epic B（区域管理）待开发
- 订单管理是招聘系统的核心业务功能
- 涉及复杂表单（多选择器联动）、状态流转、人员关联等场景
- 是测试工具演进的绝佳实践场

**范围：**
- ✅ 订单列表功能测试（查看、搜索、筛选、分页）
- ✅ 订单 CRUD 测试（创建、编辑、删除订单）
- ✅ 订单状态流转测试（激活订单、关闭订单）
- ✅ 订单详情查看测试
- ✅ 人员关联功能测试（添加人员到订单、管理工作状态）
- ✅ 附件管理测试（添加附件）
- ✅ 完整流程测试
- ✅ 稳定性验证（10次连续运行）
- ❌ 不修改后端业务逻辑
- ❌ 不修改前端 UI 组件

**模式：** 业务测试为主，工具包支持为辅（遵循 Epic A 成功模式）

**依赖：**
- Epic 1: ✅ 已完成（Select 工具基础框架）
- Epic 2: ✅ 已完成（Select 工具在真实 E2E 测试中验证）

**验收标准：**
1. 订单管理核心功能有完整的 E2E 测试覆盖
2. 所有测试连续运行 10 次，100% 通过率
3. 必要时扩展 e2e-test-utils 工具包（复杂表单提交、状态流转、资产附件等）
4. 测试可作为其他复杂业务模块 E2E 测试的参考

**交付物：**
- 订单管理 Page Object
- 订单列表测试用例
- 订单 CRUD 测试用例
- 订单状态流转测试用例
- 人员关联测试用例
- 附件管理测试用例
- 完整流程测试用例
- 稳定性验证报告
- 工具包扩展文档（如有）

**FRs covered:** FR1-FR50（复用现有工具，必要时扩展）

**业务功能覆盖清单：**

| 业务功能 | 测试场景数 | 描述 |
|---------|-----------|------|
| **订单列表** | 4 | 查看、搜索、筛选、分页 |
| **创建订单** | 3 | 基本创建、多选择器、复杂表单 |
| **编辑订单** | 2 | 基本编辑、状态变更 |
| **删除订单** | 2 | 直接删除、级联删除验证 |
| **订单详情** | 2 | 基本详情、完整信息展示 |
| **状态流转** | 3 | 激活订单、关闭订单、状态限制 |
| **人员关联** | 3 | 添加人员、管理工作状态、人员列表 |
| **附件管理** | 2 | 添加附件、附件验证 |
| **完整流程** | 2 | 新增完整流程、编辑完整流程 |

**总计：** 23 个测试场景

---

### Story 10.1: 创建订单管理 Page Object

作为测试开发者，
我想要创建订单管理的 Page Object，
以便组织订单管理相关的页面元素和操作。

**验收标准：**

**Given** Epic 9 的 Page Object 模式已验证
**When** 创建 `web/tests/e2e/pages/admin/order-management.page.ts`
**Then** 定义订单列表页面的选择器和操作方法
**And** 定义创建订单表单的选择器和操作方法
**And** 定义编辑订单表单的选择器和操作方法
**And** 定义订单详情对话框的选择器和操作方法
**And** 定义人员关联相关的选择器和操作方法
**And** 定义附件上传相关的选择器和操作方法
**And** 遵循现有 Page Object 设计模式
**And** 所有方法有完整的 TypeScript 类型定义

**参考：**
- `web/tests/e2e/pages/admin/disability-person.page.ts` 作为参考
- 遵循项目的 Page Object 设计模式

---

### Story 10.2: 编写订单列表查看测试

作为测试开发者，
我想要编写订单列表查看的 E2E 测试，
以便验证订单列表的基本功能和数据展示。

**验收标准：**

**Given** 订单管理 Page Object 已创建
**When** 编写订单列表查看测试用例
**Then** 验证订单列表按预期加载
**And** 验证订单数据的正确展示（订单名称、平台、公司、渠道、状态等）
**And** 验证订单状态徽章显示正确（草稿、已确认、进行中等）
**And** 验证工作状态徽章显示正确（未就业、待就业、已就业、已离职）
**And** 验证分页功能
**And** 测试在真实浏览器中通过

**测试文件:** `web/tests/e2e/specs/admin/order-list.spec.ts`

---

### Story 10.3: 编写订单搜索和筛选测试

作为测试开发者，
我想要编写订单搜索和筛选的 E2E 测试，
以便验证多维度搜索和筛选功能。

**验收标准：**

**Given** 订单列表 Page Object 已创建
**When** 编写搜索和筛选测试用例
**Then** 包含以下测试场景：

1. **订单名称搜索**
   - 输入订单名称关键词搜索
   - 验证搜索结果正确过滤

2. **订单状态筛选**
   - 按订单状态筛选（草稿、已确认、进行中等）
   - 验证筛选结果正确

3. **工作状态筛选**
   - 按工作状态筛选（未就业、待就业、已就业、已离职）
   - 验证筛选结果正确

4. **平台筛选**
   - 选择平台进行筛选
   - 使用 `selectRadixOption` 或 `selectRadixOptionAsync`
   - 验证筛选结果正确

5. **公司筛选**
   - 选择公司进行筛选
   - 验证筛选结果正确

6. **渠道筛选**
   - 选择渠道进行筛选
   - 验证筛选结果正确

7. **日期范围筛选**
   - 选择开始日期和结束日期
   - 验证日期范围内的订单正确显示

8. **重置筛选**
   - 重置所有筛选条件
   - 验证显示全部订单

**测试文件:** `web/tests/e2e/specs/admin/order-filter.spec.ts`

---

### Story 10.4: 编写创建订单测试

作为测试开发者，
我想要编写创建订单的 E2E 测试，
以便验证订单创建功能。

**验收标准：**

**Given** 订单管理 Page Object 已创建
**When** 编写创建订单测试用例
**Then** 包含以下测试场景：

1. **基本创建订单**
   - 填写必填字段（订单名称、预计开始日期）
   - 验证订单创建成功
   - 验证订单出现在列表中

2. **创建订单并选择平台**
   - 选择平台
   - 使用 `selectRadixOption` 或 `selectRadixOptionAsync`
   - 验证平台关联正确

3. **创建订单并选择公司**
   - 选择公司
   - 验证公司关联正确

4. **创建订单并选择渠道**
   - 选择渠道
   - 验证渠道关联正确

5. **创建完整订单（所有字段）**
   - 填写所有可选字段
   - 验证所有数据保存正确

6. **表单验证测试**
   - 未填写必填字段时提交
   - 验证错误提示显示正确

**测试文件:** `web/tests/e2e/specs/admin/order-create.spec.ts`

---

### Story 10.5: 编写编辑订单测试

作为测试开发者，
我想要编写编辑订单的 E2E 测试，
以便验证订单编辑功能。

**验收标准：**

**Given** 创建订单测试已通过
**When** 编写编辑订单测试用例
**Then** 包含以下测试场景：

1. **编辑订单基本信息**
   - 修改订单名称
   - 修改预计开始日期
   - 验证修改后数据更新

2. **编辑订单关联信息**
   - 更换平台
   - 更换公司
   - 更换渠道
   - 验证关联更新正确

3. **编辑后验证列表更新**
   - 编辑订单后返回列表
   - 验证列表中显示更新后的信息

**测试文件:** `web/tests/e2e/specs/admin/order-edit.spec.ts`

---

### Story 10.6: 编写删除订单测试

作为测试开发者，
我想要编写删除订单的 E2E 测试，
以便验证订单删除功能和相关约束。

**验收标准：**

**Given** 编辑订单测试已通过
**When** 编写删除订单测试用例
**Then** 包含以下测试场景：

1. **删除草稿状态订单**
   - 删除草稿状态的订单
   - 验证删除确认对话框显示
   - 确认删除
   - 验证删除成功后列表中不再显示

2. **删除有关联人员的订单**
   - 尝试删除已关联人员的订单
   - 验证错误提示或级联删除行为
   - 根据实际业务逻辑验证结果

3. **取消删除**
   - 点击删除按钮
   - 在确认对话框中点击取消
   - 验证订单未被删除

**测试文件:** `web/tests/e2e/specs/admin/order-delete.spec.ts`

---

### Story 10.7: 编写订单状态流转测试

作为测试开发者，
我想要编写订单状态流转的 E2E 测试，
以便验证激活和关闭订单的功能。

**验收标准：**

**Given** 订单 CRUD 测试已通过
**When** 编写订单状态流转测试用例
**Then** 包含以下测试场景：

1. **激活草稿订单**
   - 创建草稿状态订单
   - 点击激活订单按钮
   - 验证确认对话框显示
   - 确认激活
   - 验证订单状态变为进行中

2. **关闭进行中订单**
   - 激活订单后
   - 点击关闭订单按钮
   - 验证确认对话框显示
   - 确认关闭
   - 验证订单状态变为已完成

3. **状态限制验证**
   - 尝试激活非草稿状态的订单
   - 验证按钮禁用或操作被阻止
   - 尝试关闭非进行中状态的订单
   - 验证操作限制正确

**测试文件:** `web/tests/e2e/specs/admin/order-status.spec.ts`

---

### Story 10.8: 编写订单详情查看测试

作为测试开发者，
我想要编写查看订单详情的 E2E 测试，
以便验证订单详情页面的完整信息展示。

**验收标准：**

**Given** 订单管理 Page Object 已创建
**When** 编写订单详情查看测试用例
**Then** 包含以下测试场景：

1. **查看基本订单详情**
   - 打开订单详情
   - 验证订单名称、平台、公司、渠道显示正确
   - 验证订单状态、工作状态显示正确
   - 验证预计开始日期显示正确

2. **查看订单人员列表**
   - 在详情中查看关联人员
   - 验证人员列表显示正确
   - 验证人员工作状态显示正确

3. **查看订单附件**
   - 在详情中查看附件列表
   - 验证附件显示正确

**测试文件:** `web/tests/e2e/specs/admin/order-detail.spec.ts`

---

### Story 10.9: 编写人员关联功能测试

作为测试开发者，
我想要编写人员关联功能的 E2E 测试，
以便验证添加人员到订单和管理工作状态的功能。

**验收标准：**

**Given** 订单管理 Page Object 已创建
**When** 编写人员关联测试用例
**Then** 包含以下测试场景：

1. **添加人员到订单**
   - 打开订单人员管理对话框
   - 选择残疾人
   - 设置入职日期和薪资
   - 验证人员添加成功
   - 验证人员出现在订单详情中

2. **管理工作状态**
   - 修改人员工作状态（未就业→待就业→已就业）
   - 验证状态更新正确

3. **设置实际入职日期**
   - 设置人员的实际入职日期
   - 验证日期保存正确

4. **人员离职**
   - 设置人员为已离职状态
   - 设置离职日期
   - 验证离职信息保存正确

**测试文件:** `web/tests/e2e/specs/admin/order-person.spec.ts`

---

### Story 10.10: 编写附件管理测试

作为测试开发者，
我想要编写订单附件管理的 E2E 测试，
以便验证添加订单附件的功能。

**验收标准：**

**Given** 订单管理 Page Object 已创建
**When** 编写附件管理测试用例
**Then** 包含以下测试场景：

1. **为订单添加附件**
   - 打开添加附件对话框
   - 选择订单人员
   - 上传附件文件
   - 验证附件添加成功

2. **附件文件格式验证**
   - 上传支持的文件格式
   - 验证上传成功
   - 尝试上传不支持的格式（如有）
   - 验证错误提示

**测试文件:** `web/tests/e2e/specs/admin/order-attachment.spec.ts`

---

### Story 10.11: 编写订单完整流程测试

作为测试开发者，
我想要编写订单管理的完整流程 E2E 测试，
以便验证从创建到关闭的端到端场景。

**验收标准：**

**Given** 所有子功能测试已完成
**When** 编写完整流程测试
**Then** 包含以下测试场景：

1. **新增订单完整流程**
   - 创建订单（填写所有字段）
   - 添加人员到订单
   - 为人员添加附件
   - 激活订单
   - 验证所有步骤成功

2. **编辑订单完整流程**
   - 打开已有订单
   - 修改订单信息
   - 添加更多人员
   - 关闭订单
   - 验证所有步骤成功

**测试文件:** `web/tests/e2e/specs/admin/order-complete.spec.ts`

---

### Story 10.12: 运行测试并收集问题和改进建议

作为测试开发者，
我想要运行订单管理测试并收集反馈，
以便发现潜在问题并改进测试或工具。

**验收标准：**

**Given** 所有订单管理测试用例已编写
**When** 运行完整的订单管理 E2E 测试套件
**Then** 记录所有问题（失败的测试、错误消息、使用体验）
**Then** 分类问题：业务逻辑 bug vs 测试代码问题 vs 工具不足
**And** 整理成问题清单
**And** 识别是否需要扩展 e2e-test-utils 工具包

**关注点：**
- 现有 Select 工具是否满足多选择器表单需求？
- 是否需要复杂表单提交专用工具？
- 是否需要状态流转测试工具？
- 是否需要资产附件操作工具？
- 错误消息是否清晰？

---

### Story 10.13: 扩展工具包（如需要）

作为测试开发者，
我想要根据 Story 10.12 的发现扩展 e2e-test-utils 工具包，
以便更好地支持订单管理等复杂业务模块的测试。

**验收标准：**

**Given** Story 10.12 已识别工具扩展需求
**When** 实现必要的工具扩展
**Then** 如需复杂表单提交工具：实现 `fillComplexForm()` 函数
**And** 如需状态流转测试工具：实现 `transitionOrderStatus()` 函数
**And** 如需资产附件工具：实现 `attachAssetToOrder()` 函数
**And** 编写工具函数的单元测试
**And** 在订单管理测试中验证新工具
**And** 更新工具包文档

**可能的工具扩展：**
```typescript
// 复杂表单提交工具（示例）
export async function fillComplexForm(
  page: Page,
  fields: Record<string, any>
): Promise<void>

// 状态流转测试工具（示例）
export async function transitionOrderStatus(
  page: Page,
  fromStatus: string,
  toStatus: string
): Promise<void>

// 资产附件操作工具（示例）
export async function attachAssetToOrder(
  page: Page,
  orderId: string,
  assetFile: string
): Promise<void>
```

**依赖：**
- 仅在 Story 10.12 确认需要时才执行此 Story
- 如无需扩展，此 Story 可标记为 N/A

---

### Story 10.14: 订单管理稳定性验证

作为测试开发者，
我想要验证订单管理测试的稳定性，
以便确保测试可以可靠地使用。

**验收标准：**

**Given** 所有问题已修复（包括工具扩展）
**When** 连续运行订单管理相关测试 10 次
**Then** 所有测试 100% 通过
**And** 无 flaky 失败
**And** 平均执行时间符合预期

**测试场景：**
- `pnpm test:e2e:chromium order-*.spec.ts` 运行 10 次

**成功标准：**
- 10/10 次通过 = 100% 稳定性 ✅
- 9/10 次通过 = 90% 稳定性，需要分析失败原因 ⚠️
- < 9/10 次通过 = 稳定性不足，需要修复 ❌

**Epic 10 回顾：**
- 如果 100% 通过，Epic C 完成
- 如果 < 100%，需要分析并修复问题后再验证

---

### Epic 11: 基础配置管理测试 (Epic F)

**目标：** 为平台、公司、渠道配置管理编写 E2E 测试，为后续用户管理和跨端测试提供必要的测试数据。

**状态:** 🆕 Backlog

**背景：**
- Platform 和 Company 是订单创建和企业用户的必要前置条件
- Company 必须关联 Platform（1:N 关系）
- Channel 是订单的可选条件

**实体关系链：**
```
Platform (平台)
  ↓ 1:N
Company (公司) - 必须 platformId
  ↓ 1:N
Order (订单) - 必须 companyId
```

**交付物：**
- Platform 管理 Page Object
- Platform 创建和列表验证测试
- Company 管理 Page Object（重点）
- Company 创建和列表验证测试
- Channel 管理 Page Object（可选）
- Channel 创建和列表验证测试（可选）
- 配置数据验证测试（订单可以选择配置）

**Story 列表：**
- Story 11.1: Platform 管理 Page Object
- Story 11.2: 创建测试平台
- Story 11.3: 验证平台列表显示
- Story 11.4: Company 管理 Page Object（重点）
- Story 11.5: 创建测试公司（需要先有平台）
- Story 11.6: 验证公司列表显示
- Story 11.7: Channel 管理 Page Object（可选）
- Story 11.8: 创建测试渠道（可选）
- Story 11.9: 配置数据验证（订单可以选择平台和公司）

**Epic 11 回顾：**
- 验证配置管理功能正常
- 确认为后续 Epic 提供稳定的测试数据

---

### Epic 12: 用户管理与小程序登录测试 (Epic D)

**目标：** 为用户管理和小程序登录编写 E2E 测试，解锁小程序端的测试能力。

**状态:** 🆕 Backlog

**依赖：** Epic 11 完成（需要 Company 数据）

**背景：**
- 小程序通过 H5 URL 访问（`/mini` 和 `/talent-mini`）
- 企业用户（EMPLOYER 类型）需要关联公司
- 人才用户（TALENT 类型）需要关联残疾人
- 小程序只读，无写操作

**交付物：**
- 用户管理 Page Object
- 后台创建企业用户测试
- 后台创建人才用户测试
- 企业小程序 Page Object
- 企业小程序登录测试
- 人才小程序 Page Object
- 人才小程序登录测试
- 用户权限验证测试（确保小程序无写操作）

**Story 列表：**
- Story 12.1: 用户管理 Page Object
- Story 12.2: 后台创建企业用户测试
- Story 12.3: 后台创建人才用户测试
- Story 12.4: 企业小程序 Page Object
- Story 12.5: 企业小程序登录测试
- Story 12.6: 人才小程序 Page Object
- Story 12.7: 人才小程序登录测试
- Story 12.8: 用户权限验证测试（小程序无写操作）

**技术要点：**
- 小程序 H5 URL: `http://localhost:8080/mini` 和 `/talent-mini`
- 登录后存储 token 进行后续操作
- 使用 Playwright 测试 H5 页面

**Epic 12 回顾：**
- 验证用户管理和小程序登录功能正常
- 为跨端测试提供登录能力

---

### Epic 13: 跨端数据同步测试 (Epic E)

**目标：** 验证后台操作后小程序端的数据同步，覆盖完整的业务流程。

**状态:** 🆕 Backlog

**依赖：** Epic 10（订单管理）和 Epic 12（小程序登录）完成

**背景：**
- 真实用户旅程跨越管理后台和小程序
- 管理员在后台操作 → 用户在小程序查看
- 需要验证数据同步的正确性和时效性

**交付物：**
- 后台创建订单 → 企业小程序验证测试
- 后台编辑订单 → 企业小程序验证测试
- 后台添加残疾人到订单 → 人才小程序验证测试
- 后台更新工作状态 → 双小程序验证测试
- 跨端测试稳定性验证

**Story 列表：**
- Story 13.1: 后台创建订单 → 企业小程序验证
- Story 13.2: 后台编辑订单 → 企业小程序验证
- Story 13.3: 后台添加人员 → 人才小程序验证
- Story 13.4: 后台更新状态 → 双小程序验证
- Story 13.5: 跨端测试稳定性验证

**技术要点：**
- 多 Page 对象管理（后台 + 小程序）
- 数据同步等待策略
- WebSocket 通信验证（`/mini-ws`、`/talent-mini-ws`）
- 测试隔离和清理

**Epic 13 回顾：**
- 验证完整的跨端业务流程
- 确保数据同步正确性

---
