--- stepsCompleted: ['step-01-init', 'step-02-discovery', 'step-03-success', 'step-04-journeys', 'step-07-project-type', 'step-08-scoping', 'step-09-functional', 'step-10-nonfunctional', 'step-11-complete', 'revision-2025-01-10', 'revision-2026-01-12'] inputDocuments: - name: 项目文档索引 path: docs/index.md type: project-knowledge loadedAt: '2026-01-07T12:00:00.000Z' - name: 测试策略 path: docs/standards/testing-standards.md type: testing-standards loadedAt: '2026-01-07T12:00:00.000Z' - name: Web UI测试规范 path: docs/standards/web-ui-testing-standards.md type: testing-standards loadedAt: '2026-01-07T12:00:00.000Z' - name: 残疾人管理组件 path: allin-packages/disability-person-management-ui/src/components/DisabilityPersonManagement.tsx type: source-code loadedAt: '2026-01-07T12:00:00.000Z' - name: 残疾人实体模型 path: allin-packages/disability-module/src/entities/disabled-person.entity.ts type: source-code loadedAt: '2026-01-07T12:00:00.000Z' - name: E2E测试示例 path: web/tests/e2e/specs/admin/users.spec.ts type: test-reference loadedAt: '2026-01-07T12:00:00.000Z' documentCounts: briefs: 0 research: 0 projectDocs: 3 testReferences: 1 workflowType: 'prd' lastStep: 6 revisedAt: '2026-01-12' revisionNotes: '修订范围:从"测试工具包开发"扩展为"Web E2E 测试覆盖",业务测试为主,工具包为支持手段;增加 Epic C: 订单管理 E2E 测试;新增 Epic D/E/F: 小程序相关测试(用户管理、跨端同步、基础配置)' --- # Product Requirements Document - Web 应用 E2E 测试覆盖 **作者:** Root **创建日期:** 2026-01-07 **修订日期:** 2026-01-10 --- ## 执行摘要 本项目旨在为 Web 管理后台的关键业务功能建立完整的 E2E 测试覆盖。在编写业务测试的过程中,将通用测试模式抽象到 `@d8d/e2e-test-utils` 包中,以加速后续功能的测试开发。 ### 项目背景 188-179 招聘系统是一个大型企业级 Monorepo 招聘管理平台,采用 React 19 + Hono 4.x + TypeORM 技术栈。现有 E2E 测试使用 Playwright,遵循 Page Object 模式。 当前残疾人管理功能已经实现了完整的业务逻辑,包括: - 照片上传管理(身份证、残疾证、个人照片等) - 银行卡信息管理(支持多张卡) - 备注管理(支持特殊需求标记) - 回访记录管理 订单管理是招聘系统的核心业务功能,包括: - 订单 CRUD 操作(创建、查看、编辑、删除) - 订单状态管理(草稿、已确认、进行中、已完成、已取消) - 人员关联管理(添加残疾人到订单、管理工作状态) - 附件管理(添加订单相关资产文件) - 多维度筛选(按平台、公司、渠道、状态等) 但 E2E 测试覆盖不完整,需要补充这些功能的测试用例。 ### 核心目标 **主目标:为 Web 管理后台的业务功能建立完整的 E2E 测试覆盖** **副目标:在测试过程中抽象可复用工具** **工作方式:测试驱动 + 工具演进** 1. **编写业务 E2E 测试**(主任务) - 优先完成业务功能的测试覆盖 - 验证业务逻辑的正确性 - 确保测试稳定性 2. **抽象通用测试工具**(自然演进) - 从业务测试中发现重复模式 - 将通用模式抽象到 `@d8d/e2e-test-utils` 包 - 持续完善工具函数 3. **输出两种形式** - **业务测试覆盖**:完整的 E2E 测试用例 - **共享测试工具包**:`packages/e2e-test-utils` ### Epic 组织 本项目按业务功能组织为多个 Epic: | Epic | 内容 | 状态 | |------|------|------| | **Epic A: 残疾人管理 E2E 测试** | 完整的残疾人管理功能测试覆盖 | ✅ 已完成 | | **Epic B: 区域管理 E2E 测试** | 区域管理(省市区街道)测试覆盖 | 🔄 待开发 | | **Epic C: 订单管理 E2E 测试** | 订单管理(CRUD、状态流转、人员关联)测试覆盖 | 📋 待开发 | | **Epic D: 用户管理与小程序登录测试** | 用户创建、小程序登录 E2E 测试 | 🆕 待开发 | | **Epic E: 跨端数据同步测试** | 后台操作 → 小程序数据验证 | 🆕 待开发 | | **Epic F: 基础配置管理测试** | 平台、公司、渠道配置管理测试 | 🆕 待开发 | | **Epic G: e2e-test-utils 包维护** | 支持性任务:维护测试工具包 | 🌟 持续演进 | **说明**: - Epic A、B、C 是**管理后台业务测试 Epic**,直接交付业务价值 - Epic D、E、F 是**小程序相关测试 Epic**,扩展测试覆盖到完整业务流程 - Epic G 是**支持性 Epic**,为业务测试提供工具支持 - 工具包的开发是**自然演进**的结果,不是预先规划的目标 ### 特殊价值 **这个项目的特殊之处在于:** 1. **业务价值优先**:直接交付业务测试覆盖,确保产品质量 2. **工具自然演进**:不是"为了做工具而做工具",而是从实践中抽象 3. **双重收益**: - 直接收益:完成业务功能的 E2E 测试覆盖 - 长期收益:可复用的测试工具,加速后续开发 4. **降低认知负担**:新测试开发者不需要深入理解 Radix UI 内部机制,只需调用统一 API 5. **提高测试稳定性**:统一的等待策略、错误处理和重试逻辑 ### 为什么现在做 - 残疾人管理功能已实现,E2E 测试覆盖是质量保障的需要 - 在编写残疾人管理测试时,发现可以抽象通用工具 - 未来还有更多管理功能需要测试,提前建立工具能避免重复工作 - 区域管理功能需要测试,是继续实践的好机会 - 订单管理是招聘系统的核心业务功能,涵盖 CRUD、状态流转、人员关联等复杂场景,是测试工具演进的绝佳实践场 --- ## 项目分类 **技术类型:** `testing`(E2E 测试覆盖) **领域:** `web_admin`(Web 管理后台业务功能测试) **复杂度:** `medium`(业务测试 + 工具抽象) **项目上下文:** 棕地项目 - 为现有 Web 管理后台补充 E2E 测试覆盖,遵循现有 Page Object 模式 --- ## 成功标准 ### 用户成功 **测试开发者视角的成功指标:** 1. **快速上手** - 新测试开发者在 30 分钟内能写出第一个包含 Radix UI Select 的测试用例 - 不需要深入研究 Radix UI 内部机制或 DOM 结构 2. **一次成功** - 第一次运行测试就通过,不需要反复调试时序问题 - 测试连续运行 20 次全部通过,无 flaky 失败 3. **易于维护** - 其他团队成员接手测试时,能在 10 分钟内理解并修改测试代码 - 测试代码清晰表达意图,不需要注释就能看懂 4. **稳定的开发体验** - 测试失败时能快速定位是产品问题还是测试问题 - 有清晰的错误提示指向问题所在 ### 业务成功 **业务测试覆盖率(主指标):** | 业务功能 | 目标覆盖率 | 当前状态 | 测量方式 | |---------|-----------|---------|---------| | 残疾人管理 | 关键流程 100% | ✅ 已完成 | 代码覆盖率报告 | | 区域管理 | 关键流程 100% | 🔄 待开发 | 代码覆盖率报告 | | 订单管理 | 关键流程 100% | 📋 待开发 | 代码覆盖率报告 | | 其他管理功能 | 按需补充 | ⏳ 规划中 | 业务优先级 | **短期(1-3个月)** - E2E 测试编写时间减少 50%(相比之前每次重新摸索) - 残疾人管理功能的测试覆盖率达到关键用户流程 100% ✅ - 区域管理功能的测试覆盖率达到关键用户流程 100% - 订单管理功能的测试覆盖率达到关键用户流程 100% - 工具函数被业务测试自然复用 **中期(3-6个月)** - 新功能的 E2E 测试开发周期显著缩短 - E2E 测试的 flaky 率降低到 5% 以下 - 至少 4 个管理功能完成 E2E 测试覆盖(残疾人、区域、订单、其他) **长期(6-12个月)** - 建立 E2E 测试规范成为团队标准 - 新人 E2E 测试培训时间减少 70% - 测试工具函数成为项目的标准基础设施 ### 技术成功 **代码质量** - 共享工具函数的测试覆盖率 ≥ 80% - TypeScript 类型安全,无 any 类型 - 代码通过 ESLint 和 TypeScript 严格模式检查 **可扩展性** - 新增组件测试模式只需扩展,无需修改核心逻辑 - 支持未来的 Radix UI 版本升级 - 工具函数设计支持配置和自定义 **文档完整性** - 测试指南覆盖所有提取的模式 - 每个模式至少提供 1 个实际使用示例 - 文档清晰说明静态 vs 异步 Select 的区别 ### 可衡量的结果 | 指标 | 当前状态 | 目标状态 | 测量方式 | |------|---------|---------|---------| | 残疾人管理测试覆盖率 | ✅ 关键流程 100% | ✅ 已达成 | 代码覆盖率报告 | | 区域管理测试覆盖率 | 0% | 关键流程 100% | 代码覆盖率报告 | | 订单管理测试覆盖率 | 0% | 关键流程 100% | 代码覆盖率报告 | | Radix Select 测试编写时间 | 需要研究/摸索 | 5 分钟内完成 | 计时实验 | | 测试稳定性(通过率) | 良好 | 20 次连续运行 100% 通过 | 自动化运行 | | 工具函数测试覆盖率 | 进行中 | ≥ 80% | 代码覆盖率报告 | | 文档完整性 | 基础 | 覆盖所有工具 + 示例 | 文档检查清单 | --- ## 产品范围 ### MVP - Minimum Viable Product **核心:为 Web 管理后台的业务功能建立完整的 E2E 测试覆盖** **1. Epic A: 残疾人管理 E2E 测试** ✅ 已完成 完整的残疾人管理功能测试覆盖: - 照片上传功能测试(身份证、残疾证、个人照片) - 银行卡管理功能测试(添加、编辑、删除) - 备注功能测试(添加、修改、删除) - 回访功能测试(记录创建、查看) - 完整流程测试(所有功能组合) **测试过程中抽象的工具:** - Radix UI Select 测试工具(静态/异步) - 文件上传测试工具 - 其他表单交互工具 **2. Epic B: 区域管理 E2E 测试** 🔄 当前目标 区域管理功能的完整测试覆盖: - 区域列表查看测试 - 添加区域测试(省/市/区/街道) - 编辑区域测试 - 删除区域测试 - 级联选择测试(省市区街道四级联动) - 完整流程测试 **可能需要抽象的工具:** - 级联选择测试工具(如现有工具不满足需求) - 树形结构操作工具(如需要) **3. Epic C: 订单管理 E2E 测试** 📋 待开发 订单管理功能的完整测试覆盖(核心业务功能): - 订单列表功能测试(查看、搜索、筛选、分页) - 订单 CRUD 测试(创建、编辑、删除订单) - 订单状态流转测试(激活订单、关闭订单) - 订单详情查看测试 - 人员关联功能测试(添加人员到订单、管理工作状态) - 附件管理测试(添加附件) - 完整流程测试 **可能需要抽象的工具(按需):** - 复杂表单提交工具(订单表单包含多个选择器:平台、公司、渠道) - 状态流转测试工具(订单状态变更操作) - 资产附件操作工具 **4. e2e-test-utils 包** 🌟 支持性任务 作为业务测试的支持工具,自然演进: ``` packages/e2e-test-utils/ ├── src/ │ ├── index.ts │ ├── select.ts # Radix UI Select 工具 ✅ │ ├── file-upload.ts # 文件上传工具 🔄 │ └── ... # 其他工具(按需添加) ├── tests/ └── README.md ``` **价值主张:** 业务测试覆盖直接交付价值,工具包是自然演进的支持产物。 **5. Epic D: 用户管理与小程序登录测试** 🆕 待开发 用户管理和小程序登录的完整测试覆盖: **测试前置条件:** - 管理员创建企业用户(EMPLOYER 类型),关联公司 - 管理员创建人才用户(TALENT 类型),关联残疾人 - 用户可登录到对应小程序 **测试场景:** - 用户管理 Page Object 开发 - 后台创建企业用户测试 - 后台创建人才用户测试 - 企业小程序 Page Object 开发 - 企业小程序登录测试 - 人才小程序 Page Object 开发 - 人才小程序登录测试 - 用户权限验证测试(确保小程序无写操作) **技术要点:** - 小程序通过 H5 URL 访问(`/mini` 和 `/talent-mini`) - 使用 Playwright 测试 H5 页面 - 登录后存储 token 进行后续操作 **6. Epic E: 跨端数据同步测试** 🆕 待开发 验证后台操作后小程序端的数据同步: **测试场景:** - 后台创建订单 → 企业小程序验证订单显示 - 后台编辑订单 → 企业小程序验证订单更新 - 后台添加残疾人到订单 → 人才小程序验证人员显示 - 后台更新工作状态 → 双小程序验证状态同步 - 跨端测试稳定性验证 **技术要点:** - 多 Page 对象管理(后台 + 小程序) - 数据同步等待策略 - WebSocket 通信验证(`/mini-ws`、`/talent-mini-ws`) - 测试隔离和清理 **7. Epic F: 基础配置管理测试** 🆕 待开发 平台、公司、渠道配置管理的测试覆盖: **实体关系链:** ``` Platform (平台) ↓ 1:N Company (公司) - 必须 platformId ↓ 1:N Order (订单) - 必须 companyId ``` **测试场景:** - Platform 管理测试 - 创建测试平台 - 验证平台列表显示 - Company 管理测试(重点) - 创建测试公司(需要先有平台) - 验证公司列表显示 - 验证平台关联 - Channel 管理测试(可选) - 创建测试渠道 - 验证渠道列表显示 - 配置数据验证 - 验证订单可以选择平台和公司 - 验证用户可以关联公司 **重要性说明:** - Platform 是订单创建的必要条件 - Company 是订单和企业用户的必要条件(关联 Platform) - Channel 是订单的可选条件 --- **Epic 优先级建议:** **Phase 1(当前进行中):** 1. **Epic B: 区域管理** - 相对简单,可作为工具演进实践 2. **Epic C: 订单管理** - 核心业务功能,复杂场景 **Phase 2(小程序测试):** 3. **Epic F: 基础配置管理** - 为后续 Epic 提供测试数据 - 必须先完成:Platform 和 Company 测试 4. **Epic D: 用户管理与小程序登录** - 小程序测试的入口 - 依赖:Epic F(需要 Company 数据) 5. **Epic E: 跨端数据同步测试** - 验证完整业务流程 - 依赖:Epic D 和 Epic C ### Growth Features (Post-MVP) **更多业务功能的 E2E 测试覆盖:** - 其他管理功能的测试(按业务优先级) - 用户权限管理测试 - 系统配置管理测试 - 报表功能测试 **工具包持续演进(按需):** - 在编写新业务测试时,如发现重复模式则抽象新工具 - Date Picker、Slider、Tabs 等 Radix 组件测试模式(如业务需要) - 表单验证错误处理测试模式(如业务需要) **开发体验增强:** - VS Code snippets 快速插入测试代码 - 测试模板和最佳实践文档 - 更完善的错误提示和调试信息 ### Vision (Future) **完整的 E2E 测试覆盖:** - Web 管理后台所有关键功能的测试覆盖 - 自动化测试作为 CI/CD 的标准环节 - 测试覆盖率可视化仪表盘 **智能化测试开发:** - AI 辅助测试编写(描述行为自动生成测试) - 自动发现页面组件并生成测试骨架 - 智能等待策略(根据组件特性自动调整) **团队测试文化:** - 测试驱动开发成为团队标准实践 - 新人培训包含 E2E 测试开发 - 测试模式库和最佳实践分享 --- ## 用户旅程 ### 旅程 1:张伟 - 赶时间的测试开发者 **人物设定:** - **姓名:** 张伟 - **角色:** 全栈开发者,需要为新功能编写 E2E 测试 - **情境:** 产品经理刚刚要求他为残疾人管理功能补充完整的 E2E 测试 - **痛点:** 之前每次写测试都要花大量时间研究 Radix UI 的 DOM 结构,测试经常因为时序问题失败 - **目标:** 快速完成测试任务,测试要稳定可靠 **他的故事:** 周一早上,张伟接到任务:"残疾人管理功能需要补充照片上传、银行卡管理等功能的 E2E 测试,周三前完成。" 张伟叹了口气。上次写测试时,他花了整整一下午研究 Radix UI Select 的测试方法,还要处理各种时序问题。测试写完后还经常 flaky,团队 CI 管道里经常因为这个功能失败。 他打开项目,注意到有个新包 `packages/e2e-test-utils`。他好奇地点开 README,发现里面正好有他需要的 Radix UI Select 测试工具。 他决定试一试。只需要导入工具函数,然后调用 `selectRadixOption(page, '残疾类型', '视力残疾')` 就可以了。不需要研究 DOM 结构,不需要处理复杂的等待逻辑。 **第一个小时:** 张伟轻松完成了照片上传和银行卡管理的测试。这些功能之前他一直觉得很难测试,现在居然这么简单。 **第二个小时:** 他继续添加备注和回访功能的测试。遇到异步加载的省份选择器时,他发现工具函数已经处理了等待逻辑,直接用 `selectRadixOptionAsync` 就可以了。 **第三个小时:** 张伟写完最后一个测试,点击运行。所有测试一次性通过!他有些不敢相信,又运行了 5 次,全部稳定通过。 **结果:** 周二下午,张伟不仅完成了所有测试,还把工具函数推荐给了团队其他成员。他甚至有时间优化测试代码,让测试更清晰易懂。 --- ### 旅程需求总结 这些用户旅程揭示了以下核心需求: **测试开发者(张伟)的需求:** - 简单易用的 API,不需要深入理解 Radix UI - 自动处理等待和时序问题 - 清晰的错误提示和调试信息 - 完整的使用文档和示例 - 工具函数开箱即用,快速集成 **新手测试开发者的需求:** - 快速入门指南,降低学习曲线 - 渐进式的学习路径(从简单到复杂) - 丰富的实际代码示例 - 常见问题和解决方案文档 **QA 工程师的需求:** - 测试工具函数的可靠性保障 - 测试覆盖率和质量报告 - 测试最佳实践指南 - 团队协作和代码审查支持 **Tech Lead 的需求:** - 代码质量和可维护性标准 - 测试模式的一致性和规范性 - 技术决策文档和架构说明 - 团队培训和知识传递材料 --- ## Developer Tool Specific Requirements ### Project-Type Overview 188-179 E2E 测试工具包是一个**开发者工具库**,专注于简化 Playwright E2E 测试中对 Radix UI 组件的测试。作为内部工具包,它需要提供清晰的 API、完整的类型安全和易用的开发体验。 ### Technical Architecture Considerations **语言与类型系统:** - 纯 TypeScript 实现,目标 ES2020+ - 严格类型检查,无 `any` 类型 - 完整的 JSDoc 注释用于 IDE 提示 **包结构:** ``` packages/e2e-test-utils/ ├── package.json ├── src/ │ ├── index.ts # 主导出 │ ├── radix-select.ts # Radix UI Select 工具 │ ├── file-upload.ts # 文件上传工具 │ ├── form-helper.ts # 表单辅助函数 │ ├── dialog.ts # 对话框操作 │ └── dynamic-list.ts # 动态列表管理 ├── tests/ # 工具函数的单元测试 └── README.md ``` **依赖管理:** - Peer dependency: `@playwright/test` (由测试项目提供) - 无运行时依赖,保持轻量 - 开发依赖: TypeScript, Vitest (用于自测) ### Language & API Matrix | 组件类型 | 工具函数 | 参数 | 返回值 | |---------|---------|------|--------| | Radix UI Select (静态) | `selectRadixOption(page, label, value)` | Page, 标签文本, 选项值 | Promise\ | | Radix UI Select (异步) | `selectRadixOptionAsync(page, label, value, options)` | Page, 标签文本, 选项值, 等待配置 | Promise\ | | 文件上传 | `uploadFileToField(page, selector, fileName)` | Page, 选择器, 文件名 | Promise\ | | 多步骤表单 | `fillMultiStepForm(page, steps)` | Page, 步骤数组 | Promise\ | | 动态列表 | `addDynamicListItem(page, itemType, data)` | Page, 项类型, 数据 | Promise\ | | 对话框操作 | `handleDialog(page, action)` | Page, 操作类型 | Promise\ | ### Installation Methods **在测试项目中安装:** ```bash # 在 web/ 目录下 pnpm add -D @d8d/e2e-test-utils@workspace:* ``` **在测试文件中导入:** ```typescript import { selectRadixOption, uploadFileToField } from '@d8d/e2e-test-utils'; ``` ### API Surface **核心工具函数签名:** ```typescript /** * 选择 Radix UI 下拉框的静态选项 * @param page Playwright Page 对象 * @param label 下拉框标签文本 * @param value 要选择的选项值 */ export async function selectRadixOption( page: Page, label: string, value: string ): Promise /** * 选择 Radix UI 下拉框的异步加载选项 * @param page Playwright Page 对象 * @param label 下拉框标签文本 * @param value 要选择的选项值 * @param options 等待配置 (超时、重试等) */ export async function selectRadixOptionAsync( page: Page, label: string, value: string, options?: AsyncSelectOptions ): Promise /** * 上传文件到指定字段 * @param page Playwright Page 对象 * @param selector 文件输入选择器 * @param fileName 要上传的文件名(相对于 fixtures 目录) */ export async function uploadFileToField( page: Page, selector: string, fileName: string ): Promise ``` ### Code Examples **示例 1:选择静态枚举型下拉框** ```typescript import { selectRadixOption } from '@d8d/e2e-test-utils'; // 选择残疾类型 await selectRadixOption(page, '残疾类型', '视力残疾'); ``` **示例 2:选择异步加载的下拉框** ```typescript import { selectRadixOptionAsync } from '@d8d/e2e-test-utils'; // 选择省份(异步加载) await selectRadixOptionAsync(page, '省份', '广东省', { timeout: 5000, waitForOption: true }); ``` **示例 3:上传照片** ```typescript import { uploadFileToField } from '@d8d/e2e-test-utils'; // 上传身份证照片 await uploadFileToField(page, '[data-testid="id-card-photo-input"]', 'sample-id-card.jpg'); ``` ### Migration Guide **从现有的内联测试代码迁移到工具函数:** **之前(内联代码):** ```typescript // 需要手动处理 Radix UI 的复杂 DOM 结构和时序 await page.click(`text=残疾类型`); await page.waitForSelector('[role="option"]'); await page.click(`[role="option"]:has-text("视力残疾")`); ``` **之后(使用工具函数):** ```typescript import { selectRadixOption } from '@d8d/e2e-test-utils'; await selectRadixOption(page, '残疾类型', '视力残疾'); ``` **迁移步骤:** 1. 安装工具包:`pnpm add -D @d8d/e2e-test-utils@workspace:*` 2. 导入需要的工具函数 3. 替换内联的 Radix UI 操作代码 4. 验证测试通过 ### Implementation Considerations **等待策略:** - 使用 `waitForLoadState('networkidle')` 处理异步加载 - 为静态选项设置合理默认超时(2秒) - 为异步选项提供可配置超时 **错误处理:** - 提供清晰的错误消息,指出具体失败点 - 区分"元素未找到"和"超时"错误 - 包含上下文信息(选择器、标签、期望值) **测试稳定性:** - 使用 Playwright 的 auto-waiting 机制 - 添加显式等待防止时序问题 - 支持重试机制处理 flaky 网络请求 **可扩展性:** - 工具函数支持配置对象参数 - 预留钩子函数用于自定义行为 - 设计支持未来 Radix UI 版本升级 --- ## Project Scoping & Phased Development ### MVP Strategy & Philosophy **MVP 方法:** 测试驱动 + 工具演进 核心理念:优先完成业务功能的 E2E 测试覆盖,在测试过程中自然抽象可复用工具。工具包是支持手段,不是目标本身。 **资源需求:** - 团队规模:1-2 名开发者 - 技能要求:TypeScript、Playwright、业务理解 - 时间估算:每个业务功能 1-2 周 ### MVP Feature Set (Phase 1) **核心用户旅程支持:** - ✅ 张伟的快速测试开发旅程(残疾人管理测试) - 🔄 张伟继续旅程(区域管理测试) - 📋 张伟再出发(订单管理测试) **Epic A: 残疾人管理 E2E 测试** ✅ 已完成 **业务测试覆盖:** - 照片上传功能测试 - 银行卡管理功能测试 - 备注功能测试 - 回访功能测试 - 完整流程测试 **测试过程中抽象的工具:** - `selectRadixOption()` - 静态枚举型下拉框 - `selectRadixOptionAsync()` - 异步加载型下拉框 - `uploadFileToField()` - 文件上传 - 其他表单辅助函数 **Epic B: 区域管理 E2E 测试** 🔄 当前目标 **业务测试覆盖:** - 区域列表查看 - 添加区域(省/市/区/街道) - 编辑区域 - 删除区域 - 级联选择测试 - 完整流程测试 **可能需要抽象的工具(按需):** - 级联选择工具(如现有 `selectCascade` 不满足需求) - 树形结构操作工具(如需要) **Epic C: 订单管理 E2E 测试** 📋 待开发 **业务测试覆盖:** - 订单列表功能(查看、搜索、筛选、分页) - 订单 CRUD 操作(创建、编辑、删除) - 订单状态流转(激活订单、关闭订单) - 订单详情查看 - 人员关联功能(添加人员、管理工作状态) - 附件管理(添加附件) - 完整流程测试 **可能需要抽象的工具(按需):** - 复杂表单提交工具(平台、公司、渠道等多选择器) - 状态流转测试工具(订单状态变更) - 资产附件操作工具 **e2e-test-utils 包维护** 🌟 持续演进 - 工具函数测试覆盖率 ≥ 80% - 完善文档和使用示例 - 按业务需求添加新工具 **MVP 排除的功能(留给后续版本):** - VS Code snippets - CLI 测试生成器 - AI 辅助测试生成 - 跨项目的工具包开源 ### Post-MVP Features **Phase 2 (Post-MVP) - 业务测试扩展:** **更多业务功能测试:** - 其他管理功能的 E2E 测试覆盖 - 按业务优先级和风险评估确定测试顺序 - 每个功能的完整测试用例 **工具包按需演进:** - 在编写新业务测试时,如发现重复模式则抽象新工具 - Date Picker、Slider、Tabs 等(如业务需要) - 表单验证错误处理模式(如业务需要) **开发体验增强:** - VS Code snippets 快速插入 - 测试模板和最佳实践文档 - 更完善的错误提示和调试信息 **质量保障:** - CI/CD 集成测试报告 - 测试覆盖率趋势追踪 - Flaky 测试检测和报告 ### Risk Mitigation Strategy **技术风险:** - **风险:** Radix UI DOM 结构变化导致工具函数失效 - **缓解:** - 使用稳定的选择器策略(role、data-testid) - 设计可扩展的函数签名,支持自定义选择器 - 工具函数自测,快速发现问题 **业务测试风险:** - **风险:** 业务功能变更导致测试用例失效 - **缓解:** - 测试用例与业务实现解耦 - 使用 Page Object 模式提高可维护性 - 定期审查和更新测试用例 **市场/采用风险:** - **风险:** 团队成员不愿意使用新工具,继续用老方法 - **缓解:** - 通过实际业务测试证明价值 - 渐进式推广:让早期使用者推荐给团队 - 完善文档:降低学习成本 **资源风险:** - **风险:** 测试开发时间超出预期 - **缓解:** - 按业务优先级排序,先做高价值功能 - 每个业务功能独立时间盒(1-2 周) - 降级方案:优先保证关键路径的测试覆盖 **质量风险:** - **风险:** 测试不稳定,经常 flaky 失败 - **缓解:** - 工具函数编写单元测试 - 20 次连续运行稳定性验证 - 代码审查确保质量 ### Scope Decision Rationale **为什么 MVP 范围这样设计:** 1. **业务价值优先**:直接交付业务测试覆盖,确保产品质量 2. **工具自然演进**:不预设工具需求,从实践中抽象 3. **渐进式扩展**:每个业务功能独立 Epic,可并行或串行 4. **可测量成果**:每个 Epic 都有明确的成功标准(覆盖率、稳定性) 5. **风险可控**:范围明确,时间盒限制,有降级方案 **MVP 成功标志:** - ✅ 残疾人管理 E2E 测试覆盖关键流程 100% - ✅ 测试连续运行 20 次,100% 通过 - ✅ 从测试中抽象可复用工具 - 🔄 区域管理 E2E 测试覆盖关键流程 100% - 📋 订单管理 E2E 测试覆盖关键流程 100% --- ## Functional Requirements ### Radix UI Select 组件测试支持 - FR1: 测试开发者可以使用工具函数选择静态枚举型 Radix UI Select 下拉框的选项 - FR2: 测试开发者可以使用工具函数选择异步加载型 Radix UI Select 下拉框的选项 - FR3: 工具函数可以自动处理 Radix UI Select 的 DOM 结构和交互流程 - FR4: 工具函数可以等待异步加载的选项出现在下拉列表中 - FR5: 工具函数可以提供清晰的错误提示,包含标签、期望值等上下文信息 - FR6: 工具函数可以区分"元素未找到"和"超时"错误类型 ### 文件上传测试支持 - FR7: 测试开发者可以使用工具函数上传文件到指定的文件输入字段 - FR8: 工具函数可以从 fixtures 目录加载测试文件 - FR9: 工具函数可以支持多文件上传场景 - FR10: 工具函数可以验证文件上传是否成功完成 ### 表单交互测试支持 - FR11: 测试开发者可以使用工具函数填写多步骤表单 - FR12: 工具函数可以滚动页面到特定的表单区域 - FR13: 工具函数可以处理表单验证错误场景 - FR14: 测试开发者可以使用工具函数提交表单并等待响应 - FR15: 工具函数可以支持常见的表单字段类型(文本、选择器、日期等) ### 动态列表测试支持 - FR16: 测试开发者可以使用工具函数向动态列表中添加新项 - FR17: 测试开发者可以使用工具函数从动态列表中删除项 - FR18: 工具函数可以支持不同类型的动态列表项(银行卡、备注等) - FR19: 工具函数可以验证动态列表项添加或删除后的状态 - FR20: 工具函数可以处理动态列表的异步更新场景 ### 对话框操作测试支持 - FR21: 测试开发者可以使用工具函数统一操作对话框(确认、取消、关闭) - FR22: 工具函数可以等待对话框完全关闭后再继续执行 - FR23: 工具函数可以处理对话框内的表单填写和提交 - FR24: 工具函数可以验证对话框是否按预期打开或关闭 ### 测试工具包基础设施 - FR25: 测试开发者可以通过 npm workspace 协议安装测试工具包 - FR26: 工具包可以作为 peer dependency 依赖 Playwright,不增加运行时依赖 - FR27: 工具包提供完整的 TypeScript 类型定义和类型提示 - FR28: 工具包的所有导出函数都有完整的 JSDoc 注释 - FR29: 工具包使用严格类型检查,不使用 any 类型 - FR30: 工具包支持目标 ES2020+ 的 JavaScript 环境 - FR31: 工具包的每个工具函数都可以独立导入和使用 - FR32: 工具包可以与其他测试工具和库兼容使用 ### 文档和开发者支持 - FR33: 测试开发者可以通过 README 快速了解工具包的用途和安装方法 - FR34: 文档提供每个工具函数的详细使用示例 - FR35: 文档提供静态 Select 和异步 Select 的区别说明 - FR36: 文档提供从现有测试代码迁移到工具函数的指南 - FR37: 文档提供常见问题和解决方案 - FR38: 文档提供残疾人管理测试作为完整的使用示例 - FR39: 测试开发者可以在 30 分钟内使用工具函数编写第一个测试 - FR40: 工具包的使用示例覆盖所有 6 个核心工具函数 ### 测试质量和稳定性保障 - FR41: 工具函数使用 Playwright 的 auto-waiting 机制防止时序问题 - FR42: 工具函数为静态选项设置合理的默认超时配置 - FR43: 工具函数为异步选项提供可配置的超时参数 - FR44: 工具函数可以支持重试机制处理不稳定的网络请求 - FR45: 工具函数可以在测试连续运行 20 次时保持 100% 通过率 ### 可扩展性和维护性 - FR46: 工具函数支持配置对象参数,允许自定义行为 - FR47: 工具函数设计支持未来的 Radix UI 版本升级 - FR48: 工具函数使用稳定的选择器策略(role、data-testid) - FR49: 工具包预留扩展接口,支持新增其他 Radix 组件测试模式 - FR50: 工具包的代码结构清晰,便于团队贡献和维护 --- ## Non-Functional Requirements ### 可靠性 **测试稳定性(最关键):** - NFR1: 工具函数在相同条件下连续运行 20 次,必须保持 100% 通过率,无 flaky 失败 - NFR2: 工具函数能够正确处理异步加载场景,避免时序问题导致的测试失败 - NFR3: 当 DOM 元素暂时不可用时,工具函数提供清晰的错误消息,而不是超时无响应 - NFR4: 工具函数能够区分产品 bug 和测试代码问题,帮助开发者快速定位问题根源 **错误处理和诊断:** - NFR5: 当选择操作失败时,错误消息包含以下信息: - 下拉框标签名称 - 期望选择的值 - 实际可用的选项列表 - 失败原因(元素未找到、超时、选项不存在等) - NFR6: 当文件上传失败时,错误消息包含文件路径、选择器、失败原因 - NFR7: 错误消息格式统一,便于日志分析和问题定位 ### 性能 **测试执行效率:** - NFR8: 单个 Radix UI Select 选择操作(静态)应在 2 秒内完成 - NFR9: 单个 Radix UI Select 选择操作(异步)应在 5 秒内完成(默认超时) - NFR10: 工具函数本身的开销不超过 100ms(不包括 Playwright 操作时间) - NFR11: 使用工具函数的测试比手动编写 DOM 操作的测试执行时间差异 < 10% **等待策略优化:** - NFR12: 静态选项使用合理的默认超时(2 秒),避免不必要的等待 - NFR13: 异步选项提供可配置的超时参数,默认值为 5 秒 - NFR14: 工具函数使用 Playwright 的 auto-waiting 机制,减少显式等待的需要 ### 集成性 **Playwright 兼容性:** - NFR15: 工具包兼容 Playwright 最新稳定版本和上一个 LTS 版本 - NFR16: 工具包可以作为 peer dependency 引用,不增加运行时依赖 - NFR17: 工具函数接受标准 Playwright Page 对象作为参数 - NFR18: 工具包不依赖特定版本的 Playwright,使用灵活的版本范围 **测试框架集成:** - NFR19: 工具函数可以在任何使用 Playwright 的测试框架中运行(Vitest、Jest 等) - NFR20: 工具包不修改全局配置,不需要额外的测试框架配置 - NFR21: 工具函数可以与现有的 Page Object 模式无缝集成 **Monorepo 集成:** - NFR22: 工具包通过 pnpm workspace 协议安装,支持本地开发 - NFR23: 工具包的构建产物与项目的 TypeScript 配置兼容 - NFR24: 工具包的类型定义可以自动被 IDE 识别和提示 ### 代码质量 **类型安全:** - NFR25: 工具包使用 TypeScript 严格模式,无 `any` 类型 - NFR26: 所有导出函数都有完整的参数类型和返回值类型 - NFR27: 类型定义支持 IDE 自动补全和类型检查 - NFR28: 类型错误在编译时被捕获,不在运行时暴露 **代码可维护性:** - NFR29: 工具包的代码覆盖率 ≥ 80% - NFR30: 每个工具函数都有对应的单元测试 - NFR31: 代码遵循项目的 ESLint 和 Prettier 配置 - NFR32: 函数复杂度保持在低水平(圈复杂度 < 10) **文档质量:** - NFR33: 每个导出函数都有完整的 JSDoc 注释 - NFR34: README 包含快速入门、安装说明、基本用法 - NFR35: 每个工具函数至少有 1 个实际使用示例 - NFR36: 文档说明静态 Select 和异步 Select 的区别和使用场景 **开发者体验:** - NFR37: 新测试开发者可以在 30 分钟内使用工具函数编写第一个测试 - NFR38: 工具函数的命名清晰直观,不需要频繁查看文档 - NFR39: 函数参数设计简洁,必需参数 ≤ 3 个 - NFR40: 错误消息对新手友好,包含问题诊断和建议修复步骤 ### 兼容性 **浏览器和环境:** - NFR41: 工具函数在 Playwright 支持的所有浏览器中正常工作(Chromium、Firefox、WebKit) - NFR42: 工具函数在 headless 和 headed 模式下都能正常工作 - NFR43: 工具函数在 CI/CD 环境中稳定运行 **版本兼容性:** - NFR44: 工具包支持 Node.js 当前 LTS 版本和上一个 LTS 版本 - NFR45: 工具包的设计考虑未来 Radix UI 版本升级,使用稳定的选择器策略 - NFR46: 重大版本变更时提供迁移指南