Ver Fonte

feat(story): 创建 Story 13.1 - 后台创建订单到企业小程序验证

- 定义 7 个验收标准和 7 个主要任务
- 基于 Epic 10 (订单管理) 和 Epic 12 (小程序登录)
- 实现跨端数据同步验证:后台创建订单 → 企业小程序显示
- 多 Page 对象管理策略(独立 Browser Context)
- Epic 13 状态: backlog → in-progress

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname há 3 dias atrás
pai
commit
c752f18765

+ 482 - 0
_bmad-output/implementation-artifacts/13-1-order-create-sync.md

@@ -0,0 +1,482 @@
+# Story 13.1: 后台创建订单 → 企业小程序验证
+
+Status: ready-for-dev
+
+<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
+
+## Story
+
+作为测试开发者,
+我想要验证后台创建订单后企业小程序的数据同步,
+以便确保跨端数据同步的正确性和时效性。
+
+## Acceptance Criteria
+
+### AC1: 后台创建订单基础流程
+**Given** 后台订单管理功能已完成(Epic 10)
+**When** 测试者在管理后台创建订单
+**Then** 测试应验证以下功能:
+- 使用 OrderManagementPage 创建测试订单
+- 填写订单名称、预计开始日期等必填字段
+- 选择平台和公司(如适用)
+- 验证订单在后台列表中显示
+- 获取创建订单的 ID 和关键信息
+
+### AC2: 企业小程序数据同步验证
+**Given** 管理后台已创建订单
+**When** 企业用户登录小程序
+**Then** 测试应验证以下功能:
+- 使用 EnterpriseMiniPage 登录企业小程序
+- 验证新创建的订单在小程序订单列表中显示
+- 验证订单信息完整(订单名称、状态、日期等)
+- 验证数据同步在合理时间内完成(≤ 10 秒)
+
+### AC3: WebSocket 通信验证(可选)
+**Given** 小程序支持 WebSocket 实时更新
+**When** 订单创建后
+**Then** 测试应验证以下功能:
+- 监听 WebSocket 连接(`/mini-ws` 端点)
+- 验证订单创建消息正确推送
+- 验证消息格式符合预期
+
+### AC4: 多 Page 对象管理
+**Given** 测试需要同时操作后台和小程序
+**When** 执行跨端测试
+**Then** 测试应满足以下要求:
+- 使用独立的 Page 对象管理后台和小程序
+- 正确管理多个 browser context 或 page
+- 确保测试之间不会相互干扰
+
+### AC5: 测试数据隔离和清理
+**Given** 跨端测试涉及多个系统
+**When** 执行测试
+**Then** 测试应遵循以下策略:
+- 使用唯一标识符创建测试订单(避免冲突)
+- 测试后清理创建的订单数据
+- 验证清理后小程序列表不再显示该订单
+
+### AC6: 数据同步时效性验证
+**Given** 网络延迟和系统负载
+**When** 创建订单后查询小程序
+**Then** 测试应验证以下场景:
+- 在正常情况下,数据应在 5 秒内同步
+- 支持轮询等待机制(最多等待 10 秒)
+- 验证超时情况下的错误处理
+
+### AC7: 代码质量标准
+**Given** 遵循项目测试规范
+**When** 编写测试代码
+**Then** 代码应符合以下标准:
+- 使用 TIMEOUTS 常量定义超时
+- 使用 data-testid 选择器(优先级高于文本选择器)
+- 测试文件命名:`order-create-sync.spec.ts`
+- 完整的测试描述和注释
+- TypeScript 类型安全
+- 通过 `pnpm typecheck` 类型检查
+
+## Tasks / Subtasks
+
+- [ ] 任务 1: 创建跨端测试文件和基础设施 (AC: #4, #7)
+  - [ ] 1.1 创建 `web/tests/e2e/specs/cross-platform/order-create-sync.spec.ts`
+  - [ ] 1.2 配置测试 fixtures(adminLoginPage, orderManagementPage, enterpriseMiniPage)
+  - [ ] 1.3 添加测试前置条件(需要测试平台和公司数据)
+
+- [ ] 任务 2: 实现后台创建订单测试 (AC: #1)
+  - [ ] 2.1 编写"后台创建订单成功"测试
+  - [ ] 2.2 验证订单在后台列表中显示
+  - [ ] 2.3 获取并存储订单 ID 和关键信息
+
+- [ ] 任务 3: 实现企业小程序验证测试 (AC: #2)
+  - [ ] 3.1 编写"企业小程序显示新订单"测试
+  - [ ] 3.2 验证订单信息完整性
+  - [ ] 3.3 实现数据同步等待机制
+
+- [ ] 任务 4: 实现 WebSocket 通信验证(可选)(AC: #3)
+  - [ ] 4.1 添加 WebSocket 监听器(如支持)
+  - [ ] 4.2 验证消息推送格式
+  - [ ] 4.3 验证消息内容正确性
+
+- [ ] 任务 5: 实现测试数据清理策略 (AC: #5)
+  - [ ] 5.1 添加 afterEach 钩子清理订单数据
+  - [ ] 5.2 验证清理后小程序不再显示该订单
+
+- [ ] 任务 6: 实现数据同步时效性验证 (AC: #6)
+  - [ ] 6.1 实现轮询等待机制
+  - [ ] 6.2 验证正常同步时间(≤ 5 秒)
+  - [ ] 6.3 验证超时处理(最长 10 秒)
+
+- [ ] 任务 7: 验证代码质量 (AC: #7)
+  - [ ] 7.1 运行 `pnpm typecheck` 验证类型检查
+  - [ ] 7.2 运行测试确保所有测试通过
+  - [ ] 7.3 验证选择器使用 data-testid
+
+## Dev Notes
+
+### Epic 13 背景和依赖
+
+**Epic 13: 跨端数据同步测试 (Epic E)**
+
+- **目标**: 验证后台操作后小程序端的数据同步,覆盖完整的业务流程
+- **业务分组**: Epic E(跨端数据同步测试)
+- **背景**: 真实用户旅程跨越管理后台和小程序,需要验证数据同步的正确性和时效性
+- **依赖**:
+  - Epic 10: ✅ 已完成(订单管理 E2E 测试)
+  - Epic 12: 🔄 进行中(小程序登录测试)
+
+**Epic 13 Story 依赖关系:**
+```
+Story 13.1: 后台创建订单 → 企业小程序验证 ← 当前 Story
+Story 13.2: 后台编辑订单 → 企业小程序验证
+Story 13.3: 后台添加人员 → 人才小程序验证
+Story 13.4: 后台更新状态 → 双小程序验证
+Story 13.5: 跨端测试稳定性验证
+```
+
+### Epic 10 关键经验(订单管理)
+
+从已完成的 Epic 10 中学习到的订单管理模式:
+
+**OrderManagementPage 可用方法:**
+```typescript
+// 页面导航
+async goto(): Promise<void>
+async expectToBeVisible(): Promise<void>
+
+// 订单 CRUD
+async createOrder(data: OrderData): Promise<FormSubmitResult>
+async editOrder(orderId: string, data: OrderData): Promise<FormSubmitResult>
+async deleteOrder(orderId: string): Promise<FormSubmitResult>
+async orderExists(orderName: string): Promise<boolean>
+
+// 订单详情
+async openDetailDialog(orderName: string): Promise<void>
+async getOrderDetailInfo(): Promise<OrderData>
+```
+
+**订单数据结构:**
+```typescript
+interface OrderData {
+  name: string;              // 订单名称
+  expectedStartDate?: string; // 预计开始日期
+  platformId?: number;       // 平台ID
+  companyId?: number;        // 公司ID
+  channelId?: number;        // 渠道ID
+  status?: string;           // 订单状态
+  workStatus?: string;       // 工作状态
+}
+```
+
+**订单创建模式:**
+```typescript
+const orderData = {
+  name: `跨端测试订单_${Date.now()}`,
+  expectedStartDate: '2026-01-15',
+  platformId: 1,
+  companyId: 1,
+};
+
+const result = await orderManagementPage.createOrder(orderData);
+expect(result.success).toBe(true);
+```
+
+### Epic 12 关键经验(小程序登录)
+
+从已完成的 Epic 12 中学习到的小程序模式:
+
+**EnterpriseMiniPage 可用方法:**
+```typescript
+// 页面导航
+async goto(): Promise<void>
+async expectToBeVisible(): Promise<void>
+
+// 登录方法
+async login(phone: string, password: string): Promise<void>
+
+// Token 管理
+async getToken(): Promise<string | null>
+async setToken(token: string): Promise<void>
+async clearAuth(): Promise<void>
+
+// 订单列表(待实现)
+async getOrderList(): Promise<OrderData[]>
+async waitForOrderToAppear(orderName: string, timeout?: number): Promise<boolean>
+```
+
+**企业小程序登录流程:**
+```typescript
+await enterpriseMiniPage.goto();
+await enterpriseMiniPage.login(
+  '13800138000',  // 企业用户手机号
+  'password123'
+);
+await enterpriseMiniPage.expectLoginSuccess();
+```
+
+### 多 Page 对象管理策略
+
+**方案 1: 使用多个 Browser Context(推荐)**
+```typescript
+import { test as base } from '@playwright/test';
+
+type CrossPlatformFixtures = {
+  adminPage: Page;
+  miniPage: Page;
+  orderManagementPage: OrderManagementPage;
+  enterpriseMiniPage: EnterpriseMiniPage;
+};
+
+export const test = base.extend<CrossPlatformFixtures>({
+  adminPage: async ({ browser }, use) => {
+    const context = await browser.newContext();
+    const page = await context.newPage();
+    await use(page);
+    await context.close();
+  },
+  miniPage: async ({ browser }, use) => {
+    const context = await browser.newContext();
+    const page = await context.newPage();
+    await use(page);
+    await context.close();
+  },
+  orderManagementPage: async ({ adminPage }, use) => {
+    const page = new OrderManagementPage(adminPage);
+    await use(page);
+  },
+  enterpriseMiniPage: async ({ miniPage }, use) => {
+    const page = new EnterpriseMiniPage(miniPage);
+    await use(page);
+  },
+});
+```
+
+**方案 2: 使用单个 Browser Context,多个 Page(备选)**
+```typescript
+test('跨端数据同步测试', async ({ page }) => {
+  // 后台操作
+  const adminPage = page;
+  const orderManagementPage = new OrderManagementPage(adminPage);
+
+  // 小程序操作(使用新的 page)
+  const miniContext = await adminPage.context().browser()?.newContext();
+  const miniPage = await miniContext?.newPage();
+  const enterpriseMiniPage = new EnterpriseMiniPage(miniPage!);
+  // ...
+});
+```
+
+### 数据同步等待策略
+
+**轮询等待模式:**
+```typescript
+async waitForOrderToAppear(
+  orderName: string,
+  timeout: number = 10000
+): Promise<boolean> {
+  const startTime = Date.now();
+  while (Date.now() - startTime < timeout) {
+    const orders = await this.getOrderList();
+    if (orders.some(o => o.name === orderName)) {
+      return true;
+    }
+    await this.page.waitForTimeout(500); // 每 500ms 检查一次
+  }
+  return false;
+}
+```
+
+**使用 Playwright 的等待机制:**
+```typescript
+await expect(async () => {
+  const orders = await enterpriseMiniPage.getOrderList();
+  expect(orders.some(o => o.name === orderName)).toBe(true);
+}).toPass({
+  timeout: 10000,
+  intervals: [500, 1000], // 检查间隔
+});
+```
+
+### WebSocket 通信验证(可选)
+
+**WebSocket 监听器:**
+```typescript
+// 监听 WebSocket 连接
+page.on('websocket', ws => {
+  ws.on('framereceived', frame => {
+    if (frame.payload) {
+      const message = JSON.parse(frame.payload.toString());
+      // 验证消息格式
+      expect(message).toHaveProperty('type', 'order_created');
+      expect(message.data).toHaveProperty('orderId');
+    }
+  });
+});
+```
+
+### 测试数据准备策略
+
+**前置条件:**
+1. 需要测试平台数据(使用 Story 11.2 创建的平台)
+2. 需要测试公司数据(使用 Story 11.5 创建的公司)
+3. 需要企业用户数据(使用 Story 12.2 创建的企业用户)
+
+**测试数据唯一性:**
+```typescript
+const timestamp = Date.now();
+const orderData = {
+  name: `跨端同步测试_${timestamp}`,
+  expectedStartDate: '2026-01-15',
+};
+```
+
+### 测试数据清理策略
+
+**清理方法:**
+```typescript
+test.afterEach(async ({ orderManagementPage, orderName }) => {
+  // 在后台删除测试订单
+  await orderManagementPage.goto();
+  await orderManagementPage.deleteOrder(orderName);
+});
+```
+
+**验证清理成功:**
+```typescript
+test('清理后小程序不显示订单', async ({ enterpriseMiniPage, orderName }) => {
+  const orders = await enterpriseMiniPage.getOrderList();
+  expect(orders.some(o => o.name === orderName)).toBe(false);
+});
+```
+
+### 小程序订单列表页面(待实现)
+
+**预期页面元素:**
+- 订单列表容器
+- 订单项(订单名称、状态、日期)
+- 订单详情按钮
+- 筛选器(可选)
+
+**如页面未实现,需要添加 data-testid:**
+```typescript
+private readonly selectors = {
+  orderList: '[data-testid="mini-order-list"]',
+  orderItem: '[data-testid="mini-order-item"]',
+  orderName: '[data-testid="mini-order-name"]',
+  orderStatus: '[data-testid="mini-order-status"]',
+  orderDate: '[data-testid="mini-order-date"]',
+};
+```
+
+### 项目结构
+
+**新建文件:**
+- `web/tests/e2e/specs/cross-platform/order-create-sync.spec.ts`
+- `web/tests/e2e/pages/mini/enterprise-mini.page.ts`(扩展订单列表方法)
+
+**相关参考文件:**
+- `web/tests/e2e/pages/admin/order-management.page.ts` (Epic 10)
+- `web/tests/e2e/pages/mini/enterprise-mini.page.ts` (Epic 12)
+- `web/tests/e2e/specs/admin/order-create.spec.ts` (Epic 10)
+
+### 选择器策略
+
+**优先级(遵循项目标准):**
+1. `data-testid` 属性(最高优先级)
+2. ARIA 属性 + role
+3. 文本内容(最低优先级,避免使用)
+
+**需要在小程序页面添加 data-testid:**
+- `mini-order-list` - 订单列表容器
+- `mini-order-item` - 订单项(可动态生成)
+- `mini-order-name` - 订单名称
+- `mini-order-status` - 订单状态
+
+### TypeScript 类型定义
+
+**跨端测试数据类型:**
+```typescript
+interface CrossPlatformOrderData {
+  /** 后台订单 ID */
+  adminOrderId: string;
+  /** 订单名称 */
+  orderName: string;
+  /** 订单状态 */
+  status: string;
+  /** 创建时间 */
+  createdAt: string;
+}
+
+interface SyncVerificationResult {
+  /** 同步是否成功 */
+  synced: boolean;
+  /** 同步耗时(毫秒) */
+  syncTime: number;
+  /** 后台订单数据 */
+  adminOrder: OrderData;
+  /** 小程序订单数据 */
+  miniOrder?: OrderData;
+}
+```
+
+### 测试超时配置
+
+**使用 TIMEOUTS 常量:**
+```typescript
+import { TIMEOUTS } from '../../utils/timeouts';
+
+// 数据同步等待时间
+const SYNC_TIMEOUT = TIMEOUTS.networkIdle; // 10000ms
+
+// 轮询检查间隔
+const POLL_INTERVAL = 500;
+```
+
+### 调试技巧
+
+**跨端测试调试:**
+1. 使用 `page.screenshot()` 在关键步骤截图
+2. 使用 `console.debug()` 输出订单信息
+3. 分别记录后台和小程序的操作时间
+
+**同步问题调试:**
+- 检查网络请求(使用 Playwright 的 network 监听)
+- 检查 WebSocket 连接(如使用)
+- 检查 localStorage 和 sessionStorage(token 存储)
+
+### 参考文档
+
+**架构文档:**
+- `_bmad-output/planning-artifacts/epics.md#Epic 13`
+- `_bmad-output/project-context.md`
+- `docs/standards/e2e-radix-testing.md`
+
+**相关 Story 文档:**
+- `10-1-order-page-object.md` (订单管理 Page Object)
+- `10-4-order-create-tests.md` (创建订单测试)
+- `12-4-enterprise-mini-page-object.md` (企业小程序 Page Object)
+- `12-5-enterprise-mini-login.md` (企业小程序登录测试)
+
+## Dev Agent Record
+
+### Agent Model Used
+
+_Created by create-story workflow_
+
+### Debug Log References
+
+_Implementation phase - no debug yet_
+
+### Completion Notes List
+
+_Ready for development - Status: ready-for-dev_
+
+### File List
+
+_Artifact file: `/mnt/code/188-179-template-6/_bmad-output/implementation-artifacts/13-1-order-create-sync.md`_
+
+## Change Log
+
+- 2026-01-14: Story 13.1 创建完成
+  - 后台创建订单 → 企业小程序验证需求
+  - 多 Page 对象管理策略
+  - 数据同步等待策略
+  - 状态:ready-for-dev

+ 2 - 2
_bmad-output/implementation-artifacts/sprint-status.yaml

@@ -208,8 +208,8 @@ development_status:
   # 背景: 真实用户旅程跨越多个端,需要验证数据同步
   # 依赖: Epic 10(订单管理)和 Epic 12(小程序登录)完成
   # 技术要点: 多 Page 对象管理、WebSocket 通信验证
-  epic-13: backlog
-  13-1-order-create-sync: backlog          # 后台创建订单 → 企业小程序验证
+  epic-13: in-progress
+  13-1-order-create-sync: ready-for-dev   # 后台创建订单 → 企业小程序验证
   13-2-order-edit-sync: backlog            # 后台编辑订单 → 企业小程序验证
   13-3-person-add-sync: backlog            # 后台添加人员 → 人才小程序验证
   13-4-work-status-sync: backlog           # 后台更新状态 → 双小程序验证