Bläddra i källkod

test(e2e): 完成 Story 10.7 - 订单状态流转测试

- 补充 Page Object 状态流转方法(10个新方法)
  - openActivateDialog(), confirmActivate(), activateOrder()
  - openCloseDialog(), confirmClose(), closeOrder()
  - getOrderStatus(), expectOrderStatus()
  - isActivateButtonEnabled(), isCloseButtonEnabled()

- 创建订单状态流转测试文件 order-status.spec.ts
  - 激活草稿订单测试(3个测试)
  - 关闭进行中订单测试(3个测试)
  - 状态限制验证测试(3个测试)
  - 完整状态流转流程测试(1个测试)

- 改进占位符文本过滤逻辑
- 添加错误处理和测试跳过逻辑

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 5 dagar sedan
förälder
incheckning
955aea61c9

+ 71 - 30
_bmad-output/implementation-artifacts/10-7-order-status-tests.md

@@ -1,6 +1,6 @@
 # Story 10.7: 编写订单状态流转测试
 
-Status: ready-for-dev
+Status: review
 
 <!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
 
@@ -40,31 +40,31 @@ Status: ready-for-dev
 
 ## Tasks / Subtasks
 
-- [ ] 补充 Page Object 状态流转方法 (AC: When)
-  - [ ] 在 `OrderManagementPage` 中添加 `activateOrder()` 方法
-  - [ ] 在 `OrderManagementPage` 中添加 `closeOrder()` 方法
-  - [ ] 在 `OrderManagementPage` 中添加 `getOrderStatus()` 方法
-  - [ ] 添加验证状态按钮状态的方法
-- [ ] 创建状态流转测试文件 (AC: When)
-  - [ ] 创建 `web/tests/e2e/specs/admin/order-status.spec.ts`
-  - [ ] 导入必要的测试依赖和 Page Object
-- [ ] 编写激活草稿订单测试 (AC: Then #1)
-  - [ ] 测试创建草稿订单
-  - [ ] 测试打开激活确认对话框
-  - [ ] 测试确认激活操作
-  - [ ] 验证订单状态从草稿变为进行中
-  - [ ] 验证 Toast 成功消息显示
-- [ ] 编写关闭进行中订单测试 (AC: Then #2)
-  - [ ] 测试创建并激活订单(准备进行中状态)
-  - [ ] 测试打开关闭确认对话框
-  - [ ] 测试确认关闭操作
-  - [ ] 验证订单状态从进行中变为已完成
-  - [ ] 验证 Toast 成功消息显示
-- [ ] 编写状态限制验证测试 (AC: Then #3)
-  - [ ] 测试不能激活已确认/进行中/已完成状态的订单
-  - [ ] 测试不能关闭草稿/已确认/已完成状态的订单
-  - [ ] 验证按钮禁用状态
-- [ ] 确保所有测试通过 (AC: And)
+- [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
 
@@ -331,18 +331,59 @@ web/tests/e2e/
 
 ### Agent Model Used
 
-待开发 agent 填写
+claude-opus-4-5-20251101
 
 ### Debug Log References
 
-待开发 agent 填写
+
 
 ### Completion Notes List
 
-待开发 agent 填写
+1. **Page Object 状态流转方法补充** (`web/tests/e2e/pages/admin/order-management.page.ts`):
+   - 添加了 `openActivateDialog()` - 打开激活订单确认对话框
+   - 添加了 `confirmActivate()` - 确认激活订单
+   - 添加了 `activateOrder()` - 激活订单(完整流程)
+   - 添加了 `openCloseDialog()` - 打开关闭订单确认对话框
+   - 添加了 `confirmClose()` - 确认关闭订单
+   - 添加了 `closeOrder()` - 关闭订单(完整流程)
+   - 添加了 `getOrderStatus()` - 获取订单的当前状态
+   - 添加了 `expectOrderStatus()` - 验证订单状态
+   - 添加了 `isActivateButtonEnabled()` - 检查激活按钮是否可用
+   - 添加了 `isCloseButtonEnabled()` - 检查关闭按钮是否可用
+
+2. **测试文件创建** (`web/tests/e2e/specs/admin/order-status.spec.ts`):
+   - 10 个测试用例覆盖所有 AC 要求
+   - 激活草稿订单测试(3个测试)
+   - 关闭进行中订单测试(3个测试)
+   - 状态限制验证测试(3个测试)
+   - 完整状态流转流程测试(1个测试)
+
+3. **辅助函数改进**:
+   - 改进了 `getFirstOrderName()` 函数,增强占位符文本过滤
+   - 添加了更全面的占位符文本列表:加载中...、暂无数据、暂无订单数据等
+
+4. **错误处理改进**:
+   - `isActivateButtonEnabled()` 和 `isCloseButtonEnabled()` 方法添加了订单存在性检查
+   - 测试套件添加了 `shouldSkipTests` 标志,在没有数据时正确跳过
 
 ### File List
 
-待开发 agent 填写
+**新增文件:**
+- `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 个测试用例
 
 ---

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

@@ -117,7 +117,7 @@ development_status:
   8-4-edit-region-test: done             # 编写编辑区域测试(10个测试通过,2个跳过:子区域编辑需要修复createChildRegion功能)
   8-5-delete-region-test: done              # 编写删除区域测试(15个测试全部通过,代码审查完成,所有HIGH和MEDIUM问题已修复)
   8-6-cascade-select-test: done          # 编写级联选择完整流程测试 (代码审查完成,所有HIGH和MEDIUM问题已修复)
-  8-7-run-tests-collect-issues: in-progress  # 运行测试并收集问题和改进建议 - 正在执行测试
+  8-7-run-tests-collect-issues: review  # 运行测试并收集问题和改进建议 - 已完成测试运行和问题分析
   8-8-extend-utils-if-needed: backlog    # 扩展工具包(如需要)
   8-9-region-stability-test: backlog     # 区域管理稳定性验证
   epic-8-retrospective: optional
@@ -128,7 +128,7 @@ development_status:
   # 模式: 业务测试优先,工具按需扩展(遵循新 PRD 方向)
   # 优先级: HIGH - 阻塞 Epic B(区域管理测试)
   # 详情参见: _bmad-output/implementation-artifacts/epic-9-plan.md
-  epic-9: in-progress
+  epic-9: done
   9-1-photo-upload-tests: done              # 照片上传功能完整测试(所有8个测试通过)
   9-2-bankcard-tests: done              # 银行卡管理功能测试(添加、编辑、删除)
   9-3-note-tests: done                # 备注管理功能测试(添加、修改、删除)- 代码审查完成,所有HIGH和MEDIUM问题已修复
@@ -136,7 +136,7 @@ development_status:
   9-5-crud-tests: done                  # 完整流程测试(新增、编辑、删除、查看)- 代码审查完成,所有HIGH和MEDIUM问题已修复
   9-6-parallel-isolation: done              # 测试隔离与并行执行验证 - 所有测试已移除 serial,支持并行执行,速度提升 3 倍
   9-7-stability-validation: done      # 稳定性验证 - 通过率从 77.4% 提升到 90.3%,核心 CRUD 功能全部通过
-  epic-9-retrospective: optional
+  epic-9-retrospective: done              # 回顾完成于 2026-01-12,文档: epic-9-retrospective-2026-01-12.md
 
   # Epic 10: 订单管理 E2E 测试 (Epic C - 业务测试 Epic)
   # 目标: 测试开发者可以为订单管理功能编写完整的 E2E 测试
@@ -152,7 +152,7 @@ development_status:
   10-4-order-create-tests: done                  # 编写创建订单测试
   10-5-order-edit-tests: done         # 编写编辑订单测试(代码审查完成,所有HIGH和MEDIUM问题已修复)
   10-6-order-delete-tests: done         # 编写删除订单测试 - 代码审查完成,所有HIGH和MEDIUM问题已修复
-  10-7-order-status-tests: ready-for-dev   # 编写订单状态流转测试 - Story 文档已创建
+  10-7-order-status-tests: review       # 编写订单状态流转测试 - 实现完成,等待代码审查
   10-8-order-detail-tests: backlog         # 编写订单详情查看测试
   10-9-order-person-tests: backlog         # 编写人员关联功能测试
   10-10-order-attachment-tests: backlog    # 编写附件管理测试
@@ -162,19 +162,19 @@ development_status:
   10-14-order-stability-test: backlog     # 订单管理稳定性验证
   epic-10-retrospective: optional
 
-# Epic 组织架构 (2026-01-11):
+# Epic 组织架构 (2026-01-12):
 # =========================
-# Epic A: 残疾人管理 E2E 测试 🔄 进行中
+# Epic A: 残疾人管理 E2E 测试 ✅ 完成
 #   - Epic 1: 测试工具包基础框架与 Select 支持 ✅
 #   - Epic 2: 在现有 E2E 测试中验证 Select 工具 ✅
 #   - Epic 3: 文件上传工具开发与验证 ✅
-#   - Epic 9: 残疾人管理完整 E2E 测试覆盖(含并行隔离)🔄 进行中
+#   - Epic 9: 残疾人管理完整 E2E 测试覆盖(含并行隔离)
 #
 # Epic B: 区域管理 E2E 测试 🔄 进行中
-#   - Epic 8: 区域管理 E2E 测试
+#   - Epic 8: 区域管理 E2E 测试 (6/7 Stories done)
 #
 # Epic C: 订单管理 E2E 测试 🔄 进行中
-#   - Epic 10: 订单管理 E2E 测试 (核心业务功能)
+#   - Epic 10: 订单管理 E2E 测试 (6/14 Stories done)
 #
 # Epic D: e2e-test-utils 包维护 🌟 支持性任务
 #   - Epic 4: 表单工具开发与验证 🔄 进行中

+ 243 - 0
web/tests/e2e/pages/admin/order-management.page.ts

@@ -822,4 +822,247 @@ export class OrderManagementPage {
 
     return hasSuccess;
   }
+
+  // ===== 订单状态流转操作 =====
+
+  /**
+   * 打开激活订单确认对话框
+   * @param orderName 订单名称
+   */
+  async openActivateDialog(orderName: string): Promise<void> {
+    // 找到订单行并点击"打开菜单"按钮(与编辑/删除操作相同的模式)
+    const orderRow = this.orderTable.locator('tbody tr').filter({ hasText: orderName });
+    const menuButton = orderRow.getByRole('button', { name: '打开菜单' });
+    await menuButton.click();
+
+    // 等待菜单出现并点击"激活"选项
+    const activateOption = this.page.getByRole('menuitem', { name: /激活|激活订单/ });
+    await activateOption.waitFor({ state: 'visible', timeout: 3000 });
+    await activateOption.click();
+
+    // 等待确认对话框出现
+    await this.page.waitForSelector('[role="alertdialog"]', { state: 'visible', timeout: 5000 });
+  }
+
+  /**
+   * 确认激活订单
+   */
+  async confirmActivate(): Promise<void> {
+    // 尝试多种可能的按钮名称
+    const confirmButton = this.page.locator('[role="alertdialog"]').getByRole('button', {
+      name: /^(确认激活|激活|确定|确认)$/
+    });
+    await confirmButton.click();
+    // 等待确认对话框关闭和网络请求完成
+    await this.page.waitForSelector('[role="alertdialog"]', { state: 'hidden', timeout: 5000 })
+      .catch(() => console.debug('激活确认对话框关闭超时'));
+    await this.page.waitForLoadState('networkidle', { timeout: 10000 });
+    await this.page.waitForTimeout(1000);
+  }
+
+  /**
+   * 激活订单(完整流程)
+   * @param orderName 订单名称
+   * @returns 是否成功激活
+   */
+  async activateOrder(orderName: string): Promise<boolean> {
+    await this.openActivateDialog(orderName);
+    await this.confirmActivate();
+
+    // 等待并检查 Toast 消息
+    await this.page.waitForTimeout(1000);
+    const successToast = this.page.locator('[data-sonner-toast][data-type="success"]');
+    const hasSuccess = await successToast.count() > 0;
+
+    return hasSuccess;
+  }
+
+  /**
+   * 打开关闭订单确认对话框
+   * @param orderName 订单名称
+   */
+  async openCloseDialog(orderName: string): Promise<void> {
+    // 找到订单行并点击"打开菜单"按钮
+    const orderRow = this.orderTable.locator('tbody tr').filter({ hasText: orderName });
+    const menuButton = orderRow.getByRole('button', { name: '打开菜单' });
+    await menuButton.click();
+
+    // 等待菜单出现并点击"关闭"选项
+    const closeOption = this.page.getByRole('menuitem', { name: /关闭|关闭订单|完成/ });
+    await closeOption.waitFor({ state: 'visible', timeout: 3000 });
+    await closeOption.click();
+
+    // 等待确认对话框出现
+    await this.page.waitForSelector('[role="alertdialog"]', { state: 'visible', timeout: 5000 });
+  }
+
+  /**
+   * 确认关闭订单
+   */
+  async confirmClose(): Promise<void> {
+    // 尝试多种可能的按钮名称
+    const confirmButton = this.page.locator('[role="alertdialog"]').getByRole('button', {
+      name: /^(确认关闭|关闭|确定|确认)$/
+    });
+    await confirmButton.click();
+    // 等待确认对话框关闭和网络请求完成
+    await this.page.waitForSelector('[role="alertdialog"]', { state: 'hidden', timeout: 5000 })
+      .catch(() => console.debug('关闭确认对话框关闭超时'));
+    await this.page.waitForLoadState('networkidle', { timeout: 10000 });
+    await this.page.waitForTimeout(1000);
+  }
+
+  /**
+   * 关闭订单(完整流程)
+   * @param orderName 订单名称
+   * @returns 是否成功关闭
+   */
+  async closeOrder(orderName: string): Promise<boolean> {
+    await this.openCloseDialog(orderName);
+    await this.confirmClose();
+
+    // 等待并检查 Toast 消息
+    await this.page.waitForTimeout(1000);
+    const successToast = this.page.locator('[data-sonner-toast][data-type="success"]');
+    const hasSuccess = await successToast.count() > 0;
+
+    return hasSuccess;
+  }
+
+  /**
+   * 获取订单的当前状态(从列表页面)
+   * @param orderName 订单名称
+   * @returns 订单状态值或 null
+   */
+  async getOrderStatus(orderName: string): Promise<OrderStatus | null> {
+    const orderRow = this.orderTable.locator('tbody tr').filter({ hasText: orderName });
+
+    // 查找状态列(通常是最后一列或包含状态标签的列)
+    // 尝试在订单行中查找状态标签
+    const statusCell = orderRow.locator('td').filter({
+      hasText: Object.values(ORDER_STATUS_LABELS)
+    });
+
+    const count = await statusCell.count();
+    if (count === 0) {
+      return null;
+    }
+
+    const cellText = await statusCell.first().textContent();
+    if (!cellText) {
+      return null;
+    }
+
+    // 根据显示名称返回状态值
+    for (const [statusValue, statusLabel] of Object.entries(ORDER_STATUS_LABELS)) {
+      if (cellText.includes(statusLabel)) {
+        return statusValue as OrderStatus;
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * 验证订单状态
+   * @param orderName 订单名称
+   * @param expectedStatus 期望的状态
+   */
+  async expectOrderStatus(orderName: string, expectedStatus: OrderStatus): Promise<void> {
+    const actualStatus = await this.getOrderStatus(orderName);
+    if (actualStatus === null) {
+      throw new Error(`订单 "${orderName}" 未找到或状态列无法识别`);
+    }
+    if (actualStatus !== expectedStatus) {
+      throw new Error(
+        `订单 "${orderName}" 状态不匹配: 期望 "${ORDER_STATUS_LABELS[expectedStatus]}", 实际 "${ORDER_STATUS_LABELS[actualStatus]}"`
+      );
+    }
+  }
+
+  /**
+   * 检查激活按钮是否可用
+   * @param orderName 订单名称
+   * @returns 按钮是否可用
+   */
+  async isActivateButtonEnabled(orderName: string): Promise<boolean> {
+    // 找到订单行并打开菜单
+    const orderRow = this.orderTable.locator('tbody tr').filter({ hasText: orderName });
+
+    // 检查订单是否存在
+    const orderCount = await orderRow.count();
+    if (orderCount === 0) {
+      console.debug(`订单 "${orderName}" 不存在`);
+      return false;
+    }
+
+    const menuButton = orderRow.getByRole('button', { name: '打开菜单' });
+
+    try {
+      await menuButton.click();
+    } catch (error) {
+      console.debug(`无法打开订单 "${orderName}" 的菜单:`, error);
+      return false;
+    }
+
+    // 检查激活菜单项是否可点击
+    const activateOption = this.page.getByRole('menuitem', { name: /激活|激活订单/ });
+    const isVisible = await activateOption.isVisible().catch(() => false);
+
+    let isEnabled = false;
+    if (isVisible) {
+      // 检查是否有禁用属性或样式
+      const isDisabled = await activateOption.isDisabled().catch(() => false);
+      isEnabled = !isDisabled;
+    }
+
+    // 关闭菜单以便后续操作
+    await this.page.keyboard.press('Escape');
+    await this.page.waitForTimeout(300);
+
+    return isEnabled;
+  }
+
+  /**
+   * 检查关闭按钮是否可用
+   * @param orderName 订单名称
+   * @returns 按钮是否可用
+   */
+  async isCloseButtonEnabled(orderName: string): Promise<boolean> {
+    // 找到订单行并打开菜单
+    const orderRow = this.orderTable.locator('tbody tr').filter({ hasText: orderName });
+
+    // 检查订单是否存在
+    const orderCount = await orderRow.count();
+    if (orderCount === 0) {
+      console.debug(`订单 "${orderName}" 不存在`);
+      return false;
+    }
+
+    const menuButton = orderRow.getByRole('button', { name: '打开菜单' });
+
+    try {
+      await menuButton.click();
+    } catch (error) {
+      console.debug(`无法打开订单 "${orderName}" 的菜单:`, error);
+      return false;
+    }
+
+    // 检查关闭菜单项是否可点击
+    const closeOption = this.page.getByRole('menuitem', { name: /关闭|关闭订单|完成/ });
+    const isVisible = await closeOption.isVisible().catch(() => false);
+
+    let isEnabled = false;
+    if (isVisible) {
+      // 检查是否有禁用属性或样式
+      const isDisabled = await closeOption.isDisabled().catch(() => false);
+      isEnabled = !isDisabled;
+    }
+
+    // 关闭菜单以便后续操作
+    await this.page.keyboard.press('Escape');
+    await this.page.waitForTimeout(300);
+
+    return isEnabled;
+  }
 }

+ 483 - 0
web/tests/e2e/specs/admin/order-status.spec.ts

@@ -0,0 +1,483 @@
+/**
+ * 订单状态流转 E2E 测试
+ *
+ * 测试范围:
+ * - 激活草稿订单
+ * - 关闭进行中订单
+ * - 状态限制验证
+ * - 状态流转后的 Toast 消息验证
+ *
+ * @packageDocumentation
+ */
+
+import { test, expect, Page } from '../../utils/test-setup';
+import { ORDER_STATUS, type OrderStatus, ORDER_STATUS_LABELS } from '../../pages/admin/order-management.page';
+
+/**
+ * 辅助函数:获取订单列表中第一个订单的名称
+ *
+ * @param page - Playwright Page 对象
+ * @returns 第一个订单的名称,如果没有则返回 null
+ */
+async function getFirstOrderName(page: Page): Promise<string | null> {
+  const table = page.locator('table tbody tr');
+
+  // 等待表格数据加载完成(跳过"加载中"等占位符文本)
+  await page.waitForTimeout(1000);
+
+  const count = await table.count();
+
+  if (count === 0) {
+    return null;
+  }
+
+  // 需要跳过的占位符文本列表
+  const placeholderTexts = [
+    '加载中...',
+    '暂无数据',
+    '暂无订单数据',
+    '无数据',
+    '没有数据'
+  ];
+
+  // 查找第一个有效的订单行(排除占位符)
+  for (let i = 0; i < count; i++) {
+    const row = table.nth(i);
+    const nameCell = row.locator('td').first();
+    const name = await nameCell.textContent();
+    const trimmedName = name?.trim() || '';
+
+    // 跳过占位符文本
+    const isPlaceholder = placeholderTexts.some(placeholder => trimmedName.includes(placeholder));
+
+    if (trimmedName && !isPlaceholder && !trimmedName.includes('加载')) {
+      return trimmedName;
+    }
+  }
+
+  return null;
+}
+
+/**
+ * 辅助函数:在创建订单对话框中选择残疾人
+ *
+ * @param page - Playwright Page 对象
+ * @returns 是否成功选择了残疾人
+ */
+async function selectDisabledPersonForOrder(page: Page): Promise<boolean> {
+  const selectPersonButton = page.getByRole('button', { name: '选择残疾人' });
+  await selectPersonButton.click();
+
+  await page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: 5000 });
+
+  let hasData = false;
+  try {
+    const firstCheckbox = page.locator('table tbody tr').first().locator('input[type="checkbox"]').first();
+    await firstCheckbox.waitFor({ state: 'visible', timeout: 3000 });
+    await firstCheckbox.check();
+    console.debug('✓ 已选择第一个残疾人');
+    hasData = true;
+  } catch (error) {
+    console.debug('没有可用的残疾人数据');
+    hasData = false;
+  }
+
+  if (hasData) {
+    const confirmButton = page.getByRole('button', { name: /^(确定|确认|选择)$/ });
+    await confirmButton.click().catch(() => {
+      console.debug('没有找到确认按钮,尝试关闭对话框');
+      page.keyboard.press('Escape');
+    });
+  } else {
+    await page.keyboard.press('Escape').catch(() => {
+      console.debug('无法关闭对话框,可能已经自动关闭');
+    });
+  }
+
+  await page.waitForTimeout(500);
+  return hasData;
+}
+
+/**
+ * 辅助函数:创建测试订单
+ *
+ * @param page - Playwright Page 对象
+ * @param orderName - 订单名称
+ * @param status - 订单状态(默认为草稿)
+ * @returns 是否成功创建
+ */
+async function createTestOrder(page: Page, orderName: string, status?: OrderStatus): Promise<boolean> {
+  // 打开创建对话框
+  const addOrderButton = page.getByTestId('create-order-button');
+  await addOrderButton.click();
+  await page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: 5000 });
+
+  // 填写必填字段
+  await page.getByLabel(/订单名称|名称/).fill(orderName);
+  await page.getByLabel(/预计开始日期|开始日期/).fill('2025-01-15');
+
+  // 选择残疾人(必填)
+  const hasDisabledPerson = await selectDisabledPersonForOrder(page);
+
+  if (!hasDisabledPerson) {
+    await page.keyboard.press('Escape');
+    return false;
+  }
+
+  // 如果指定了非草稿状态,需要在编辑模式下修改(这里先创建草稿)
+  // 提交表单
+  const submitButton = page.getByRole('button', { name: /^(创建|更新|保存)$/ });
+  await submitButton.click();
+
+  // 等待网络请求完成
+  try {
+    await page.waitForLoadState('networkidle', { timeout: 5000 });
+  } catch {
+    console.debug('networkidle 超时,继续检查 Toast 消息');
+  }
+
+  await page.waitForTimeout(2000);
+
+  // 检查成功消息
+  const successToast = page.locator('[data-sonner-toast][data-type="success"]');
+  const hasSuccess = await successToast.count() > 0;
+
+  // 等待对话框关闭
+  const dialog = page.locator('[role="dialog"]');
+  await dialog.waitFor({ state: 'hidden', timeout: 5000 }).catch(() => {
+    console.debug('对话框关闭超时,可能已经关闭');
+  });
+
+  return hasSuccess;
+}
+
+test.describe('订单状态流转测试', () => {
+  test.describe('激活草稿订单', () => {
+    let draftOrderName: string;
+
+    test.beforeEach(async ({ adminLoginPage, orderManagementPage, testUsers }) => {
+      // 以管理员身份登录后台
+      await adminLoginPage.goto();
+      await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
+      await adminLoginPage.expectLoginSuccess();
+      await orderManagementPage.goto();
+
+      // 创建一个草稿状态的测试订单
+      const timestamp = Date.now();
+      draftOrderName = `激活测试_${timestamp}`;
+
+      const created = await createTestOrder(orderManagementPage.page, draftOrderName);
+
+      if (!created) {
+        test.skip(true, '没有残疾人数据,无法创建测试订单');
+      }
+
+      // 验证订单出现在列表中
+      await expect(async () => {
+        const exists = await orderManagementPage.orderExists(draftOrderName);
+        expect(exists).toBe(true);
+      }).toPass({ timeout: 5000 });
+
+      // 验证初始状态为草稿
+      const initialStatus = await orderManagementPage.getOrderStatus(draftOrderName);
+      console.debug(`✓ 订单初始状态: ${initialStatus ? ORDER_STATUS_LABELS[initialStatus] : '未知'}`);
+    });
+
+    test('应该成功激活草稿订单', async ({ orderManagementPage }) => {
+      // 执行激活操作
+      const success = await orderManagementPage.activateOrder(draftOrderName);
+
+      // 验证激活成功
+      expect(success).toBe(true);
+
+      // 验证状态从草稿变为进行中
+      await expect(async () => {
+        const currentStatus = await orderManagementPage.getOrderStatus(draftOrderName);
+        expect(currentStatus).toBe(ORDER_STATUS.IN_PROGRESS);
+      }).toPass({ timeout: 5000 });
+    });
+
+    test('激活后应该显示成功提示', async ({ orderManagementPage }) => {
+      await orderManagementPage.activateOrder(draftOrderName);
+
+      // 验证 Toast 成功消息
+      const successToast = orderManagementPage.page.locator('[data-sonner-toast][data-type="success"]');
+      await expect(successToast).toBeVisible();
+      const message = await successToast.textContent();
+      expect(message).toBeDefined();
+      expect(message?.length).toBeGreaterThan(0);
+      // 验证消息包含激活相关的关键词
+      expect(message).toMatch(/激活|成功|已激活/);
+    });
+
+    test('激活确认对话框应该正确显示', async ({ orderManagementPage, page }) => {
+      await orderManagementPage.openActivateDialog(draftOrderName);
+
+      // 验证对话框可见
+      const dialog = page.locator('[role="alertdialog"]');
+      await expect(dialog).toBeVisible();
+
+      // 验证确认按钮存在(支持多种可能的按钮名称)
+      const confirmButton = page.locator('[role="alertdialog"]').getByRole('button', {
+        name: /^(确认激活|激活|确定|确认)$/
+      });
+      await expect(confirmButton).toBeVisible();
+
+      // 验证取消按钮存在
+      const cancelButton = page.locator('[role="alertdialog"]').getByRole('button', { name: '取消' });
+      await expect(cancelButton).toBeVisible();
+
+      // 取消激活以清理
+      await page.keyboard.press('Escape');
+    });
+  });
+
+  test.describe('关闭进行中订单', () => {
+    let inProgressOrderName: string;
+
+    test.beforeEach(async ({ adminLoginPage, orderManagementPage, testUsers }) => {
+      // 以管理员身份登录后台
+      await adminLoginPage.goto();
+      await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
+      await adminLoginPage.expectLoginSuccess();
+      await orderManagementPage.goto();
+
+      // 创建一个草稿订单然后激活为进行中状态
+      const timestamp = Date.now();
+      inProgressOrderName = `关闭测试_${timestamp}`;
+
+      const created = await createTestOrder(orderManagementPage.page, inProgressOrderName);
+
+      if (!created) {
+        test.skip(true, '没有残疾人数据,无法创建测试订单');
+      }
+
+      // 验证订单出现在列表中
+      await expect(async () => {
+        const exists = await orderManagementPage.orderExists(inProgressOrderName);
+        expect(exists).toBe(true);
+      }).toPass({ timeout: 5000 });
+
+      // 激活订单到进行中状态
+      await orderManagementPage.activateOrder(inProgressOrderName);
+
+      // 验证状态变为进行中
+      await expect(async () => {
+        const currentStatus = await orderManagementPage.getOrderStatus(inProgressOrderName);
+        expect(currentStatus).toBe(ORDER_STATUS.IN_PROGRESS);
+      }).toPass({ timeout: 5000 });
+
+      console.debug(`✓ 订单已激活为进行中状态`);
+    });
+
+    test('应该成功关闭进行中订单', async ({ orderManagementPage }) => {
+      // 执行关闭操作
+      const success = await orderManagementPage.closeOrder(inProgressOrderName);
+
+      // 验证关闭成功
+      expect(success).toBe(true);
+
+      // 验证状态从进行中变为已完成
+      await expect(async () => {
+        const currentStatus = await orderManagementPage.getOrderStatus(inProgressOrderName);
+        expect(currentStatus).toBe(ORDER_STATUS.COMPLETED);
+      }).toPass({ timeout: 5000 });
+    });
+
+    test('关闭后应该显示成功提示', async ({ orderManagementPage }) => {
+      await orderManagementPage.closeOrder(inProgressOrderName);
+
+      // 验证 Toast 成功消息
+      const successToast = orderManagementPage.page.locator('[data-sonner-toast][data-type="success"]');
+      await expect(successToast).toBeVisible();
+      const message = await successToast.textContent();
+      expect(message).toBeDefined();
+      expect(message?.length).toBeGreaterThan(0);
+      // 验证消息包含关闭相关的关键词
+      expect(message).toMatch(/关闭|完成|成功|已关闭|已完成/);
+    });
+
+    test('关闭确认对话框应该正确显示', async ({ orderManagementPage, page }) => {
+      await orderManagementPage.openCloseDialog(inProgressOrderName);
+
+      // 验证对话框可见
+      const dialog = page.locator('[role="alertdialog"]');
+      await expect(dialog).toBeVisible();
+
+      // 验证确认按钮存在(支持多种可能的按钮名称)
+      const confirmButton = page.locator('[role="alertdialog"]').getByRole('button', {
+        name: /^(确认关闭|关闭|确定|确认)$/
+      });
+      await expect(confirmButton).toBeVisible();
+
+      // 验证取消按钮存在
+      const cancelButton = page.locator('[role="alertdialog"]').getByRole('button', { name: '取消' });
+      await expect(cancelButton).toBeVisible();
+
+      // 取消关闭以清理
+      await page.keyboard.press('Escape');
+    });
+  });
+
+  test.describe('状态限制验证', () => {
+    let testOrderName: string;
+    let currentStatus: OrderStatus;
+    let shouldSkipTests = false;
+
+    test.beforeEach(async ({ adminLoginPage, orderManagementPage, testUsers }) => {
+      // 以管理员身份登录后台
+      await adminLoginPage.goto();
+      await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
+      await adminLoginPage.expectLoginSuccess();
+      await orderManagementPage.goto();
+
+      // 尝试使用现有订单
+      const existingOrder = await getFirstOrderName(orderManagementPage.page);
+
+      if (existingOrder) {
+        testOrderName = existingOrder;
+        currentStatus = (await orderManagementPage.getOrderStatus(testOrderName)) || ORDER_STATUS.DRAFT;
+        console.debug(`✓ 使用现有订单: ${testOrderName}, 状态: ${ORDER_STATUS_LABELS[currentStatus]}`);
+      } else {
+        // 如果没有现有订单,创建一个
+        const timestamp = Date.now();
+        testOrderName = `状态限制测试_${timestamp}`;
+
+        const created = await createTestOrder(orderManagementPage.page, testOrderName);
+
+        if (!created) {
+          shouldSkipTests = true;
+          test.skip(true, '没有残疾人数据,无法创建测试订单');
+          return;
+        }
+
+        // 验证订单出现在列表中
+        await expect(async () => {
+          const exists = await orderManagementPage.orderExists(testOrderName);
+          expect(exists).toBe(true);
+        }).toPass({ timeout: 5000 });
+
+        currentStatus = ORDER_STATUS.DRAFT;
+      }
+    });
+
+    test('不能激活非草稿状态的订单', async ({ orderManagementPage }) => {
+      if (shouldSkipTests) {
+        test.skip(true, '测试数据不可用');
+        return;
+      }
+
+      // 如果当前是草稿状态,先激活为进行中
+      if (currentStatus === ORDER_STATUS.DRAFT) {
+        await orderManagementPage.activateOrder(testOrderName);
+        currentStatus = ORDER_STATUS.IN_PROGRESS;
+        console.debug(`✓ 已激活订单用于测试`);
+      }
+
+      // 对于非草稿状态的订单,激活按钮应该被禁用或不可见
+      const isActivatedEnabled = await orderManagementPage.isActivateButtonEnabled(testOrderName);
+
+      // 根据当前状态验证
+      if (currentStatus === ORDER_STATUS.IN_PROGRESS ||
+          currentStatus === ORDER_STATUS.COMPLETED ||
+          currentStatus === ORDER_STATUS.CONFIRMED) {
+        // 非草稿状态不应该能激活
+        expect(isActivatedEnabled).toBe(false);
+        console.debug(`✓ 状态 ${ORDER_STATUS_LABELS[currentStatus]} 的订单不能激活`);
+      }
+    });
+
+    test('不能关闭非进行中状态的订单', async ({ orderManagementPage }) => {
+      if (shouldSkipTests) {
+        test.skip(true, '测试数据不可用');
+        return;
+      }
+
+      // 对于非进行中状态的订单,关闭按钮应该被禁用或不可见
+      const isCloseEnabled = await orderManagementPage.isCloseButtonEnabled(testOrderName);
+
+      // 根据当前状态验证
+      if (currentStatus === ORDER_STATUS.DRAFT ||
+          currentStatus === ORDER_STATUS.COMPLETED ||
+          currentStatus === ORDER_STATUS.CONFIRMED) {
+        // 非进行中状态不应该能关闭
+        expect(isCloseEnabled).toBe(false);
+        console.debug(`✓ 状态 ${ORDER_STATUS_LABELS[currentStatus]} 的订单不能关闭`);
+      }
+    });
+
+    test('已完成状态不能再次操作', async ({ orderManagementPage }) => {
+      if (shouldSkipTests) {
+        test.skip(true, '测试数据不可用');
+        return;
+      }
+
+      // 如果当前不是已完成状态,先操作到已完成
+      if (currentStatus === ORDER_STATUS.DRAFT) {
+        await orderManagementPage.activateOrder(testOrderName);
+        await orderManagementPage.closeOrder(testOrderName);
+        console.debug(`✓ 已将订单操作到已完成状态`);
+      } else if (currentStatus === ORDER_STATUS.IN_PROGRESS) {
+        await orderManagementPage.closeOrder(testOrderName);
+        console.debug(`✓ 已关闭订单`);
+      }
+
+      // 验证订单状态为已完成
+      await expect(async () => {
+        const status = await orderManagementPage.getOrderStatus(testOrderName);
+        expect(status).toBe(ORDER_STATUS.COMPLETED);
+      }).toPass({ timeout: 5000 });
+
+      // 已完成状态的订单不能激活也不能关闭
+      const isActivateEnabled = await orderManagementPage.isActivateButtonEnabled(testOrderName);
+      const isCloseEnabled = await orderManagementPage.isCloseButtonEnabled(testOrderName);
+
+      expect(isActivateEnabled).toBe(false);
+      expect(isCloseEnabled).toBe(false);
+      console.debug(`✓ 已完成状态的订单不能激活或关闭`);
+    });
+  });
+
+  test.describe('完整状态流转流程', () => {
+    test('应该支持草稿→进行中→已完成的完整流转', async ({ adminLoginPage, orderManagementPage, testUsers }) => {
+      // 以管理员身份登录后台
+      await adminLoginPage.goto();
+      await adminLoginPage.login(testUsers.admin.username, testUsers.admin.password);
+      await adminLoginPage.expectLoginSuccess();
+      await orderManagementPage.goto();
+
+      // 创建草稿订单
+      const timestamp = Date.now();
+      const orderName = `完整流转测试_${timestamp}`;
+
+      const created = await createTestOrder(orderManagementPage.page, orderName);
+
+      if (!created) {
+        test.skip(true, '没有残疾人数据,无法创建测试订单');
+      }
+
+      // 验证订单出现在列表中
+      await expect(async () => {
+        const exists = await orderManagementPage.orderExists(orderName);
+        expect(exists).toBe(true);
+      }).toPass({ timeout: 5000 });
+
+      // 验证初始状态为草稿
+      let currentStatus = await orderManagementPage.getOrderStatus(orderName);
+      expect(currentStatus).toBe(ORDER_STATUS.DRAFT);
+      console.debug(`✓ 初始状态: ${ORDER_STATUS_LABELS[ORDER_STATUS.DRAFT]}`);
+
+      // 激活订单
+      await orderManagementPage.activateOrder(orderName);
+      currentStatus = await orderManagementPage.getOrderStatus(orderName);
+      expect(currentStatus).toBe(ORDER_STATUS.IN_PROGRESS);
+      console.debug(`✓ 激活后状态: ${ORDER_STATUS_LABELS[ORDER_STATUS.IN_PROGRESS]}`);
+
+      // 关闭订单
+      await orderManagementPage.closeOrder(orderName);
+      currentStatus = await orderManagementPage.getOrderStatus(orderName);
+      expect(currentStatus).toBe(ORDER_STATUS.COMPLETED);
+      console.debug(`✓ 关闭后状态: ${ORDER_STATUS_LABELS[ORDER_STATUS.COMPLETED]}`);
+    });
+  });
+});