10-7-order-status-tests.md 13 KB

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

Status: done

Story

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

Acceptance Criteria

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

  1. 激活草稿订单

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

    • 激活订单后
    • 点击关闭订单按钮
    • 验证确认对话框显示
    • 确认关闭
    • 验证订单状态变为已完成
  3. 状态限制验证

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

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

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)

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):

// 订单状态常量
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. 激活订单方法:

    /**
    * 打开激活订单确认对话框
    * @param orderName 订单名称
    */
    async openActivateDialog(orderName: string): Promise<void>
    
    /**
    * 确认激活订单
    */
    async confirmActivate(): Promise<void>
    
    /**
    * 激活订单(完整流程)
    * @param orderName 订单名称
    * @returns 是否成功激活
    */
    async activateOrder(orderName: string): Promise<boolean>
    
  2. 关闭订单方法:

    /**
    * 打开关闭订单确认对话框
    * @param orderName 订单名称
    */
    async openCloseDialog(orderName: string): Promise<void>
    
    /**
    * 确认关闭订单
    */
    async confirmClose(): Promise<void>
    
    /**
    * 关闭订单(完整流程)
    * @param orderName 订单名称
    * @returns 是否成功关闭
    */
    async closeOrder(orderName: string): Promise<boolean>
    
  3. 状态获取方法:

    /**
    * 获取订单的当前状态(从列表页面)
    * @param orderName 订单名称
    * @returns 订单状态值
    */
    async getOrderStatus(orderName: string): Promise<OrderStatus | null>
    
    /**
    * 验证订单状态
    * @param orderName 订单名称
    * @param expectedStatus 期望的状态
    */
    async expectOrderStatus(orderName: string, expectedStatus: OrderStatus): Promise<void>
    
  4. 按钮状态验证方法:

    /**
    * 检查激活按钮是否可用
    * @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_STATUSORDER_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 需求来源:

Page Object 现有实现:

前序 Story 学习:

项目上下文:

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 个测试用例