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

Status: done

<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->

## Story

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

## Acceptance Criteria

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

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

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

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

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

## Tasks / Subtasks

- [x] 补充 Page Object 状态流转方法 (AC: When)
  - [x] 在 `OrderManagementPage` 中添加 `activateOrder()` 方法
  - [x] 在 `OrderManagementPage` 中添加 `closeOrder()` 方法
  - [x] 在 `OrderManagementPage` 中添加 `getOrderStatus()` 方法
  - [x] 添加验证状态按钮状态的方法
- [x] 创建状态流转测试文件 (AC: When)
  - [x] 创建 `web/tests/e2e/specs/admin/order-status.spec.ts`
  - [x] 导入必要的测试依赖和 Page Object
- [x] 编写激活草稿订单测试 (AC: Then #1)
  - [x] 测试创建草稿订单
  - [x] 测试打开激活确认对话框
  - [x] 测试确认激活操作
  - [x] 验证订单状态从草稿变为进行中
  - [x] 验证 Toast 成功消息显示
- [x] 编写关闭进行中订单测试 (AC: Then #2)
  - [x] 测试创建并激活订单（准备进行中状态）
  - [x] 测试打开关闭确认对话框
  - [x] 测试确认关闭操作
  - [x] 验证订单状态从进行中变为已完成
  - [x] 验证 Toast 成功消息显示
- [x] 编写状态限制验证测试 (AC: Then #3)
  - [x] 测试不能激活已确认/进行中/已完成状态的订单
  - [x] 测试不能关闭草稿/已确认/已完成状态的订单
  - [x] 验证按钮禁用状态
- [x] 确保所有测试通过 (AC: And)

## Dev Notes

### Epic Context

**Epic 10: 订单管理 E2E 测试 (Epic C - 业务测试 Epic)**

- **目标**: 测试开发者可以为订单管理功能编写完整的 E2E 测试，验证订单的 CRUD、状态流转、人员关联和附件管理功能
- **业务分组**: Epic C（业务测试 Epic）
- **背景**: 订单管理是招聘系统的核心业务功能，涉及复杂表单（多选择器联动）、状态流转、人员关联等场景
- **模式**: 业务测试为主，工具包支持为辅（遵循 Epic A 成功模式）

**依赖:**
- Epic 1: ✅ 已完成（Select 工具基础框架）
- Epic 2: ✅ 已完成（Select 工具在真实 E2E 测试中验证）
- Story 10.1: ✅ 已完成（订单管理 Page Object）
- Story 10.2: ✅ 已完成（订单列表查看测试）
- Story 10.3: ✅ 已完成（订单搜索和筛选测试）
- Story 10.4: ✅ 已完成（创建订单测试）
- Story 10.5: ✅ 已完成（编辑订单测试）
- Story 10.6: ✅ 已完成（删除订单测试）

### 前序 Story 情报 (Story 10.6)

**从 Story 10.6 学到的经验:**

1. **Page Object 菜单操作模式**：
   - 编辑和删除操作都通过"打开菜单"按钮进入
   - 状态流转按钮可能也在菜单中，或者在行操作按钮区域
   - 需要先探索实际 UI 结构来确定按钮位置

2. **灵活的选择器策略**：
   - 使用正则表达式匹配多种可能的按钮名称
   - 示例：`/^(确认删除|删除|确定|确认)$/` 匹配确认按钮

3. **测试隔离优化**：
   - 每个测试套件创建独立的测试订单
   - 避免测试之间的状态干扰
   - 使用时间戳确保订单名称唯一

4. **Toast 消息验证**：
   - 使用正则表达式匹配关键词而非精确匹配
   - 示例：`/删除/` 匹配删除相关的成功消息

### Page Object 已有功能

**订单状态常量定义** (`web/tests/e2e/pages/admin/order-management.page.ts`):

```typescript
// 订单状态常量
export const ORDER_STATUS = {
  DRAFT: 'draft',
  CONFIRMED: 'confirmed',
  IN_PROGRESS: 'in_progress',
  COMPLETED: 'completed',
} as const;

export type OrderStatus = typeof ORDER_STATUS[keyof typeof ORDER_STATUS];

// 订单状态显示名称映射
export const ORDER_STATUS_LABELS: Record<OrderStatus, string> = {
  draft: '草稿',
  confirmed: '已确认',
  in_progress: '进行中',
  completed: '已完成',
} as const;
```

**已有的相关方法:**

| 方法 | 说明 | 状态流转测试用途 |
|------|------|-----------------|
| `createOrder(data)` | 创建订单 | 创建草稿订单作为测试起点 |
| `editOrder(orderName, data)` | 编辑订单 | 可通过 `status` 字段修改状态（但不是真实的状态流转操作） |
| `openDetailDialog(orderName)` | 打开订单详情 | 验证详情中的状态显示 |
| `getOrderDetailInfo()` | 获取订单详情 | 获取当前订单状态信息 |
| `openEditDialog(orderName)` | 打开编辑菜单 | 参考菜单操作模式 |

### 需要补充的 Page Object 方法

**状态流转操作方法（需要添加）:**

1. **激活订单方法:**
   ```typescript
   /**
    * 打开激活订单确认对话框
    * @param orderName 订单名称
    */
   async openActivateDialog(orderName: string): Promise<void>

   /**
    * 确认激活订单
    */
   async confirmActivate(): Promise<void>

   /**
    * 激活订单（完整流程）
    * @param orderName 订单名称
    * @returns 是否成功激活
    */
   async activateOrder(orderName: string): Promise<boolean>
   ```

2. **关闭订单方法:**
   ```typescript
   /**
    * 打开关闭订单确认对话框
    * @param orderName 订单名称
    */
   async openCloseDialog(orderName: string): Promise<void>

   /**
    * 确认关闭订单
    */
   async confirmClose(): Promise<void>

   /**
    * 关闭订单（完整流程）
    * @param orderName 订单名称
    * @returns 是否成功关闭
    */
   async closeOrder(orderName: string): Promise<boolean>
   ```

3. **状态获取方法:**
   ```typescript
   /**
    * 获取订单的当前状态（从列表页面）
    * @param orderName 订单名称
    * @returns 订单状态值
    */
   async getOrderStatus(orderName: string): Promise<OrderStatus | null>

   /**
    * 验证订单状态
    * @param orderName 订单名称
    * @param expectedStatus 期望的状态
    */
   async expectOrderStatus(orderName: string, expectedStatus: OrderStatus): Promise<void>
   ```

4. **按钮状态验证方法:**
   ```typescript
   /**
    * 检查激活按钮是否可用
    * @param orderName 订单名称
    * @returns 按钮是否可用
    */
   async isActivateButtonEnabled(orderName: string): Promise<boolean>

   /**
    * 检查关闭按钮是否可用
    * @param orderName 订单名称
    * @returns 按钮是否可用
    */
   async isCloseButtonEnabled(orderName: string): Promise<boolean>
   ```

### 测试覆盖场景清单

**激活草稿订单:**
- [ ] 创建草稿状态订单
- [ ] 打开激活确认对话框
- [ ] 确认激活操作
- [ ] 验证订单状态从草稿变为进行中
- [ ] 验证 Toast 成功消息显示

**关闭进行中订单:**
- [ ] 创建并激活订单（准备进行中状态）
- [ ] 打开关闭确认对话框
- [ ] 确认关闭操作
- [ ] 验证订单状态从进行中变为已完成
- [ ] 验证 Toast 成功消息显示

**状态限制验证:**
- [ ] 尝试激活已确认状态的订单 → 按钮禁用或操作失败
- [ ] 尝试激活进行中状态的订单 → 按钮禁用或操作失败
- [ ] 尝试激活已完成状态的订单 → 按钮禁用或操作失败
- [ ] 尝试关闭草稿状态的订单 → 按钮禁用或操作失败
- [ ] 尝试关闭已确认状态的订单 → 按钮禁用或操作失败
- [ ] 尝试关闭已完成状态的订单 → 按钮禁用或操作失败

**状态流转图参考:**
```
草稿 (draft) --[激活]--> 进行中 (in_progress) --[关闭]--> 已完成 (completed)
                        ↑
                   [确认] (从草稿)
```

### UI 结构探索要点

**状态流转按钮位置假设（需要验证）:**

1. **在操作菜单中**（与编辑/删除类似）:
   - 点击"打开菜单"按钮
   - 菜单中可能包含"激活"、"关闭"等选项

2. **作为行操作按钮**:
   - 直接在订单行显示激活/关闭按钮
   - 按钮可能根据订单状态显示/隐藏

3. **在详情页面中**:
   - 打开订单详情后显示状态操作按钮

**测试时优先探索的顺序:**
1. 先检查操作菜单中是否有状态流转选项
2. 检查行中是否有独立的激活/关闭按钮
3. 检查详情页面中的状态操作按钮

### 项目结构对齐

**遵循 Epic 9.6 并行执行决策:**
- ✅ 不使用 `test.describe.serial`
- ✅ 每个测试创建独立的测试数据
- ✅ 使用时间戳确保订单名称唯一

**遵循项目的类型规范:**
- ✅ 使用 TypeScript 严格模式
- ✅ 使用 `ORDER_STATUS` 和 `ORDER_STATUS_LABELS` 常量
- ✅ 状态类型使用 `OrderStatus` 类型别名

**遵循项目的测试模式:**
- ✅ 使用 Playwright fixtures
- ✅ 使用 Page Object 模式
- ✅ Toast 消息使用 `data-sonner-toast` 选择器
- ✅ 对话框使用 `role="dialog"` 或 `role="alertdialog"`

### Project Structure Notes

**测试文件位置:**
```
web/tests/e2e/
├── pages/admin/
│   └── order-management.page.ts  (需要补充状态流转方法)
└── specs/admin/
    └── order-status.spec.ts      (新建)
```

**与其他测试的关系:**
- `order-list.spec.ts`: 验证列表中状态徽章显示
- `order-create.spec.ts`: 创建草稿订单（测试起点）
- `order-edit.spec.ts`: 编辑订单（可能涉及状态修改）
- `order-delete.spec.ts`: 删除订单（参考菜单操作模式）

**潜在冲突:**
- 状态流转测试可能创建多种状态的订单，需要确保数据隔离
- 建议使用唯一的订单名称前缀：`状态流转测试_${timestamp}`

### References

**Epic 需求来源:**
- [Source: _bmad-output/planning-artifacts/epics.md](epics.md) - Story 10.7 详细需求

**Page Object 现有实现:**
- [Source: web/tests/e2e/pages/admin/order-management.page.ts](web/tests/e2e/pages/admin/order-management.page.ts) - 订单状态常量、订单数据接口

**前序 Story 学习:**
- [Source: _bmad-output/implementation-artifacts/10-6-order-delete-tests.md](10-6-order-delete-tests.md) - 菜单操作模式、灵活选择器、测试隔离

**项目上下文:**
- [Source: _bmad-output/project-context.md](project-context.md) - 技术栈、测试规范、类型系统

## Dev Agent Record

### Agent Model Used

claude-opus-4-5-20251101

### Debug Log References

无

### Completion Notes List

1. **Page Object 状态流转方法补充** (`web/tests/e2e/pages/admin/order-management.page.ts`):
   - 添加了 `openActivateDialog()` - 打开激活订单确认对话框
   - 添加了 `confirmActivate()` - 确认激活订单
   - 添加了 `activateOrder()` - 激活订单（完整流程）
   - 添加了 `openCloseDialog()` - 打开关闭订单确认对话框
   - 添加了 `confirmClose()` - 确认关闭订单
   - 添加了 `closeOrder()` - 关闭订单（完整流程）
   - 添加了 `getOrderStatus()` - 获取订单的当前状态
   - 添加了 `expectOrderStatus()` - 验证订单状态
   - 添加了 `checkActivateButtonEnabled()` - 检查激活按钮是否可用
   - 添加了 `checkCloseButtonEnabled()` - 检查关闭按钮是否可用

2. **测试文件创建** (`web/tests/e2e/specs/admin/order-status.spec.ts`):
   - 10 个测试用例覆盖所有 AC 要求
   - 激活草稿订单测试（3个测试）
   - 关闭进行中订单测试（3个测试）
   - 状态限制验证测试（3个测试）
   - 完整状态流转流程测试（1个测试）

3. **代码审查修复 (2026-01-12)**:
   - **HIGH #1-2**: 重构状态限制验证测试，现在显式创建和测试 IN_PROGRESS/COMPLETED 状态
   - **HIGH #3**: 改进 `getOrderStatus()` 方法，跳过第一列避免匹配订单名称，增加状态徽章查找策略
   - **HIGH #4**: 移除所有硬编码超时，使用 Playwright 最佳实践（waitForSelector, waitForFunction）
   - **HIGH #5**: 修复测试跳过逻辑，从 beforeEach 移到单个测试内部
   - **MEDIUM #6**: 重命名方法：`isActivateButtonEnabled()` → `checkActivateButtonEnabled()`，`isCloseButtonEnabled()` → `checkCloseButtonEnabled()`，明确表示有副作用
   - **MEDIUM #7**: 移除未使用的 `getFirstOrderName()` 辅助函数
   - **MEDIUM #8**: 改进 Toast 消息验证正则：`/激活.*成功|已激活/` 和 `/关闭.*成功|已完成/`

### File List

**新增文件:**
- `web/tests/e2e/specs/admin/order-status.spec.ts` - 订单状态流转测试文件

**修改文件:**
- `web/tests/e2e/pages/admin/order-management.page.ts` - 添加了10个状态流转相关方法

### Change Log

**2026-01-12**
- 补充 Page Object 状态流转方法（10个新方法）
- 创建订单状态流转测试文件
- 实现激活草稿订单测试
- 实现关闭进行中订单测试
- 实现状态限制验证测试
- 改进占位符文本过滤逻辑
- 添加错误处理和测试跳过逻辑
- 完成 10 个测试用例

---
