Status: ready-for-dev
作为测试开发者, 我想要编写订单附件管理的 E2E 测试, 以便验证添加订单附件的功能。
Given 订单管理 Page Object 已创建 When 编写附件管理测试用例 Then 包含以下测试场景:
为订单添加附件
附件文件格式验证
测试文件: web/tests/e2e/specs/admin/order-attachment.spec.ts
openAddAttachmentDialog() 方法可用uploadAttachment(personName, fileName, mimeType) 方法可用getAttachmentListFromDetail() 方法可用web/tests/e2e/specs/admin/order-attachment.spec.tsEpic 10: 订单管理 E2E 测试 (Epic C - 业务测试 Epic)
依赖:
从 Story 10.8 学到的经验:
订单详情对话框结构:
openDetailDialog(orderName) 打开订单详情对话框closeDetailDialog() 关闭对话框附件列表获取:
getAttachmentListFromDetail() 方法已实现(行 752-818)从 Story 10.9 学到的经验:
API 直接创建测试数据:
createDisabledPersonViaAPI() 创建残疾人数据人员管理验证:
getPersonListFromDetail() 方法已修复(正确选择绑定人员列表表格)hasText: '工作状态' 作为筛选条件测试数据隔离:
testDataCounter 全局计数器确保唯一性订单附件管理相关方法 (web/tests/e2e/pages/admin/order-management.page.ts):
| 方法 | 说明 | 当前状态 | 本 Story 需求 |
|---|---|---|---|
openAddAttachmentDialog() |
打开添加附件对话框 | 已实现 (行 1032-1036) | 可直接使用 |
uploadAttachment(personName, fileName, mimeType) |
上传附件 | 已实现 (行 1044-1067) | 需验证UI 结构 |
getAttachmentListFromDetail() |
获取附件列表 | 已实现 (行 752-818) | 验证附件后检查 |
openAddAttachmentDialog() 方法当前实现(行 1032-1036):
async openAddAttachmentDialog() {
const attachmentButton = this.page.getByRole('button', { name: /添加附件|上传附件/ });
await attachmentButton.click();
await this.page.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG });
}
uploadAttachment() 方法当前实现(行 1044-1067):
async uploadAttachment(personName: string, fileName: string, mimeType: string = 'image/jpeg') {
// 选择订单人员
const personSelect = this.page.getByLabel(/选择人员|订单人员/);
await personSelect.click();
await this.page.getByRole('option', { name: personName }).click();
// 查找文件上传输入框
const fileInput = this.page.locator('input[type="file"]');
await fileInput.setInputFiles({
name: fileName,
mimeType,
buffer: Buffer.from(`fake ${fileName} content`),
});
// 等待上传处理
await this.page.waitForTimeout(TIMEOUTS.MEDIUM);
// 提交
const submitButton = this.page.getByRole('button', { name: /^(上传|确定|保存)$/ });
await submitButton.click();
await this.page.waitForLoadState('networkidle');
await this.page.waitForTimeout(TIMEOUTS.LONG);
}
潜在问题:
getByLabel + getByRole('option'))setInputFiles 的 buffer 模式(而非 fixtures 文件路径)需要验证的 UI 结构:
<input type="file"> 标准 HTML 元素为订单添加附件:
附件文件格式验证:
附件管理对话框结构假设(需要验证):
添加附件按钮位置:
添加附件对话框结构:
<input type="file"> 元素附件列表展示:
测试时优先探索的顺序:
openDetailDialog(orderName) 打开订单详情对话框探索策略:
// 步骤1: 打开订单详情
await orderPage.openDetailDialog(orderName);
// 步骤2: 查找添加附件按钮
const attachmentButton = page.getByRole('button', { name: /添加附件|上传附件/ });
// 或
const attachmentButton = page.getByTestId('add-attachment-button');
// 步骤3: 点击并验证对话框打开
await attachmentButton.click();
await page.waitForSelector('[role="dialog"]', { state: 'visible' });
// 步骤4: 探索对话框结构
// - 人员选择器
const personSelect = page.getByLabel(/选择人员|订单人员/);
// 或 Radix Select
await selectRadixOption(page, '订单人员', personName);
// - 文件上传输入框
const fileInput = page.locator('input[type="file"]');
// 使用 fixtures 文件
await fileInput.setInputFiles('web/tests/fixtures/images/sample-id-card.jpg');
// 步骤5: 提交并验证
const submitButton = page.getByRole('button', { name: /^(上传|确定|保存)$/ });
await submitButton.click();
// 步骤6: 验证附件列表
const attachments = await orderPage.getAttachmentListFromDetail();
Fixtures 文件 (位于 web/tests/fixtures/images/):
sample-id-card.jpg - 身份证照片(JPG 格式)sample-disability-card.jpg - 残疾证照片(JPG 格式)id-card-front.jpg - 身份证正面(JPG 格式)id-card-back.jpg - 身份证反面(JPG 格式)disability-card.jpg - 残疾证照片(JPG 格式)photo.jpg - 个人照片(JPG 格式)photo.png - 个人照片(PNG 格式)photo.webp - 个人照片(WEBP 格式)large-file.jpg - 大文件(用于测试文件大小限制)invalid.txt - 无效格式文件(用于测试格式验证)测试数据创建流程:
遵循 Epic 9.6 并行执行决策:
test.describe.serial遵循项目的类型规范:
WORK_STATUS 和 WORK_STATUS_LABELS 常量WorkStatus 类型别名遵循项目的测试模式:
data-sonner-toast 选择器role="dialog" 或 role="alertdialog"测试数据隔离:
createDisabledPersonViaAPI() 创建残疾人数据orderManagementPage.createOrder() 创建测试订单orderManagementPage.addPersonToOrder() 添加人员到订单测试文件位置:
web/tests/e2e/
├── pages/admin/
│ └── order-management.page.ts (已有附件方法)
└── specs/admin/
└── order-attachment.spec.ts (新建)
测试 Fixtures 位置:
web/tests/fixtures/
└── images/
├── sample-id-card.jpg
├── sample-disability-card.jpg
├── photo.jpg
├── photo.png
├── photo.webp
└── invalid.txt
与其他测试的关系:
order-create.spec.ts: 创建订单测试(提供订单数据源)order-person.spec.ts: 人员关联测试(提供人员数据源)order-detail.spec.ts: 订单详情测试(验证附件列表显示)本 Story 完成后的影响:
Epic 需求来源:
Page Object 现有实现:
前序 Story 学习:
项目上下文:
Epic 9 并行执行决策:
claude-opus-4-5-20251101
无
Story 创建完成 - 2026-01-13
工作流执行:
create-story/workflow.yamlepics.md (Story 10.10 行 2181-2205)10-9-order-person-tests.mdproject-context.mdorder-management.page.ts验收标准映射:
Page Object 方法验证:
openAddAttachmentDialog() - 已实现(行 1032-1036)uploadAttachment(personName, fileName, mimeType) - 已实现(行 1044-1067)getAttachmentListFromDetail() - 已实现(行 752-818)测试 Fixtures 确认:
sample-id-card.jpg, photo.png, photo.webpinvalid.txt (用于格式验证)依赖关系确认:
待完成(开发阶段):
order-attachment.spec.ts已创建的文件:
_bmad-output/implementation-artifacts/10-10-order-attachment-tests.md - Story 文档需创建的文件(开发阶段):
web/tests/e2e/specs/admin/order-attachment.spec.ts - 附件管理测试文件相关参考文件:
web/tests/e2e/pages/admin/order-management.page.ts - 订单管理 Page Object(行 1027-1067: 附件方法)_bmad-output/implementation-artifacts/10-8-order-detail-tests.md - 订单详情测试参考_bmad-output/implementation-artifacts/10-9-order-person-tests.md - 人员关联测试参考sprint-status.yaml 更新说明:
由于 sprint-status.yaml 文件不存在,Story 10-10 的状态无法通过文件更新。
建议运行 bmad:bmm:workflows:sprint-status 工作流来初始化或更新 sprint status 文件。
手动更新指令(如果文件存在):
# 在 sprint-status.yaml 中
stories:
10-10:
status: ready-for-dev # 从 backlog 改为 ready-for-dev