|
|
@@ -0,0 +1,347 @@
|
|
|
+# Story 10.9: 编写人员关联功能测试
|
|
|
+
|
|
|
+Status: ready-for-dev
|
|
|
+
|
|
|
+<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
|
|
|
+
|
|
|
+## Story
|
|
|
+
|
|
|
+作为测试开发者,
|
|
|
+我想要编写人员关联功能的 E2E 测试,
|
|
|
+以便验证添加人员到订单和管理工作状态的功能。
|
|
|
+
|
|
|
+## Acceptance Criteria
|
|
|
+
|
|
|
+**Given** 订单管理 Page Object 已创建
|
|
|
+**When** 编写人员关联测试用例
|
|
|
+**Then** 包含以下测试场景:
|
|
|
+
|
|
|
+1. **添加人员到订单**
|
|
|
+ - 打开订单人员管理对话框
|
|
|
+ - 选择残疾人
|
|
|
+ - 设置入职日期和薪资
|
|
|
+ - 验证人员添加成功
|
|
|
+ - 验证人员出现在订单详情中
|
|
|
+
|
|
|
+2. **管理工作状态**
|
|
|
+ - 修改人员工作状态(未就业→待就业→已就业)
|
|
|
+ - 验证状态更新正确
|
|
|
+
|
|
|
+3. **设置实际入职日期**
|
|
|
+ - 设置人员的实际入职日期
|
|
|
+ - 验证日期保存正确
|
|
|
+
|
|
|
+4. **人员离职**
|
|
|
+ - 设置人员为已离职状态
|
|
|
+ - 设置离职日期
|
|
|
+ - 验证离职信息保存正确
|
|
|
+
|
|
|
+**测试文件:** `web/tests/e2e/specs/admin/order-person.spec.ts`
|
|
|
+
|
|
|
+## Tasks / Subtasks
|
|
|
+
|
|
|
+- [ ] 补充 Page Object 人员管理方法 (AC: When)
|
|
|
+ - [ ] 验证并修复 `addPersonToOrder()` 方法中的残疾人选择逻辑
|
|
|
+ - [ ] 添加支持选择残疾人对话框的辅助方法(如需要)
|
|
|
+ - [ ] 添加设置实际入职日期的方法
|
|
|
+ - [ ] 添加设置离职日期的方法
|
|
|
+- [ ] 创建人员关联测试文件 (AC: When)
|
|
|
+ - [ ] 创建 `web/tests/e2e/specs/admin/order-person.spec.ts`
|
|
|
+ - [ ] 导入必要的测试依赖和 Page Object
|
|
|
+ - [ ] 配置测试 Fixtures(adminLoginPage, orderManagementPage, disabilityPersonPage)
|
|
|
+- [ ] 编写添加人员到订单测试 (AC: Then #1)
|
|
|
+ - [ ] 测试打开订单人员管理对话框
|
|
|
+ - [ ] 测试选择残疾人(关键:修复选择残疾人对话框的交互)
|
|
|
+ - [ ] 测试设置入职日期和薪资
|
|
|
+ - [ ] 测试验证人员添加成功(Toast 消息 + 详情列表)
|
|
|
+ - [ ] 测试验证人员出现在订单详情中
|
|
|
+- [ ] 编写管理工作状态测试 (AC: Then #2)
|
|
|
+ - [ ] 测试修改人员工作状态(未就业→待就业→已就业)
|
|
|
+ - [ ] 测试验证状态更新正确(从人员列表中验证)
|
|
|
+ - [ ] 测试工作状态流转的正确性
|
|
|
+- [ ] 编写设置实际入职日期测试 (AC: Then #3)
|
|
|
+ - [ ] 测试设置人员的实际入职日期
|
|
|
+ - [ ] 测试验证日期保存正确
|
|
|
+ - [ ] 测试验证日期格式正确(YYYY-MM-DD)
|
|
|
+- [ ] 编写人员离职测试 (AC: Then #4)
|
|
|
+ - [ ] 测试设置人员为已离职状态
|
|
|
+ - [ ] 测试设置离职日期
|
|
|
+ - [ ] 测试验证离职信息保存正确
|
|
|
+ - [ ] 测试验证离职后人员状态显示
|
|
|
+- [ ] 确保所有测试通过 (AC: And)
|
|
|
+ - [ ] 运行测试并修复问题
|
|
|
+ - [ ] 验证测试稳定性(连续运行 3 次)
|
|
|
+ - [ ] 启用 Story 10.8 中被跳过的测试(依赖此 Story 完成)
|
|
|
+
|
|
|
+## 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 - 10.7: ✅ 已完成(订单列表、筛选、CRUD、状态流转测试)
|
|
|
+- Story 10.8: 🔄 进行中(订单详情查看测试 - 依赖本 Story 完成选择残疾人功能)
|
|
|
+
|
|
|
+### 前序 Story 关键发现 (Story 10.8)
|
|
|
+
|
|
|
+**从 Story 10.8 学到的经验:**
|
|
|
+
|
|
|
+1. **关键阻塞问题 - 选择残疾人功能未实现**:
|
|
|
+ - Story 10.8 中无法在"选择残疾人"对话框中找到已创建的残疾人数据
|
|
|
+ - **原因**: Story 10.9 ("编写人员关联功能测试") 正是处理"选择残疾人"功能的地方
|
|
|
+ - **影响**: Story 10.8 中所有需要创建订单的测试被标记为 `test.skip()`
|
|
|
+ - **解决方案**: 本 Story 需要正确实现选择残疾人对话框的交互
|
|
|
+
|
|
|
+2. **Page Object 已有方法**:
|
|
|
+ - `openPersonManagementDialog(orderName?)`: 打开人员管理对话框
|
|
|
+ - `addPersonToOrder(personData)`: 添加人员到订单(需验证选择残疾人逻辑)
|
|
|
+ - `updatePersonWorkStatus(personName, newStatus)`: 修改人员工作状态
|
|
|
+ - `getPersonListFromDetail()`: 从订单详情对话框中获取关联人员列表(已实现)
|
|
|
+
|
|
|
+3. **测试数据准备**:
|
|
|
+ - Story 10.8 中在 `beforeEach` 创建残疾人测试数据(使用 `disabilityPersonPage`)
|
|
|
+ - 使用时间戳 + 随机数确保数据唯一性(如 `测试残疾人_${timestamp}_${random}`)
|
|
|
+
|
|
|
+4. **遵循 Epic 9.6 并行执行决策**:
|
|
|
+ - 测试不使用 `test.describe.serial`
|
|
|
+ - 每个测试创建独立的测试数据
|
|
|
+ - 测试执行后清理数据(如可能)
|
|
|
+
|
|
|
+### Page Object 已有功能分析
|
|
|
+
|
|
|
+**订单人员管理相关方法** (`web/tests/e2e/pages/admin/order-management.page.ts`):
|
|
|
+
|
|
|
+| 方法 | 说明 | 当前状态 | 本 Story 需求 |
|
|
|
+|------|------|---------|--------------|
|
|
|
+| `openPersonManagementDialog(orderName?)` | 打开人员管理对话框 | 已实现 | 可直接使用 |
|
|
|
+| `addPersonToOrder(personData)` | 添加人员到订单 | 已实现 | **需验证/修复**选择残疾人逻辑 |
|
|
|
+| `updatePersonWorkStatus(personName, newStatus)` | 修改人员工作状态 | 已实现 | 可能需验证 |
|
|
|
+| `getPersonListFromDetail()` | 获取人员列表 | 已实现 | 验证人员添加后检查 |
|
|
|
+
|
|
|
+**`addPersonToOrder()` 方法当前实现(行 844-892):**
|
|
|
+
|
|
|
+```typescript
|
|
|
+async addPersonToOrder(personData: OrderPersonData) {
|
|
|
+ // 点击添加人员按钮
|
|
|
+ const addButton = this.page.getByRole('button', { name: /添加人员|新增人员/ });
|
|
|
+ await addButton.click();
|
|
|
+ await this.page.waitForTimeout(300);
|
|
|
+
|
|
|
+ // 选择残疾人(支持通过名称选择)
|
|
|
+ if (personData.disabledPersonName) {
|
|
|
+ await selectRadixOption(this.page, '残疾人|选择残疾人', personData.disabledPersonName);
|
|
|
+ } else if (personData.disabledPersonId) {
|
|
|
+ // 如果只提供了 ID,尝试在对话框中选择第一个残疾人
|
|
|
+ const firstCheckbox = this.page.locator('[role="dialog"]').locator('table tbody tr').first().locator('input[type="checkbox"]').first();
|
|
|
+ try {
|
|
|
+ await firstCheckbox.waitFor({ state: 'visible', timeout: 3000 });
|
|
|
+ await firstCheckbox.check();
|
|
|
+ } catch {
|
|
|
+ console.debug('没有可用的残疾人数据');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // ... 填写入职日期、薪资、工作状态等
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**潜在问题**:
|
|
|
+- 使用 `selectRadixOption()` 选择残疾人,但"选择残疾人"可能不是标准的 Radix Select 组件
|
|
|
+- 可能是自定义对话框,需要直接点击行或复选框
|
|
|
+- 需要通过实际 UI 探索确定正确的选择模式
|
|
|
+
|
|
|
+**已有的订单人员数据接口**:
|
|
|
+```typescript
|
|
|
+export interface OrderPersonData {
|
|
|
+ disabledPersonId: number;
|
|
|
+ disabledPersonName?: string;
|
|
|
+ hireDate?: string;
|
|
|
+ salary?: number;
|
|
|
+ workStatus?: WorkStatus;
|
|
|
+ actualHireDate?: string; // 实际入职日期 - 可能需添加
|
|
|
+ resignDate?: string; // 离职日期 - 可能需添加
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 测试覆盖场景清单
|
|
|
+
|
|
|
+**添加人员到订单:**
|
|
|
+- [ ] 打开订单人员管理对话框
|
|
|
+- [ ] **[关键]** 在"选择残疾人"对话框中找到并选择已创建的残疾人
|
|
|
+- [ ] 填写入职日期
|
|
|
+- [ ] 填写薪资
|
|
|
+- [ ] 选择工作状态(默认未就业)
|
|
|
+- [ ] 提交并验证成功 Toast 消息
|
|
|
+- [ ] 在订单详情中验证人员显示正确
|
|
|
+
|
|
|
+**管理工作状态:**
|
|
|
+- [ ] 修改人员工作状态:未就业 → 待就业
|
|
|
+- [ ] 修改人员工作状态:待就业 → 已就业
|
|
|
+- [ ] 修改人员工作状态:已就业 → 已离职
|
|
|
+- [ ] 验证状态更新后在人员列表中显示正确
|
|
|
+- [ ] 验证状态流转的正确性(不能跳过状态)
|
|
|
+
|
|
|
+**设置实际入职日期:**
|
|
|
+- [ ] 在人员管理中设置实际入职日期
|
|
|
+- [ ] 验证日期保存成功
|
|
|
+- [ ] 验证日期格式正确(YYYY-MM-DD)
|
|
|
+
|
|
|
+**人员离职:**
|
|
|
+- [ ] 设置人员工作状态为已离职
|
|
|
+- [ ] 设置离职日期
|
|
|
+- [ ] 验证离职信息保存成功
|
|
|
+- [ ] 验证离职后状态显示为"已离职"
|
|
|
+
|
|
|
+### UI 结构探索要点
|
|
|
+
|
|
|
+**人员管理对话框结构假设(需要验证):**
|
|
|
+
|
|
|
+1. **打开方式**:
|
|
|
+ - 从订单列表页:点击订单行的"人员"按钮
|
|
|
+ - 从订单详情页:点击"人员管理"或"添加人员"按钮
|
|
|
+
|
|
|
+2. **人员列表区域**:
|
|
|
+ - 可能使用表格展示已关联人员
|
|
|
+ - 每行显示人员姓名、工作状态、入职日期、薪资等
|
|
|
+ - 可能有"添加人员"按钮
|
|
|
+ - 可能有"编辑"、"删除"操作按钮
|
|
|
+
|
|
|
+3. **添加人员对话框**:
|
|
|
+ - **关键组件**: 选择残疾人(可能是对话框或下拉选择器)
|
|
|
+ - 入职日期输入框(日期选择器)
|
|
|
+ - 薪资输入框(数字类型)
|
|
|
+ - 工作状态选择器(下拉选择)
|
|
|
+ - 可能还有实际入职日期、离职日期等字段
|
|
|
+ - 提交/取消按钮
|
|
|
+
|
|
|
+4. **"选择残疾人"对话框结构(关键探索点)**:
|
|
|
+ - **假设1**: 标准 Radix Select 下拉框
|
|
|
+ - 使用 `selectRadixOption()` 直接选择
|
|
|
+ - **假设2**: 自定义对话框
|
|
|
+ - 显示残疾人列表(表格或卡片)
|
|
|
+ - 使用复选框或单选框选择
|
|
|
+ - 需要点击特定行来选择
|
|
|
+ - **假设3**: 搜索 + 选择组合
|
|
|
+ - 有搜索框输入姓名
|
|
|
+ - 有结果列表供选择
|
|
|
+
|
|
|
+**测试时优先探索的顺序:**
|
|
|
+1. 先使用已有方法 `openPersonManagementDialog()` 打开人员管理对话框
|
|
|
+2. 点击"添加人员"按钮
|
|
|
+3. **[关键]** 探索"选择残疾人"组件的 DOM 结构
|
|
|
+4. 确定正确的选择策略(Select vs 对话框 vs 其他)
|
|
|
+5. 定位入职日期、薪资、工作状态等字段
|
|
|
+6. 定位提交按钮和验证方式
|
|
|
+
|
|
|
+**探索策略**:
|
|
|
+```typescript
|
|
|
+// 策略1: 尝试使用 Select
|
|
|
+await selectRadixOption(this.page, '残疾人', personName);
|
|
|
+
|
|
|
+// 策略2: 如果是自定义对话框
|
|
|
+const dialog = this.page.locator('[role="dialog"]');
|
|
|
+const personRow = dialog.locator('table tbody tr').filter({ hasText: personName });
|
|
|
+await personRow.click();
|
|
|
+// 或
|
|
|
+const checkbox = personRow.locator('input[type="checkbox"]');
|
|
|
+await checkbox.check();
|
|
|
+
|
|
|
+// 策略3: 如果是搜索 + 选择
|
|
|
+await searchInput.fill(personName);
|
|
|
+await searchButton.click();
|
|
|
+const resultOption = this.page.getByRole('option', { name: personName });
|
|
|
+await resultOption.click();
|
|
|
+```
|
|
|
+
|
|
|
+### 项目结构对齐
|
|
|
+
|
|
|
+**遵循 Epic 9.6 并行执行决策:**
|
|
|
+- ✅ 不使用 `test.describe.serial`
|
|
|
+- ✅ 每个测试创建独立的测试数据
|
|
|
+- ✅ 使用时间戳确保订单名称和残疾人姓名唯一
|
|
|
+
|
|
|
+**遵循项目的类型规范:**
|
|
|
+- ✅ 使用 TypeScript 严格模式
|
|
|
+- ✅ 使用 `WORK_STATUS` 和 `WORK_STATUS_LABELS` 常量
|
|
|
+- ✅ 工作状态类型使用 `WorkStatus` 类型别名
|
|
|
+
|
|
|
+**遵循项目的测试模式:**
|
|
|
+- ✅ 使用 Playwright fixtures
|
|
|
+- ✅ 使用 Page Object 模式
|
|
|
+- ✅ Toast 消息使用 `data-sonner-toast` 选择器
|
|
|
+- ✅ 对话框使用 `role="dialog"` 或 `role="alertdialog"`
|
|
|
+
|
|
|
+**测试数据隔离:**
|
|
|
+- 使用 `disabilityPersonPage` 创建测试残疾人数据
|
|
|
+- 使用 `orderManagementPage` 创建测试订单
|
|
|
+- 测试名称添加时间戳确保唯一性
|
|
|
+
|
|
|
+### Project Structure Notes
|
|
|
+
|
|
|
+**测试文件位置:**
|
|
|
+```
|
|
|
+web/tests/e2e/
|
|
|
+├── pages/admin/
|
|
|
+│ └── order-management.page.ts (需验证/修复人员管理方法)
|
|
|
+└── specs/admin/
|
|
|
+ └── order-person.spec.ts (新建)
|
|
|
+```
|
|
|
+
|
|
|
+**与其他测试的关系:**
|
|
|
+- `order-create.spec.ts`: 创建订单测试(提供订单数据源)
|
|
|
+- `order-detail.spec.ts`: 订单详情测试(依赖本 Story 的选择残疾人功能)
|
|
|
+- `disability-person-complete.spec.ts`: 残疾人管理测试(测试数据来源)
|
|
|
+
|
|
|
+**本 Story 完成后的影响:**
|
|
|
+- 解除 Story 10.8 中被跳过的测试
|
|
|
+- 为 Story 10.10(附件管理)提供人员数据
|
|
|
+- 为 Story 10.11(完整流程测试)提供完整人员管理功能
|
|
|
+
|
|
|
+### References
|
|
|
+
|
|
|
+**Epic 需求来源:**
|
|
|
+- [Source: _bmad-output/planning-artifacts/epics.md](../planning-artifacts/epics.md) - Story 10.9 详细需求(行 2143-2178)
|
|
|
+
|
|
|
+**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-7-order-status-tests.md](10-7-order-status-tests.md) - 状态流转操作模式、常量使用
|
|
|
+- [Source: _bmad-output/implementation-artifacts/10-8-order-detail-tests.md](10-8-order-detail-tests.md) - 选择残疾人阻塞问题、Page Object 已有方法
|
|
|
+
|
|
|
+**项目上下文:**
|
|
|
+- [Source: _bmad-output/project-context.md](../project-context.md) - 技术栈、测试规范、类型系统
|
|
|
+
|
|
|
+**Epic 9 并行执行决策:**
|
|
|
+- [Source: _bmad-output/implementation-artifacts/epic-9-retrospective-2026-01-12.md](epic-9-retrospective-2026-01-12.md) - 测试隔离和并行执行最佳实践
|
|
|
+
|
|
|
+## Dev Agent Record
|
|
|
+
|
|
|
+### Agent Model Used
|
|
|
+
|
|
|
+claude-opus-4-5-20251101
|
|
|
+
|
|
|
+### Debug Log References
|
|
|
+
|
|
|
+无
|
|
|
+
|
|
|
+### Completion Notes List
|
|
|
+
|
|
|
+待实现
|
|
|
+
|
|
|
+### File List
|
|
|
+
|
|
|
+**预计修改的文件:**
|
|
|
+- `web/tests/e2e/pages/admin/order-management.page.ts` - 可能需要验证/修复人员管理方法
|
|
|
+
|
|
|
+**预计新建的文件:**
|
|
|
+- `web/tests/e2e/specs/admin/order-person.spec.ts` - 人员关联功能测试文件
|
|
|
+
|