10-5-order-edit-tests.md 11 KB

Story 10.5: 编写编辑订单测试

Status: ready-for-dev

Story

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

Acceptance Criteria

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

  1. 编辑订单基本信息

    • 修改订单名称
    • 修改预计开始日期
    • 验证修改后数据更新
  2. 编辑订单关联信息

    • 更换平台
    • 更换公司
    • 更换渠道
    • 验证关联更新正确
  3. 编辑后验证列表更新

    • 编辑订单后返回列表
    • 验证列表中显示更新后的信息

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

Tasks / Subtasks

  • 创建编辑订单测试文件 (AC: When)
    • 创建 web/tests/e2e/specs/admin/order-edit.spec.ts
    • 导入必要的测试依赖(Playwright fixtures、OrderManagementPage)
    • 配置测试文件的基本结构
  • 编写编辑订单基本信息测试 (AC: Then #1)
    • 测试修改订单名称
    • 测试修改预计开始日期
    • 验证修改后数据正确更新
  • 编写编辑订单关联信息测试 (AC: Then #2)
    • 测试更换平台
    • 测试更换公司
    • 测试更换渠道
    • 验证关联更新正确
    • 使用 selectRadixOption 工具
  • 编写编辑后列表更新验证测试 (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 情报 (Story 10.1, 10.2, 10.3)

Page Object 已有的编辑功能:

web/tests/e2e/pages/admin/order-management.page.ts 包含以下编辑相关方法:

  1. 打开编辑对话框:

    async openEditDialog(orderName: string): Promise<void>
    
    • 找到订单行并点击编辑按钮
    • 等待对话框出现
  2. 填写订单表单:

    async fillOrderForm(data: OrderData): Promise<void>
    
    • 支持填写订单名称、预计开始日期
    • 支持选择平台、公司、渠道
    • 支持选择订单状态、工作状态
    • 使用 selectRadixOption 工具选择下拉选项
  3. 提交表单:

    async submitForm(): Promise<FormSubmitResult>
    
    • 返回提交结果(成功/失败、Toast 消息、网络响应)
  4. 编辑订单完整流程:

    async editOrder(orderName: string, data: OrderData): Promise<FormSubmitResult>
    
    • 组合方法:打开对话框 → 填写表单 → 提交 → 等待关闭

测试数据策略

创建测试订单: 编辑测试需要先有可编辑的订单。参考 Story 10.3 的测试数据策略:

// 使用时间戳创建唯一订单名称
const timestamp = Date.now();
const testOrderName = `编辑测试订单_${timestamp}`;

// 先创建订单
await orderManagementPage.createOrder({
  name: testOrderName,
  expectedStartDate: '2025-01-15',
  platformName: '58同城',  // 可选
  companyName: '测试公司',    // 可选
  channelName: '网络招聘',    // 可选
});

测试文件结构参考

参考 Story 10.2(订单列表查看测试)和 Story 10.3(订单筛选测试)的测试结构:

import { test, expect } from '../../utils/test-setup';
import { OrderManagementPage } from '../../pages/admin/order-management.page';
import { selectRadixOption } from '@d8d/e2e-test-utils';

test.describe.serial('编辑订单测试', () => {
  let testOrderName: string;

  test.beforeEach(async ({ adminLoginPage, orderManagementPage }) => {
    await adminLoginPage.goto();
    await adminLoginPage.login('admin', 'admin123');
    await orderManagementPage.goto();

    // 创建测试订单
    const timestamp = Date.now();
    testOrderName = `编辑测试_${timestamp}`;
    await orderManagementPage.createOrder({
      name: testOrderName,
      expectedStartDate: '2025-01-15',
    });
  });

  test.describe('编辑订单基本信息', () => {
    test('应该能修改订单名称', async ({ orderManagementPage }) => {
      // 编辑订单名称
      const newName = `${testOrderName}_已修改`;
      await orderManagementPage.editOrder(testOrderName, {
        name: newName,
      });

      // 验证列表中显示新名称
      expect(await orderManagementPage.orderExists(newName)).toBe(true);
    });

    // 更多测试...
  });
});

技术要求

导入依赖:

import { test, expect } from '../../utils/test-setup';
import { OrderManagementPage, ORDER_STATUS, WORK_STATUS } from '../../pages/admin/order-management.page';
import { selectRadixOption } from '@d8d/e2e-test-utils';

测试 Fixtures:

  • 使用 adminLoginPage fixture 进行登录
  • 使用 orderManagementPage fixture 操作页面
  • 使用 test.describe.serial() 确保测试按顺序执行

断言策略:

  • 验证编辑后返回正确的 FormSubmitResult
  • 验证列表中显示更新后的信息
  • 验证 Toast 成功消息显示

工具使用

Select 工具使用(来自 Epic 1, 2):

import { selectRadixOption } from '@d8d/e2e-test-utils';

// 选择平台
await selectRadixOption(page, '平台', '58同城');

// 选择公司
await selectRadixOption(page, '公司', '新公司');

// 选择渠道
await selectRadixOption(page, '渠道', '现场招聘');

测试标准参考

遵循以下测试标准文档:

  • docs/standards/testing-standards.md - 测试规范
  • docs/standards/web-ui-testing-standards.md - Web UI 测试规范
  • docs/standards/e2e-radix-testing.md - Radix UI E2E 测试标准

选择器优先级:

  1. data-testid - 最高优先级
  2. aria-label + role
  3. text content + role - 兜底

Project Structure Notes

文件位置:

  • 测试文件: web/tests/e2e/specs/admin/order-edit.spec.ts
  • Page Object: web/tests/e2e/pages/admin/order-management.page.ts
  • Fixtures 目录: web/tests/e2e/fixtures/

对齐统一项目结构:

  • 遵循 project-context.md 中的 TypeScript 严格模式规则
  • 函数参数、返回值必须有明确类型注解
  • 禁止使用 any 类型
  • 公共 API 必须包含完整 JSDoc 注释

测试运行命令

# 在 web 目录下运行单个测试文件
cd web
pnpm test:e2e:chromium order-edit

# 快速失败模式(推荐调试时使用)
timeout 60 pnpm test:e2e:chromium order-edit

测试注意事项

编辑对话框交互:

  • 编辑按钮使用文本"编辑"定位
  • 编辑对话框与创建对话框可能使用同一组件
  • 提交按钮文本可能是"更新"、"保存"或"确定"

表单预填充:

  • 编辑对话框打开时,表单应预填充现有数据
  • 需要验证预填充数据的正确性

测试数据清理:

  • 每个测试创建独立的测试订单
  • 使用时间戳确保订单名称唯一
  • 测试结束后不需要清理(可在后续测试中删除)

断言策略:

  • 验证 FormSubmitResult.success 为 true
  • 验证 Toast 成功消息显示
  • 验证列表中更新后的订单信息
  • 验证旧名称不再存在于列表中(修改名称时)

测试覆盖场景清单

编辑订单基本信息:

  • 修改订单名称
  • 修改预计开始日期
  • 同时修改多个基本信息

编辑订单关联信息:

  • 更换平台
  • 更换公司
  • 更换渠道
  • 同时更换多个关联信息

编辑后列表更新验证:

  • 验证列表中显示新名称
  • 验证列表中显示新日期
  • 验证列表中显示新平台
  • 验证列表中显示新公司
  • 验证列表中显示新渠道

边界条件测试(可选):

  • 编辑不存在的订单
  • 清空必填字段后编辑
  • 编辑为已存在的订单名称

前序 Story 经验总结 (Story 10.2, 10.3)

从 Story 10.2(订单列表测试)学到的经验:

  • 列表表格使用 table tbody tr 选择器定位行
  • 订单状态徽章使用 getByText 精确匹配
  • 工作状态徽章使用 getByText 精确匹配

从 Story 10.3(订单筛选测试)学到的经验:

  • 对标签使用 locator('label').filter({ hasText: ... }) 避免与表头冲突
  • 对操作添加 waitForLoadState 超时处理(可能不触发网络请求)
  • 使用 selectRadixOption 工具选择下拉选项
  • 日期处理使用本地时间格式

关键代码模式

表单数据接口:

interface OrderData {
  name: string;
  expectedStartDate?: string;
  platformId?: number;
  platformName?: string;
  companyId?: number;
  companyName?: string;
  channelId?: number;
  channelName?: string;
  status?: OrderStatus;
  workStatus?: WorkStatus;
}

表单提交结果接口:

interface FormSubmitResult {
  success: boolean;
  hasError: boolean;
  hasSuccess: boolean;
  errorMessage?: string;
  successMessage?: string;
  responses?: NetworkResponse[];
}

References

Dev Agent Record

Agent Model Used

claude-opus-4-5-20251101

Debug Log References

Completion Notes List

File List