|
|
@@ -0,0 +1,353 @@
|
|
|
+# Story 10.5: 编写编辑订单测试
|
|
|
+
|
|
|
+Status: ready-for-dev
|
|
|
+
|
|
|
+<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
|
|
|
+
|
|
|
+## 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. **打开编辑对话框:**
|
|
|
+ ```typescript
|
|
|
+ async openEditDialog(orderName: string): Promise<void>
|
|
|
+ ```
|
|
|
+ - 找到订单行并点击编辑按钮
|
|
|
+ - 等待对话框出现
|
|
|
+
|
|
|
+2. **填写订单表单:**
|
|
|
+ ```typescript
|
|
|
+ async fillOrderForm(data: OrderData): Promise<void>
|
|
|
+ ```
|
|
|
+ - 支持填写订单名称、预计开始日期
|
|
|
+ - 支持选择平台、公司、渠道
|
|
|
+ - 支持选择订单状态、工作状态
|
|
|
+ - 使用 `selectRadixOption` 工具选择下拉选项
|
|
|
+
|
|
|
+3. **提交表单:**
|
|
|
+ ```typescript
|
|
|
+ async submitForm(): Promise<FormSubmitResult>
|
|
|
+ ```
|
|
|
+ - 返回提交结果(成功/失败、Toast 消息、网络响应)
|
|
|
+
|
|
|
+4. **编辑订单完整流程:**
|
|
|
+ ```typescript
|
|
|
+ async editOrder(orderName: string, data: OrderData): Promise<FormSubmitResult>
|
|
|
+ ```
|
|
|
+ - 组合方法:打开对话框 → 填写表单 → 提交 → 等待关闭
|
|
|
+
|
|
|
+### 测试数据策略
|
|
|
+
|
|
|
+**创建测试订单:**
|
|
|
+编辑测试需要先有可编辑的订单。参考 Story 10.3 的测试数据策略:
|
|
|
+
|
|
|
+```typescript
|
|
|
+// 使用时间戳创建唯一订单名称
|
|
|
+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(订单筛选测试)的测试结构:
|
|
|
+
|
|
|
+```typescript
|
|
|
+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);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更多测试...
|
|
|
+ });
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+### 技术要求
|
|
|
+
|
|
|
+**导入依赖:**
|
|
|
+```typescript
|
|
|
+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):**
|
|
|
+```typescript
|
|
|
+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 注释
|
|
|
+
|
|
|
+### 测试运行命令
|
|
|
+
|
|
|
+```bash
|
|
|
+# 在 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` 工具选择下拉选项
|
|
|
+- 日期处理使用本地时间格式
|
|
|
+
|
|
|
+### 关键代码模式
|
|
|
+
|
|
|
+**表单数据接口:**
|
|
|
+```typescript
|
|
|
+interface OrderData {
|
|
|
+ name: string;
|
|
|
+ expectedStartDate?: string;
|
|
|
+ platformId?: number;
|
|
|
+ platformName?: string;
|
|
|
+ companyId?: number;
|
|
|
+ companyName?: string;
|
|
|
+ channelId?: number;
|
|
|
+ channelName?: string;
|
|
|
+ status?: OrderStatus;
|
|
|
+ workStatus?: WorkStatus;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**表单提交结果接口:**
|
|
|
+```typescript
|
|
|
+interface FormSubmitResult {
|
|
|
+ success: boolean;
|
|
|
+ hasError: boolean;
|
|
|
+ hasSuccess: boolean;
|
|
|
+ errorMessage?: string;
|
|
|
+ successMessage?: string;
|
|
|
+ responses?: NetworkResponse[];
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### References
|
|
|
+
|
|
|
+- [Source: _bmad-output/planning-artifacts/epics.md#Story 10.5](../planning-artifacts/epics.md)
|
|
|
+- [Source: _bmad-output/planning-artifacts/prd.md](../planning-artifacts/prd.md)
|
|
|
+- [Source: _bmad-output/planning-artifacts/architecture.md](../planning-artifacts/architecture.md)
|
|
|
+- [Source: web/tests/e2e/pages/admin/order-management.page.ts](../../web/tests/e2e/pages/admin/order-management.page.ts)
|
|
|
+- [Source: _bmad-output/implementation-artifacts/10-1-order-page-object.md](10-1-order-page-object.md)
|
|
|
+- [Source: _bmad-output/implementation-artifacts/10-2-order-list-tests.md](10-2-order-list-tests.md)
|
|
|
+- [Source: _bmad-output/implementation-artifacts/10-3-order-filter-tests.md](10-3-order-filter-tests.md)
|
|
|
+
|
|
|
+## Dev Agent Record
|
|
|
+
|
|
|
+### Agent Model Used
|
|
|
+
|
|
|
+claude-opus-4-5-20251101
|
|
|
+
|
|
|
+### Debug Log References
|
|
|
+
|
|
|
+### Completion Notes List
|
|
|
+
|
|
|
+### File List
|