# Story 13.7: 首页导航和交互测试 Status: ready-for-dev ## Story 作为测试开发者, 我想要验证企业小程序首页 dashboard 的导航和交互功能, 以便确保用户能够正常使用快捷操作和查看详情功能。 ## Acceptance Criteria ### AC1: 快捷操作按钮导航测试 **Given** 用户已登录企业小程序首页 **When** 点击快捷操作按钮 **Then** 测试应验证以下功能: - 验证"人才库"按钮可点击并跳转到人才库页面 - 验证"数据统计"按钮可点击并跳转到数据统计页面 - 验证"订单管理"按钮可点击并跳转到订单管理页面 - 验证"设置"按钮可点击并跳转到设置页面 ### AC2: "查看全部"链接测试 **Given** 首页显示分配人才列表 **When** 点击"查看全部"链接 **Then** 测试应验证以下功能: - 验证"查看全部"链接可点击 - 验证跳转到完整的人才列表页面 ### AC3: 人才卡片点击测试 **Given** 首页显示人才卡片 **When** 点击人才卡片 **Then** 测试应验证以下功能: - 验证人才卡片可点击 - 验证跳转到人才详情页面 - 验证详情页面显示正确的人才信息 ### AC4: 页面跳转验证 **Given** 用户执行导航操作 **When** 页面跳转完成后 **Then** 测试应验证以下场景: - 验证跳转后的页面 URL 正确 - 验证跳转后的页面标题正确 - 验证可以返回首页(底部导航"首页"按钮) ### AC5: 交互响应时间 **Given** 用户点击导航按钮 **When** 等待页面跳转 **Then** 测试应验证以下性能: - 验证按钮点击后页面在 2 秒内完成跳转 - 验证没有卡顿或延迟 ### AC6: 代码质量标准 **Given** 遵循项目测试规范 **When** 编写测试代码 **Then** 代码应符合以下标准: - 使用 TIMEOUTS 常量定义超时 - 使用 data-testid 选择器(优先级高于文本选择器) - 测试文件命名:`dashboard-navigation.spec.ts` - 完整的测试描述和注释 - TypeScript 类型安全 - 通过 `pnpm typecheck` 类型检查 ## Tasks / Subtasks - [ ] 任务 1: 创建首页导航测试文件 (AC: #1, #2, #3, #4, #5, #6) - [ ] 1.1 创建 `web/tests/e2e/specs/cross-platform/dashboard-navigation.spec.ts` - [ ] 1.2 配置测试 fixtures(enterpriseMiniPage) - [ ] 1.3 添加测试前置条件(企业用户登录) - [ ] 任务 2: 扩展 EnterpriseMiniPage 支持导航操作 (AC: #1, #2, #3, #4) - [ ] 2.1 添加快捷操作按钮选择器和方法 - [ ] 2.2 添加"查看全部"链接选择器和方法 - [ ] 2.3 添加人才卡片选择器和点击方法 - [ ] 2.4 添加页面 URL 验证方法 - [ ] 2.5 添加页面标题验证方法 - [ ] 2.6 添加返回首页方法 - [ ] 任务 3: 实现快捷操作按钮导航测试 (AC: #1, #4, #5) - [ ] 3.1 编写"点击人才库按钮跳转到人才库页面"测试 - [ ] 3.2 编写"点击数据统计按钮跳转到数据统计页面"测试 - [ ] 3.3 编写"点击订单管理按钮跳转到订单管理页面"测试 - [ ] 3.4 编写"点击设置按钮跳转到设置页面"测试 - [ ] 3.5 验证页面跳转 URL 正确 - [ ] 3.6 验证页面跳转在 2 秒内完成 - [ ] 任务 4: 实现"查看全部"链接测试 (AC: #2, #4, #5) - [ ] 4.1 编写"点击查看全部链接跳转到人才列表"测试 - [ ] 4.2 验证跳转后的页面 URL 正确 - [ ] 4.3 验证跳转后的页面标题正确 - [ ] 任务 5: 实现人才卡片点击测试 (AC: #3, #4, #5) - [ ] 5.1 编写"点击人才卡片跳转到人才详情"测试 - [ ] 5.2 验证详情页面显示正确的人才信息 - [ ] 5.3 验证详情页面 URL 正确 - [ ] 任务 6: 实现返回首页测试 (AC: #4) - [ ] 6.1 编写"点击底部导航首页按钮返回首页"测试 - [ ] 6.2 验证返回首页后 URL 正确 - [ ] 6.3 验证返回首页后页面元素正确显示 - [ ] 任务 7: 验证代码质量 (AC: #6) - [ ] 7.1 运行 `pnpm typecheck` 验证类型检查 - [ ] 7.2 运行测试确保所有测试通过 - [ ] 7.3 验证选择器使用 data-testid ## Dev Notes ### Epic 13 背景和依赖 **Epic 13: 跨端数据同步测试 (Epic E)** - **目标**: 验证后台操作后小程序端的数据同步,覆盖完整的业务流程 - **业务分组**: Epic E(跨端数据同步测试) - **背景**: 真实用户旅程跨越管理后台和小程序,需要验证数据同步的正确性和时效性 - **依赖**: - Epic 10: ✅ 已完成(订单管理 E2E 测试) - Epic 12: 🔄 进行中(小程序登录测试) - Story 13.6: ✅ 已完成(首页看板数据联动专项测试) **Epic 13 Story 依赖关系:** ``` Story 13.1: 后台创建订单 → 企业小程序**订单列表**验证 ✅ Story 13.2: 后台编辑订单 → 企业小程序验证 Story 13.3: 后台添加人员 → 人才小程序验证 Story 13.4: 后台更新状态 → 双小程序验证 Story 13.5: 跨端测试稳定性验证 Story 13.6: 后台添加人员 → 企业小程序**首页 dashboard** 人才数据验证 ✅ Story 13.7: 企业小程序首页 **导航和交互**测试 ← 当前 Story ``` ### 与 Story 13.6 的区别 | 维度 | Story 13.6 | Story 13.7 | |------|-----------|-----------| | **验证目标** | 首页 **数据同步** | 首页 **导航和交互** | | **验证内容** | 分配人才列表、核心统计数字 | 快捷操作按钮、查看全部链接、人才卡片点击 | | **测试场景** | 后台添加人员 → 验证首页数据变化 | 点击按钮/链接 → 验证页面跳转 | | **测试方法** | `getAssignedTalentCards()`, `getCoreStatistics()` | `clickQuickAction()`, `clickViewAll()`, `clickTalentCard()` | ### 企业小程序首页导航结构 **首页 dashboard 导航结构:** ``` ┌─────────────────────────────────┐ │ 企业仪表板 (mini-dashboard) │ ├─────────────────────────────────┤ │ 欢迎区域: │ │ - 欢迎回来 │ │ - 企业名称 │ ├─────────────────────────────────┤ │ 统计卡片: │ │ ┌─────────┬─────────┬─────────┐│ │ │ 在职人员 │ 待入职 │ 本月新增 ││ │ └─────────┴─────────┴─────────┘│ ├─────────────────────────────────┤ │ 快捷操作: │ │ ┌───────┬───────┬───────┬─────┐│ │ │人才库 │数据统计│订单管理│设置 ││ │ └───────┴───────┴───────┴─────┘│ ├─────────────────────────────────┤ │ 分配人才区域: │ │ - 人才卡片 1, 2, 3... │ │ - [查看全部] ← 可点击链接 │ ├─────────────────────────────────┤ │ 底部导航: │ │ ┌────┬────┬────┬────┬────┐ │ │ │首页│人才│订单│数据│设置│ │ │ └────┴────┴────┴────┴────┘ │ └─────────────────────────────────┘ ``` **导航交互流程:** ``` 用户点击快捷操作按钮 → 页面跳转 → 验证 URL 和标题 ↓ 用户可以点击底部导航"首页"返回 → 返回首页 → 验证首页元素 ``` ### Story 13.6 关键经验(首页看板测试) 从已完成的 Story 13.6 中学习到的首页看板测试模式: **企业小程序首页 data-testid:** ```typescript const DASHBOARD_SELECTORS = { dashboard: 'mini-dashboard', quickActions: 'mini-quick-actions', talentCard: 'mini-assigned-talent-card', talentName: 'mini-talent-name', }; ``` **首页结构发现:** - 首页包含快捷操作按钮(人才库、数据统计、订单管理、设置) - 首页包含分配人才区域(人才卡片列表) - 首页包含底部导航栏 - 小程序首页**部分**元素有 data-testid 属性 ### EnterpriseMiniPage 扩展方法 需要添加以下方法到 `enterprise-mini.page.ts`: ```typescript /** * 点击快捷操作按钮 * @param action 快捷操作名称:'talent-pool' | 'data-stats' | 'order-management' | 'settings' */ async clickQuickAction(action: string): Promise { // 根据不同的快捷操作,点击对应按钮 const buttons = { 'talent-pool': '人才库', 'data-stats': '数据统计', 'order-management': '订单管理', 'settings': '设置', }; const buttonText = buttons[action]; if (!buttonText) { throw new Error(`未知的快捷操作: ${action}`); } // 使用文本选择器(小程序可能缺少 data-testid) await this.page.getByText(buttonText).click(); } /** * 点击"查看全部"链接 */ async clickViewAll(): Promise { // 使用文本选择器查找"查看全部"链接 await this.page.getByText('查看全部').click(); } /** * 点击人才卡片 * @param talentName 人才姓名 */ async clickTalentCard(talentName: string): Promise { // 找到对应姓名的人才卡片并点击 const card = this.page.getByText(talentName); await card.click(); } /** * 验证当前页面 URL * @param expectedUrl 预期的 URL */ async expectUrl(expectedUrl: string): Promise { await this.page.waitForURL(`**${expectedUrl}**`, { timeout: TIMEOUTS.PAGE_LOAD }); expect(this.page.url()).toContain(expectedUrl); } /** * 验证页面标题 * @param expectedTitle 预期的页面标题 */ async expectPageTitle(expectedTitle: string): Promise { const title = await this.page.title(); expect(title).toContain(expectedTitle); } /** * 返回首页 */ async goBackToHome(): Promise { // 点击底部导航的"首页"按钮 await this.page.getByText('首页').click(); // 等待首页加载 await this.page.waitForTimeout(TIMEOUTS.PAGE_LOAD); } ``` ### 小程序导航验证策略 **Taro 小程序路由机制:** ```typescript // Taro 小程序使用 Hash 路由 // URL 格式:http://localhost:8080/mini#/pages/dashboard // 验证页面跳转 async expectUrl(expectedUrl: string): Promise { // 等待 URL 变化 await this.page.waitForURL(`**${expectedUrl}**`, { timeout: TIMEOUTS.PAGE_LOAD }); // 验证 URL 包含预期路径 const actualUrl = this.page.url(); expect(actualUrl).toContain(expectedUrl); } ``` **页面跳转时间测量:** ```typescript async measureNavigationTime( action: () => Promise ): Promise { const startTime = Date.now(); await action(); await this.page.waitForLoadState('networkidle', { timeout: TIMEOUTS.PAGE_LOAD }); return Date.now() - startTime; } ``` ### 测试数据准备策略 **前置条件:** 1. 需要企业用户数据(使用 Story 12.2 创建的企业用户) 2. 需要分配人才数据(使用 Story 13.6 创建的人才数据) **测试数据唯一性:** ```typescript // 使用 Story 13.6 创建的分配人才数据 // 无需额外创建数据,直接使用现有数据测试导航功能 ``` ### 选择器策略 **优先级(遵循项目标准):** 1. `data-testid` 属性(最高优先级) 2. 文本内容(小程序可能缺少 data-testid) 3. CSS 类(兜底选择器) **小程序导航相关的选择器:** - 快捷操作按钮:使用文本选择器 `getByText('人才库')` - 查看全部链接:使用文本选择器 `getByText('查看全部')` - 人才卡片:使用文本选择器 `getByText(talentName)` - 底部导航:使用文本选择器 `getByText('首页')` ### TypeScript 类型定义 **导航测试类型:** ```typescript type QuickActionType = 'talent-pool' | 'data-stats' | 'order-management' | 'settings'; interface NavigationResult { /** 导航是否成功 */ navigated: boolean; /** 导航耗时(毫秒) */ navigationTime: number; /** 目标 URL */ targetUrl: string; /** 页面标题 */ pageTitle?: string; } ``` ### 测试超时配置 **使用 TIMEOUTS 常量:** ```typescript import { TIMEOUTS } from '../../utils/timeouts'; // 页面跳转等待时间 const NAVIGATION_TIMEOUT = 2000; // 2 秒 // 页面加载等待时间 const PAGE_LOAD_TIMEOUT = TIMEOUTS.PAGE_LOAD; // 30000ms ``` ### 调试技巧 **导航测试调试:** 1. 使用 `page.url()` 获取当前 URL 2. 使用 `page.title()` 获取页面标题 3. 使用 `page.screenshot()` 在关键步骤截图 4. 记录导航时间 **导航问题调试:** - 检查 URL 是否正确变化 - 检查页面是否正确加载 - 验证页面元素是否正确显示 ### 参考文档 **架构文档:** - `_bmad-output/planning-artifacts/epics.md#Epic 13` - `_bmad-output/project-context.md` - `docs/standards/e2e-radix-testing.md` **相关 Story 文档:** - `12-4-enterprise-mini-page-object.md` (企业小程序 Page Object) - `12-5-enterprise-mini-login.md` (企业小程序登录测试) - `13-1-order-create-sync.md` (订单列表同步测试) - `13-6-dashboard-sync.md` (首页看板数据联动测试) ### 测试场景示例 **场景 1: 快捷操作按钮导航** ```typescript test('点击人才库按钮跳转到人才库页面', async ({ enterpriseMiniPage }) => { // 1. 登录并进入首页 await enterpriseMiniPage.goto(); await enterpriseMiniPage.login('13800138000', 'password123'); await enterpriseMiniPage.expectLoginSuccess(); // 2. 点击人才库按钮 const startTime = Date.now(); await enterpriseMiniPage.clickQuickAction('talent-pool'); // 3. 验证跳转 await enterpriseMiniPage.expectUrl('/pages/talent'); await enterpriseMiniPage.expectPageTitle('人才'); // 4. 验证响应时间 const navigationTime = Date.now() - startTime; expect(navigationTime).toBeLessThanOrEqual(2000); }); ``` **场景 2: 人才卡片点击** ```typescript test('点击人才卡片跳转到人才详情', async ({ enterpriseMiniPage }) => { // 1. 登录并进入首页 await enterpriseMiniPage.goto(); await enterpriseMiniPage.login('13800138000', 'password123'); await enterpriseMiniPage.expectLoginSuccess(); // 2. 点击人才卡片 const talentName = '测试残疾人_1768346782426_12_8219'; await enterpriseMiniPage.clickTalentCard(talentName); // 3. 验证跳转 await enterpriseMiniPage.expectUrl('/pages/talent-detail'); // 4. 验证详情页面显示正确的人才信息 const pageText = await enterpriseMiniPage.page.textContent('body'); expect(pageText).toContain(talentName); }); ``` **场景 3: 返回首页** ```typescript test('点击底部导航首页按钮返回首页', async ({ enterpriseMiniPage }) => { // 1. 登录并进入首页 await enterpriseMiniPage.goto(); await enterpriseMiniPage.login('13800138000', 'password123'); await enterpriseMiniPage.expectLoginSuccess(); // 2. 导航到其他页面 await enterpriseMiniPage.clickQuickAction('talent-pool'); await enterpriseMiniPage.expectUrl('/pages/talent'); // 3. 返回首页 await enterpriseMiniPage.goBackToHome(); // 4. 验证返回首页 await enterpriseMiniPage.expectUrl('/pages/dashboard'); await expect(enterpriseMiniPage.page.getByTestId('mini-dashboard')).toBeVisible(); }); ``` ## Dev Agent Record ### Agent Model Used _Creation phase - Claude Opus 4.5_ ### Debug Log References _Story 13.7 created_ ### Completion Notes List 1. **Story 13.7 创建完成**: - 首页导航和交互测试需求 - 与 Story 13.6 的区别说明 - EnterpriseMiniPage 扩展方法定义 - 状态:ready-for-dev ### File List _Created files:_ - `/mnt/code/188-179-template-6/_bmad-output/implementation-artifacts/13-7-dashboard-navigation.md` - `/mnt/code/188-179-template-6/_bmad-output/implementation-artifacts/sprint-status.yaml` (updated) ## Change Log - 2026-01-14: Story 13.7 创建完成 - 首页导航和交互测试需求 - 快捷操作按钮、查看全部链接、人才卡片点击 - 与 Story 13.6 的区别说明 - EnterpriseMiniPage 扩展方法定义 - 状态:ready-for-dev ---