13-6-dashboard-sync.md 19 KB

Story 13.6: 首页看板数据联动专项测试

Status: ready-for-dev

Story

作为测试开发者, 我想要验证后台操作后企业小程序首页看板的数据同步, 以便确保用户在小程序首页能看到最新的业务数据统计和订单卡片。

Acceptance Criteria

AC1: 后台创建订单 → 首页看板订单卡片同步

Given 后台订单管理功能已完成(Epic 10) When 测试者在管理后台创建新订单 Then 测试应验证以下功能:

  • 使用 OrderManagementPage 创建测试订单
  • 刷新企业小程序首页看板
  • 验证新订单的卡片显示在首页
  • 验证卡片信息完整(订单名称、状态、日期等)

AC2: 首页看板订单数量统计同步

Given 后台已创建多个订单 When 刷新企业小程序首页看板 Then 测试应验证以下功能:

  • 验证订单总数统计正确
  • 验证各状态订单数量统计正确(进行中、已完成等)
  • 验证数量徽章显示正确

AC3: 首页看板状态徽章同步

Given 后台订单状态发生变化 When 订单状态被更新(如激活订单、关闭订单) Then 测试应验证以下功能:

  • 小程序首页订单卡片的状态徽章更新正确
  • 状态颜色区分正确(进行中、已完成、草稿等)

AC4: 首页看板卡片信息完整性验证

Given 首页看板显示订单卡片 When 查看订单卡片信息 Then 测试应验证以下功能:

  • 卡片显示订单名称
  • 卡片显示订单状态
  • 卡片显示预计开始日期或创建日期
  • 卡片显示关联人数(如有)
  • 卡片信息与后台订单详情一致

AC5: 数据刷新时效性验证

Given 后台操作已完成 When 刷新小程序首页看板 Then 测试应验证以下场景:

  • 在正常情况下,数据应在 3 秒内同步
  • 支持轮询等待机制(最多等待 10 秒)
  • 验证下拉刷新功能触发数据更新

AC6: 与订单列表页的区别验证

Given 本 Story 与 Story 13.1 测试范围不同 When 执行本 Story 测试 Then 测试范围应明确区分:

  • Story 13.1: 验证后台创建订单 → 订单列表页显示
  • Story 13.6: 验证后台创建订单 → 首页看板卡片显示
  • 两个 Story 测试不同的页面元素和功能

AC7: 代码质量标准

Given 遵循项目测试规范 When 编写测试代码 Then 代码应符合以下标准:

  • 使用 TIMEOUTS 常量定义超时
  • 使用 data-testid 选择器(优先级高于文本选择器)
  • 测试文件命名:dashboard-sync.spec.ts
  • 完整的测试描述和注释
  • TypeScript 类型安全
  • 通过 pnpm typecheck 类型检查

