|
@@ -0,0 +1,625 @@
|
|
|
|
|
+# Story 13.6: 首页看板数据联动专项测试
|
|
|
|
|
+
|
|
|
|
|
+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 创建测试订单
|
|
|
|
|
+- 刷新企业小程序首页看板
|
|
|
|
|
+- 验证新订单的卡片显示在首页
|
|
|
|
|
+- 验证卡片信息完整(订单名称、状态、日期等)
|
|
|
|
|
+
|
|
|
|
|
+### 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:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+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 可用方法:**
|
|
|
|
|
+```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 activateOrder(orderName: string): Promise<FormSubmitResult>
|
|
|
|
|
+async closeOrder(orderName: string): Promise<FormSubmitResult>
|
|
|
|
|
+
|
|
|
|
|
+// 订单状态
|
|
|
|
|
+async getOrderStatus(orderName: string): Promise<string>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**订单状态流转:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+// 订单状态
|
|
|
|
|
+enum OrderStatus {
|
|
|
|
|
+ DRAFT = '草稿',
|
|
|
|
|
+ CONFIRMED = '已确认',
|
|
|
|
|
+ IN_PROGRESS = '进行中',
|
|
|
|
|
+ COMPLETED = '已完成',
|
|
|
|
|
+ CANCELLED = '已取消',
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 激活订单(草稿 → 进行中)
|
|
|
|
|
+await orderManagementPage.activateOrder(orderName);
|
|
|
|
|
+
|
|
|
|
|
+// 关闭订单(进行中 → 已完成)
|
|
|
|
|
+await orderManagementPage.closeOrder(orderName);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Epic 12 关键经验(小程序登录)
|
|
|
|
|
+
|
|
|
|
|
+从已完成的 Epic 12 中学习到的小程序模式:
|
|
|
|
|
+
|
|
|
|
|
+**EnterpriseMiniPage 已有方法:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+// 页面导航
|
|
|
|
|
+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>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**企业小程序登录流程:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+await enterpriseMiniPage.goto();
|
|
|
|
|
+await enterpriseMiniPage.login(
|
|
|
|
|
+ '13800138000', // 企业用户手机号
|
|
|
|
|
+ 'password123'
|
|
|
|
|
+);
|
|
|
|
|
+await enterpriseMiniPage.expectLoginSuccess();
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 多 Page 对象管理策略
|
|
|
|
|
+
|
|
|
|
|
+使用与 Story 13.1 相同的多 Context 策略:
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+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`:
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+/**
|
|
|
|
|
+ * 获取首页看板的订单卡片列表
|
|
|
|
|
+ */
|
|
|
|
|
+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> {
|
|
|
|
|
+ // 实现轮询等待
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**类型定义:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+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 类似的轮询等待模式:
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+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 创建的企业用户)
|
|
|
|
|
+
|
|
|
|
|
+**测试数据唯一性:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+const timestamp = Date.now();
|
|
|
|
|
+const orderData = {
|
|
|
|
|
+ name: `首页看板测试_${timestamp}`,
|
|
|
|
|
+ expectedStartDate: '2026-01-15',
|
|
|
|
|
+ platformId: 1,
|
|
|
|
|
+ companyId: 1,
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 测试数据清理策略
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+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 类型定义
|
|
|
|
|
+
|
|
|
|
|
+**首页看板数据类型:**
|
|
|
|
|
+```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 常量:**
|
|
|
|
|
+```typescript
|
|
|
|
|
+import { TIMEOUTS } from '../../utils/timeouts';
|
|
|
|
|
+
|
|
|
|
|
+// 首页看板数据同步等待时间
|
|
|
|
|
+const SYNC_TIMEOUT = TIMEOUTS.networkIdle; // 10000ms
|
|
|
|
|
+
|
|
|
|
|
+// 首页数据刷新等待时间
|
|
|
|
|
+const REFRESH_TIMEOUT = TIMEOUTS.PAGE_LOAD; // 30000ms
|
|
|
|
|
+
|
|
|
|
|
+// 轮询检查间隔
|
|
|
|
|
+const POLL_INTERVAL = 500;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 下拉刷新实现
|
|
|
|
|
+
|
|
|
|
|
+小程序通常支持下拉刷新功能:
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+/**
|
|
|
|
|
+ * 下拉刷新首页看板数据
|
|
|
|
|
+ */
|
|
|
|
|
+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: 创建订单 → 首页看板显示卡片**
|
|
|
|
|
+```typescript
|
|
|
|
|
+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: 订单状态变化 → 首页看板状态徽章更新**
|
|
|
|
|
+```typescript
|
|
|
|
|
+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
|