2
0

13-1-order-create-sync.md 14 KB

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: 跨端测试稳定性验证

Epic 10 关键经验(订单管理)

从已完成的 Epic 10 中学习到的订单管理模式:

OrderManagementPage 可用方法:

// 页面导航
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>

订单数据结构:

interface OrderData {
  name: string;              // 订单名称
  expectedStartDate?: string; // 预计开始日期
  platformId?: number;       // 平台ID
  companyId?: number;        // 公司ID
  channelId?: number;        // 渠道ID
  status?: string;           // 订单状态
  workStatus?: string;       // 工作状态
}

订单创建模式:

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 可用方法:

// 页面导航
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>

企业小程序登录流程:

await enterpriseMiniPage.goto();
await enterpriseMiniPage.login(
  '13800138000',  // 企业用户手机号
  'password123'
);
await enterpriseMiniPage.expectLoginSuccess();

多 Page 对象管理策略

方案 1: 使用多个 Browser Context(推荐)

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(备选)

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!);
  // ...
});

数据同步等待策略

轮询等待模式:

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 的等待机制:

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 创建的企业用户)

测试数据唯一性:

const timestamp = Date.now();
const orderData = {
  name: `跨端同步测试_${timestamp}`,
  expectedStartDate: '2026-01-15',
};

测试数据清理策略

清理方法:

test.afterEach(async ({ orderManagementPage, orderName }) => {
  // 在后台删除测试订单
  await orderManagementPage.goto();
  await orderManagementPage.deleteOrder(orderName);
});

验证清理成功:

test('清理后小程序不显示订单', async ({ enterpriseMiniPage, orderName }) => {
  const orders = await enterpriseMiniPage.getOrderList();
  expect(orders.some(o => o.name === orderName)).toBe(false);
});

小程序订单列表页面(待实现)

预期页面元素:

  • 订单列表容器
  • 订单项(订单名称、状态、日期)
  • 订单详情按钮
  • 筛选器(可选)

如页面未实现,需要添加 data-testid:

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 类型定义

跨端测试数据类型:

interface CrossPlatformOrderData {
  /** 后台订单 ID */
  adminOrderId: string;
  /** 订单名称 */
  orderName: string;
  /** 订单状态 */
  status: string;
  /** 创建时间 */
  createdAt: string;
}

interface SyncVerificationResult {
  /** 同步是否成功 */
  synced: boolean;
  /** 同步耗时(毫秒) */
  syncTime: number;
  /** 后台订单数据 */
  adminOrder: OrderData;
  /** 小程序订单数据 */
  miniOrder?: OrderData;
}

测试超时配置

使用 TIMEOUTS 常量:

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 (企业小程序登录测试)

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 个