# Story 13.1: 后台创建订单 → 企业小程序验证 Status: in-progress ## 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 > **测试开发流程(增强的 TDD)**: 本 Story 采用 Playwright MCP 优先的测试开发流程。**任务 0 必须在任务 1-6 之前完成**,它为后续任务提供验证过的选择器、交互模式和测试骨架。 > **注意**: 已移除 WebSocket 相关任务(原任务 4),因为小程序和后端服务未采用 WebSocket。 ### 阶段 1: EXPLORE - Playwright MCP 探索(RED 之前) - [x] **任务 0: Playwright MCP 探索验证**(已于 2026-01-14 完成) - [x] 0.1 启动子代理使用 Playwright MCP 手动验证完整测试流程 - [x] 0.2 记录验证的选择器(优先 data-testid,避免文本选择器) - [x] 0.3 记录交互模式(点击、填写、等待、页面跳转) - [x] 0.4 记录数据流(API 调用、请求/响应格式、同步时间) - [ ] 0.5 立即修复发现的应用层 bug(如果有) - [x] 0.6 生成测试代码骨架(基于验证的流程) - [x] 0.7 将探索结果更新到本文档 Dev Notes 的"Playwright MCP 探索结果"部分 ### 阶段 2: RED - 编写测试(基于任务 0 的探索结果) - [ ] 任务 1: 创建跨端测试文件和基础设施 (AC: #3, #6) - [ ] 1.1 基于任务 0 的探索结果创建 `web/tests/e2e/specs/cross-platform/order-create-sync.spec.ts` - [ ] 1.2 配置测试 fixtures(使用任务 0 验证过的选择器) - [ ] 1.3 添加测试前置条件(需要测试平台和公司数据) - [ ] 任务 2: 实现后台创建订单测试 (AC: #1) - [ ] 2.1 使用任务 0 验证的选择器编写"后台创建订单成功"测试 - [ ] 2.2 验证订单在后台列表中显示 - [ ] 2.3 获取并存储订单 ID 和关键信息 - [ ] 任务 3: 实现企业小程序验证测试 (AC: #2) - [ ] 3.1 使用任务 0 验证的选择器编写"企业小程序显示新订单"测试 - [ ] 3.2 验证订单信息完整性 - [ ] 3.3 实现数据同步等待机制(基于任务 0 实测的同步时间) ### 阶段 3: GREEN - 实现代码(让测试通过) - [ ] 任务 4: 实现测试数据清理策略 (AC: #4) - [ ] 4.1 添加 afterEach 钩子清理订单数据 - [ ] 4.2 验证清理后小程序不再显示该订单 - [ ] 任务 5: 实现数据同步时效性验证 (AC: #5) - [ ] 5.1 实现轮询等待机制 - [ ] 5.2 验证正常同步时间(基于任务 0 的实测数据,应 ≤ 5 秒) - [ ] 5.3 验证超时处理(最长 10 秒) ### 阶段 4: REFACTOR - 优化代码质量(可选) - [ ] 任务 6: 验证代码质量 (AC: #6) - [ ] 6.1 运行 `pnpm typecheck` 验证类型检查 - [ ] 6.2 运行测试确保所有测试通过 - [ ] 6.3 验证使用 data-testid 选择器(任务 0 已确认) ### 阶段 5: CODE REVIEW FIXES - 修复代码审查发现的问题(来自 Story 13.6 代码审查) > **代码审查来源**: Story 13.6 的代码审查发现,这些问题在 DisabledPersonSelector 组件和测试代码中存在,需要在 Story 13.1 完成前修复。 #### 高优先级问题(安全性和功能损坏) - [ ] 任务 7: 修复 DisabledPersonSelector 组件安全问题和功能损坏 - [ ] 7.1 身份证号脱敏处理(安全问题) - 当前问题:身份证号明文显示,存在安全隐患 - 修复方案:实现脱敏显示函数,只显示前6位和后4位 - [ ] 7.2 修复地区选择未连接到 API(功能损坏) - 当前问题:地区选择未调用实际 API - 修复方案:连接到真实的地区查询 API - [ ] 7.3 修复多字段搜索功能(功能损坏) - 当前问题:三个搜索字段共用同一状态,导致功能完全损坏 - 修复方案:为每个搜索字段创建独立的状态管理 - [ ] 7.4 移除未使用的 selectedIds 属性(代码清理) - 当前问题:selectedIds 属性定义但未使用 - 修复方案:移除该属性及其相关代码 #### 中优先级问题(测试代码改进) - [ ] 任务 8: 改进测试代码质量和可维护性 - [ ] 8.1 移除 process.env 状态共享 - 当前问题:使用 process.env 在测试间共享状态,违反测试隔离原则 - 修复方案:使用 Playwright 的 fixtures 或测试上下文传递状态 - [ ] 8.2 使用环境变量替代硬编码凭据 - 当前问题:测试数据(手机号、密码等)硬编码在测试中 - 修复方案:从环境变量读取测试凭据和测试数据 - [ ] 8.3 统一使用 TIMEOUTS 常量 - 当前问题:存在魔术数字(硬编码的超时值) - 修复方案:统一使用 `TIMEOUTS` 常量,消除魔术数字 #### 低优先级问题(技术债) - [ ] 任务 9: 优化组件性能和可维护性(技术债清理) - [ ] 9.1 优化 columns 数组定义 - 当前问题:columns 数组在组件内每次渲染时重新创建 - 修复方案:移到组件外或使用 useMemo 优化 - [ ] 9.2 使用命名常量替代硬编码状态值 - 当前问题:黑名单状态使用硬编码字符串/数字 - 修复方案:定义命名常量(如 BLACKLIST_STATUS_ACTIVE) - [ ] 9.3 添加错误边界和友好错误提示 - 当前问题:组件缺少错误处理机制 - 修复方案:添加 React 错误边界和用户友好的错误消息 ## 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. 点击订单详情 → 验证订单信息完整性 **注意事项**: - 订单列表项可以直接通过文本选择器访问(订单名称) - 订单详情页显示完整信息:订单编号、状态、实际人数、关联人才 **关键发现(2026-01-14 探索)**: 1. **残疾人选择问题**: - 残疾人选择对话框能够正确打开 - 使用 `getByTestId('person-checkbox-1240')` 可以选择残疾人(1240 是残疾人 ID) - 选择后需要点击 `confirm-batch-button` 确认 2. **公司关联问题**: - 小程序用户(13800001111)关联的公司是"测试公司_1768346782396" - 测试需要选择相同的公司,否则小程序看不到创建的订单 - 修复:测试代码已更新为选择正确的公司 3. **测试状态持久化**: - 之前的测试运行可能在对话框中留下了残疾人选择 - 修复:测试代码已添加逻辑检测已选择的残疾人 4. **对话框检测**: - 使用 `text=选择残疾人` 检测对话框标题比 `[role="dialog"]` 更可靠 - 确认按钮使用 `confirm-batch-button` data-testid **待解决问题**: - 残疾人选择后,测试在后续步骤超时 - 需要进一步调试表格行点击逻辑 ### 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 **任务 0 完成记录 (2026-01-14)**: - ✅ 使用 Playwright MCP 验证了完整测试流程 - ✅ 记录了所有验证过的选择器 - ✅ 发现并修复了公司关联问题(测试需要选择测试公司_1768346782396) - ✅ 发现了测试状态持久化问题,添加了检测逻辑 - ⚠️ 待解决:残疾人选择后的测试超时问题 **测试文件状态**: - 文件路径: `web/tests/e2e/specs/cross-platform/order-create-sync.spec.ts` - 状态: 部分完成,存在超时问题需要调试 ### File List **修改的文件**: - `web/tests/e2e/specs/cross-platform/order-create-sync.spec.ts` - 测试文件,已添加残疾人选择逻辑和公司选择修复 _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 个 - 2026-01-14: 增强 TDD 流程 - 添加 Playwright MCP 探索(任务 0) - 原因:测试开发应先验证流程再写测试,提高效率减少返工 - 修改:添加任务 0(Playwright MCP 探索验证),任务按 TDD 阶段分组 - 流程:EXPLORE(任务 0)→ RED(任务 1-3)→ GREEN(任务 4-5)→ REFACTOR(任务 6) - 预期收益:减少选择器调试时间,提前发现应用层 bug - 后续 Story 复用:Epic 13 的 Story 13.2-13.5 将遵循相同流程 - 2026-01-14: 添加代码审查任务(阶段 5) - 来源:Story 13.6 代码审查发现的问题 - 添加任务 7:DisabledPersonSelector 组件安全问题和功能修复(高优先级) - 添加任务 8:测试代码质量改进(中优先级) - 添加任务 9:组件性能优化和错误处理(低优先级/技术债)