# Story 13.1: 后台创建订单 → 企业小程序验证 Status: ready-for-dev ## Story 作为测试开发者, 我想要验证后台创建订单后企业小程序的数据同步, 以便确保跨端数据同步的正确性和时效性。 ## Acceptance Criteria > **注意**: 本 Story 不包含 WebSocket 通信验证,因为小程序和后端服务未采用 WebSocket。 ### AC1: 后台创建订单基础流程 **Given** 后台订单管理功能已完成(Epic 10) **When** 测试者在管理后台创建订单 **Then** 测试应验证以下功能: - 使用 OrderManagementPage 创建测试订单 - 填写订单名称、预计开始日期等必填字段 - 选择平台和公司(如适用) - 验证订单在后台列表中显示 - 获取创建订单的 ID 和关键信息 ### AC2: 企业小程序数据同步验证 **Given** 管理后台已创建订单 **When** 企业用户登录小程序 **Then** 测试应验证以下功能: - 使用 EnterpriseMiniPage 登录企业小程序 - 验证新创建的订单在小程序订单列表中显示 - 验证订单信息完整(订单名称、状态、日期等) - 验证数据同步在合理时间内完成(≤ 10 秒) ### AC3: 多 Page 对象管理 **Given** 测试需要同时操作后台和小程序 **When** 执行跨端测试 **Then** 测试应满足以下要求: - 使用独立的 Page 对象管理后台和小程序 - 正确管理多个 browser context 或 page - 确保测试之间不会相互干扰 ### AC4: 测试数据隔离和清理 **Given** 跨端测试涉及多个系统 **When** 执行测试 **Then** 测试应遵循以下策略: - 使用唯一标识符创建测试订单(避免冲突) - 测试后清理创建的订单数据 - 验证清理后小程序列表不再显示该订单 ### AC5: 数据同步时效性验证 **Given** 网络延迟和系统负载 **When** 创建订单后查询小程序 **Then** 测试应验证以下场景: - 在正常情况下,数据应在 5 秒内同步 - 支持轮询等待机制(最多等待 10 秒) - 验证超时情况下的错误处理 ### AC6: 代码质量标准 **Given** 遵循项目测试规范 **When** 编写测试代码 **Then** 代码应符合以下标准: - 使用 TIMEOUTS 常量定义超时 - 使用 data-testid 选择器(优先级高于文本选择器) - 测试文件命名:`order-create-sync.spec.ts` - 完整的测试描述和注释 - TypeScript 类型安全 - 通过 `pnpm typecheck` 类型检查 ## Tasks / Subtasks > **注意**: 已移除 WebSocket 相关任务(原任务 4),因为小程序和后端服务未采用 WebSocket。 - [ ] 任务 1: 创建跨端测试文件和基础设施 (AC: #3, #6) - [ ] 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: 实现测试数据清理策略 (AC: #4) - [ ] 4.1 添加 afterEach 钩子清理订单数据 - [ ] 4.2 验证清理后小程序不再显示该订单 - [ ] 任务 5: 实现数据同步时效性验证 (AC: #5) - [ ] 5.1 实现轮询等待机制 - [ ] 5.2 验证正常同步时间(≤ 5 秒) - [ ] 5.3 验证超时处理(最长 10 秒) - [ ] 任务 6: 验证代码质量 (AC: #6) - [ ] 6.1 运行 `pnpm typecheck` 验证类型检查 - [ ] 6.2 运行测试确保所有测试通过 - [ ] 6.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: 跨端测试稳定性验证 ``` ### Playwright MCP 探索结果 (2026-01-14) **测试目标**: 验证后台创建订单后,企业小程序能否正确显示该订单 **测试结果**: ✅ 成功 **数据同步时效性**: - 实际同步时间: < 1秒 - 要求: ≤ 10 秒 - 结论: 远超预期 **后台选择器(已验证可用)**: | 功能 | data-testid | |------|-------------| | 创建订单按钮 | `create-order-button` | | 平台选择器 | `platform-selector-create` | | 公司选择器 | `company-selector-create` | | 选择残疾人按钮 | `select-persons-button` | | 残疾人复选框 | `person-checkbox-{id}` | | 确认选择按钮 | `confirm-batch-button` | | 创建提交按钮 | `order-create-submit-button` | **小程序选择器(已验证可用)**: | 功能 | data-testid | |------|-------------| | 手机号输入框 | `mini-phone-input` | | 登录按钮 | `mini-login-button` | **测试流程(已验证)**: 1. 后台登录 → 导航到订单管理 → 点击创建订单 2. 填写订单信息(名称、平台、公司、残疾人)→ 提交创建 3. 小程序登录 → 导航到订单列表 → 验证新订单显示 4. 点击订单详情 → 验证订单信息完整性 **注意事项**: - 订单列表项可以直接通过文本选择器访问(订单名称) - 订单详情页显示完整信息:订单编号、状态、实际人数、关联人才 ### Epic 10 关键经验(订单管理) 从已完成的 Epic 10 中学习到的订单管理模式: **OrderManagementPage 可用方法:** ```typescript // 页面导航 async goto(): Promise async expectToBeVisible(): Promise // 订单 CRUD async createOrder(data: OrderData): Promise async editOrder(orderId: string, data: OrderData): Promise async deleteOrder(orderId: string): Promise async orderExists(orderName: string): Promise // 订单详情 async openDetailDialog(orderName: string): Promise async getOrderDetailInfo(): Promise ``` **订单数据结构:** ```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 async expectToBeVisible(): Promise // 登录方法 async login(phone: string, password: string): Promise // Token 管理 async getToken(): Promise async setToken(token: string): Promise async clearAuth(): Promise // 订单列表(待实现) async getOrderList(): Promise async waitForOrderToAppear(orderName: string, timeout?: number): Promise ``` **企业小程序登录流程:** ```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({ 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 { 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], // 检查间隔 }); ``` ### 测试数据准备策略 **前置条件:** 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 监听) - 检查 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` (企业小程序登录测试) **探索报告**: - `13-1-playwright-mcp-exploration.md` - Playwright MCP 测试探索报告 (2026-01-14) ## 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 - 2026-01-14: 移除 WebSocket 相关内容 - 原因:小程序和后端服务未采用 WebSocket - 修改:移除 AC3、任务 4、Dev Notes 中的 WebSocket 部分 - 验收标准:7 个 → 6 个 - 任务数量:7 个 → 6 个