Tasks / Subtasks

  • [ ] 任务 1: 扩展 EnterpriseMiniPage 支持首页看板 (AC: #1, #2, #3, #4)

    • 1.1 添加首页看板选择器(订单卡片容器、统计徽章等)
    • 1.2 实现 getDashboardOrderCards() 方法
    • 1.3 实现 getOrderCountBadge() 方法
    • 1.4 实现下拉刷新方法 refreshDashboard()
    • 1.5 实现 getDashboardStatistics() 方法
  • [ ] 任务 2: 创建跨端首页看板同步测试文件 (AC: #1, #6, #7)

    • 2.1 创建 web/tests/e2e/specs/cross-platform/dashboard-sync.spec.ts
    • 2.2 配置测试 fixtures(adminLoginPage, orderManagementPage, enterpriseMiniPage)
    • 2.3 添加测试前置条件(需要测试平台、公司、企业用户数据)
  • [ ] 任务 3: 实现订单卡片同步验证测试 (AC: #1, #4)

    • 3.1 编写"后台创建订单 → 首页看板显示卡片"测试
    • 3.2 验证卡片信息完整性(名称、状态、日期、人数)
    • 3.3 验证卡片信息与后台订单详情一致
  • [ ] 任务 4: 实现订单数量统计同步测试 (AC: #2)

    • 4.1 编写"订单总数统计正确"测试
    • 4.2 编写"各状态订单数量统计正确"测试
    • 4.3 验证数量徽章显示
  • [ ] 任务 5: 实现状态徽章同步测试 (AC: #3)

    • 5.1 编写"激活订单 → 状态徽章更新"测试
    • 5.2 编写"关闭订单 → 状态徽章更新"测试
    • 5.3 验证状态颜色区分正确
  • [ ] 任务 6: 实现数据刷新时效性测试 (AC: #5)

    • 6.1 实现轮询等待机制
    • 6.2 验证正常同步时间(≤ 3 秒)
    • 6.3 验证下拉刷新功能
  • [ ] 任务 7: 实现测试数据清理策略 (AC: #4)

    • 7.1 添加 afterEach 钩子清理订单数据
    • 7.2 验证清理后首页看板不再显示该订单
  • [ ] 任务 8: 验证代码质量 (AC: #7)

    • 8.1 运行 pnpm typecheck 验证类型检查
    • 8.2 运行测试确保所有测试通过
    • 8.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 13.2: 后台编辑订单 → 企业小程序验证
Story 13.3: 后台添加人员 → 人才小程序验证
Story 13.4: 后台更新状态 → 双小程序验证
Story 13.5: 跨端测试稳定性验证
Story 13.6: 首页看板数据联动专项测试 ← 当前 Story

与 Story 13.1 的区别

维度 Story 13.1 Story 13.6
验证目标 订单列表 首页看板
验证内容 订单列表项显示、订单详情完整性 订单卡片、统计数量、状态徽章
测试场景 创建订单 → 点击订单列表 → 验证详情 创建订单 → 查看首页 → 验证卡片和统计
测试方法 getOrderList(), openDetailDialog() getDashboardOrderCards(), getOrderCountBadge()
数据时效 订单列表数据 首页看板统计、下拉刷新

企业小程序首页看板结构(预期)

基于小程序常见模式,首页看板预期包含以下元素:

订单卡片区域:

┌─────────────────────────────┐
│  首页看板                    │
├─────────────────────────────┤
│  统计卡片:                  │
│  ┌─────────┬─────────┐      │
│  │ 全部订单 │ 进行中  │      │
│  │   12    │   5     │      │
│  └─────────┴─────────┘      │
├─────────────────────────────┤
│  订单卡片列表:              │
│  ┌─────────────────────┐    │
│  │ 订单名称:测试订单    │    │
│  │ 状态:进行中         │    │
│  │ 日期:2026-01-15     │    │
│  │ 人数:10 人          │    │
│  └─────────────────────┘    │
│  ┌─────────────────────┐    │
│  │ 订单名称:测试订单2   │    │
│  │ 状态:已完成         │    │
│  └─────────────────────┘    │
└─────────────────────────────┘

预期 data-testid:

const DASHBOARD_SELECTORS = {
  dashboard: 'mini-dashboard',
  orderCard: 'mini-order-card',
  orderName: 'mini-order-card-name',
  orderStatus: 'mini-order-card-status',
  orderDate: 'mini-order-card-date',
  orderPersonCount: 'mini-order-card-person-count',
  orderCountBadge: 'mini-order-count-badge',
  orderStatusBadge: 'mini-order-status-badge',
  refreshButton: 'mini-dashboard-refresh',
};

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 activateOrder(orderName: string): Promise<FormSubmitResult>
async closeOrder(orderName: string): Promise<FormSubmitResult>

// 订单状态
async getOrderStatus(orderName: string): Promise<string>

订单状态流转:

// 订单状态
enum OrderStatus {
  DRAFT = '草稿',
  CONFIRMED = '已确认',
  IN_PROGRESS = '进行中',
  COMPLETED = '已完成',
  CANCELLED = '已取消',
}

// 激活订单(草稿 → 进行中)
await orderManagementPage.activateOrder(orderName);

// 关闭订单(进行中 → 已完成)
await orderManagementPage.closeOrder(orderName);

Epic 12 关键经验(小程序登录)

从已完成的 Epic 12 中学习到的小程序模式:

EnterpriseMiniPage 已有方法:

// 页面导航
async goto(): Promise<void>
async expectToBeVisible(): Promise<void>

// 登录方法
async login(phone: string, password: string): Promise<void>
async expectLoginSuccess(): Promise<void>

// Token 管理
async getToken(): Promise<string | null>
async clearAuth(): Promise<void>

企业小程序登录流程:

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

多 Page 对象管理策略

使用与 Story 13.1 相同的多 Context 策略:

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

EnterpriseMiniPage 扩展方法

需要添加以下方法到 enterprise-mini.page.ts

/**
 * 获取首页看板的订单卡片列表
 */
async getDashboardOrderCards(): Promise<DashboardOrderCard[]> {
  // 实现逻辑
}

/**
 * 获取订单数量统计徽章
 */
async getOrderCountBadge(filter?: 'all' | 'inProgress' | 'completed'): Promise<number> {
  // 实现逻辑
}

/**
 * 刷新首页看板数据
 */
async refreshDashboard(): Promise<void> {
  // 实现下拉刷新
}

/**
 * 获取首页看板统计数据
 */
async getDashboardStatistics(): Promise<DashboardStatistics> {
  // 实现逻辑
}

/**
 * 等待订单卡片出现在首页看板
 */
async waitForOrderCard(orderName: string, timeout?: number): Promise<boolean> {
  // 实现轮询等待
}

类型定义:

interface DashboardOrderCard {
  name: string;
  status: string;
  date: string;
  personCount?: number;
  orderId: string;
}

interface DashboardStatistics {
  totalCount: number;
  inProgressCount: number;
  completedCount: number;
  draftCount: number;
}

数据同步等待策略

与 Story 13.1 类似的轮询等待模式:

async waitForOrderCard(
  orderName: string,
  timeout: number = 10000
): Promise<boolean> {
  const startTime = Date.now();
  while (Date.now() - startTime < timeout) {
    const cards = await this.getDashboardOrderCards();
    if (cards.some(c => c.name === orderName)) {
      return true;
    }
    await this.page.waitForTimeout(500);
  }
  return false;
}

测试数据准备策略

前置条件:

  1. 需要测试平台数据(使用 Story 11.2 创建的平台)
  2. 需要测试公司数据(使用 Story 11.5 创建的公司)
  3. 需要企业用户数据(使用 Story 12.2 创建的企业用户)

测试数据唯一性:

const timestamp = Date.now();
const orderData = {
  name: `首页看板测试_${timestamp}`,
  expectedStartDate: '2026-01-15',
  platformId: 1,
  companyId: 1,
};

测试数据清理策略

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

项目结构

新建文件:

  • web/tests/e2e/specs/cross-platform/dashboard-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/cross-platform/order-create-sync.spec.ts (Story 13.1)
  • web/tests/e2e/specs/admin/dashboard.spec.ts (管理后台 dashboard 测试)

选择器策略

优先级(遵循项目标准):

  1. data-testid 属性(最高优先级)
  2. ARIA 属性 + role
  3. 文本内容(最低优先级,避免使用)

需要在小程序首页看板页面添加 data-testid:

  • mini-dashboard - 首页看板容器
  • mini-order-card - 订单卡片
  • mini-order-card-name - 订单名称
  • mini-order-card-status - 订单状态
  • mini-order-card-date - 订单日期
  • mini-order-card-person-count - 订单人数
  • mini-order-count-badge - 订单数量徽章
  • mini-order-status-badge - 状态徽章
  • mini-dashboard-refresh - 刷新按钮

TypeScript 类型定义

首页看板数据类型:

interface DashboardOrderCard {
  /** 订单 ID */
  orderId: string;
  /** 订单名称 */
  name: string;
  /** 订单状态 */
  status: OrderStatus;
  /** 预计开始日期 */
  expectedStartDate?: string;
  /** 关联人数 */
  personCount?: number;
}

interface DashboardStatistics {
  /** 全部订单数 */
  totalCount: number;
  /** 进行中订单数 */
  inProgressCount: number;
  /** 已完成订单数 */
  completedCount: number;
  /** 草稿订单数 */
  draftCount: number;
}

interface DashboardSyncVerificationResult {
  /** 同步是否成功 */
  synced: boolean;
  /** 同步耗时(毫秒) */
  syncTime: number;
  /** 后台订单数据 */
  adminOrder: OrderData;
  /** 首页看板订单卡片 */
  dashboardCard?: DashboardOrderCard;
  /** 统计数据 */
  statistics?: DashboardStatistics;
}

测试超时配置

使用 TIMEOUTS 常量:

import { TIMEOUTS } from '../../utils/timeouts';

// 首页看板数据同步等待时间
const SYNC_TIMEOUT = TIMEOUTS.networkIdle; // 10000ms

// 首页数据刷新等待时间
const REFRESH_TIMEOUT = TIMEOUTS.PAGE_LOAD; // 30000ms

// 轮询检查间隔
const POLL_INTERVAL = 500;

下拉刷新实现

小程序通常支持下拉刷新功能:

/**
 * 下拉刷新首页看板数据
 */
async refreshDashboard(): Promise<void> {
  // 方案 1: 使用 Playwright 模拟下拉手势
  await this.page.touchstart(0, 0);
  await this.page.touchmove(0, 200);
  await this.page.touchend();

  // 等待刷新完成
  await this.page.waitForTimeout(2000);

  // 方案 2: 如果有刷新按钮,点击刷新按钮
  // await this.refreshButton.click();
}

调试技巧

首页看板调试:

  1. 使用 page.screenshot() 在关键步骤截图
  2. 使用 console.debug() 输出订单卡片和统计信息
  3. 分别记录后台操作和小程序刷新的时间

同步问题调试:

  • 检查网络请求(使用 Playwright 的 network 监听)
  • 检查首页看板 API 响应
  • 验证下拉刷新触发的请求

参考文档

架构文档:

  • _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-7-order-status-tests.md (订单状态测试)
  • 12-4-enterprise-mini-page-object.md (企业小程序 Page Object)
  • 12-5-enterprise-mini-login.md (企业小程序登录测试)
  • 13-1-order-create-sync.md (订单列表同步测试)

测试场景示例

场景 1: 创建订单 → 首页看板显示卡片

test('后台创建订单后首页看板显示订单卡片', async ({
  adminPage, miniPage, orderManagementPage, enterpriseMiniPage
}) => {
  // 1. 后台创建订单
  const orderName = `看板测试_${Date.now()}`;
  await orderManagementPage.goto();
  await orderManagementPage.createOrder({
    name: orderName,
    expectedStartDate: '2026-01-15',
  });

  // 2. 小程序登录并刷新首页
  await enterpriseMiniPage.goto();
  await enterpriseMiniPage.login('13800138000', 'password123');
  await enterpriseMiniPage.expectLoginSuccess();
  await enterpriseMiniPage.refreshDashboard();

  // 3. 验证首页看板显示订单卡片
  const cards = await enterpriseMiniPage.getDashboardOrderCards();
  expect(cards.some(c => c.name === orderName)).toBe(true);

  // 4. 验证卡片信息完整性
  const card = cards.find(c => c.name === orderName);
  expect(card?.status).toBeTruthy();
  expect(card?.expectedStartDate).toBe('2026-01-15');
});

场景 2: 订单状态变化 → 首页看板状态徽章更新

test('激活订单后首页看板状态徽章更新', async ({
  adminPage, miniPage, orderManagementPage, enterpriseMiniPage
}) => {
  // 1. 创建草稿订单
  const orderName = `状态测试_${Date.now()}`;
  await orderManagementPage.goto();
  await orderManagementPage.createOrder({
    name: orderName,
    expectedStartDate: '2026-01-15',
  });

  // 2. 验证首页看板显示草稿状态
  await enterpriseMiniPage.goto();
  await enterpriseMiniPage.refreshDashboard();
  let cards = await enterpriseMiniPage.getDashboardOrderCards();
  let card = cards.find(c => c.name === orderName);
  expect(card?.status).toBe('草稿');

  // 3. 激活订单
  await orderManagementPage.goto();
  await orderManagementPage.activateOrder(orderName);

  // 4. 验证首页看板状态更新
  await enterpriseMiniPage.refreshDashboard();
  cards = await enterpriseMiniPage.getDashboardOrderCards();
  card = cards.find(c => c.name === orderName);
  expect(card?.status).toBe('进行中');
});

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-6-dashboard-sync.md

Change Log

  • 2026-01-14: Story 13.6 创建完成
    • 首页看板数据联动专项测试需求
    • 与 Story 13.1 的区别说明
    • EnterpriseMiniPage 扩展方法定义
    • 状态:ready-for-dev