Kaynağa Gözat

📝 docs(implementation): 创建 Story 1.1 包基础结构和配置

- 创建完整的用户故事文档,包含详细的开发者上下文
- Epic 1 状态更新为 in-progress
- Story 1-1 状态更新为 ready-for-dev

🤖 Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 hafta önce
ebeveyn
işleme
7067aa4909

+ 513 - 0
_bmad-output/implementation-artifacts/1-1-create-package-structure.md

@@ -0,0 +1,513 @@
+# Story 1.1: 创建包基础结构和配置
+
+Status: ready-for-dev
+
+<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
+
+## Story
+
+作为测试开发者,
+我想要可以安装 `@d8d/e2e-test-utils` 包,
+以便在项目中使用测试工具函数。
+
+## Acceptance Criteria
+
+**Given** 项目是 Monorepo 结构
+**When** 创建 `packages/e2e-test-utils/` 目录
+**Then** 目录结构包含 `src/`, `tests/`, `package.json`, `tsconfig.json`, `vitest.config.ts`
+**And** `package.json` 包含正确的包名、版本、peer dependencies(`@playwright/test`)
+**And** `tsconfig.json` 启用严格模式,目标 ES2020+
+**And** 可以通过 `pnpm add -D @d8d/e2e-test-utils@workspace:*` 安装
+
+## Tasks / Subtasks
+
+- [ ] 创建目录结构 (AC: 1)
+  - [ ] 创建 `packages/e2e-test-utils/` 根目录
+  - [ ] 创建 `src/` 源代码目录
+  - [ ] 创建 `tests/` 测试目录
+  - [ ] 创建 `tests/fixtures/` 测试资源目录
+  - [ ] 创建 `tests/unit/` 单元测试目录
+  - [ ] 创建 `tests/integration/` 集成测试目录
+  - [ ] 创建 `tests/stability/` 稳定性测试目录
+- [ ] 配置 package.json (AC: 2, 4)
+  - [ ] 设置包名 `@d8d/e2e-test-utils`
+  - [ ] 设置版本号 `1.0.0`
+  - [ ] 配置 peer dependency `@playwright/test`
+  - [ ] 配置开发依赖(TypeScript, Vitest)
+  - [ ] 添加必要的 scripts(build, dev, test, typecheck)
+  - [ ] 配置 exports 用于 tree-shaking
+- [ ] 配置 tsconfig.json (AC: 3)
+  - [ ] 启用严格模式(`strict: true`)
+  - [ ] 设置目标 ES2020+(`target: "ES2020"`)
+  - [ ] 配置模块系统(`module: "ESNext"`)
+  - [ ] 配置路径解析(`baseUrl: "."`, `paths`)
+- [ ] 配置 vitest.config.ts (AC: 1)
+  - [ ] 设置测试目录为 `tests/unit`
+  - [ ] 配置覆盖率目标 ≥80%
+  - [ ] 配置测试超时时间
+- [ ] 创建基础占位文件
+  - [ ] 创建 `src/index.ts` 导出入口
+  - [ ] 创建 `src/types.ts` 类型定义占位
+  - [ ] 创建 `src/errors.ts` 错误类占位
+  - [ ] 创建 `src/constants.ts` 常量占位
+  - [ ] 创建 `README.md` 基础文档
+- [ ] 验证包可被安装 (AC: 4)
+  - [ ] 在 monorepo 根目录运行 `pnpm install`
+  - [ ] 验证包可以被引用 `@d8d/e2e-test-utils@workspace:*`
+  - [ ] 运行 `pnpm typecheck` 验证类型检查通过
+
+## Dev Notes
+
+### Epic 1 背景
+
+**Epic 1 目标:** 测试开发者可以安装 `@d8d/e2e-test-utils` 包,立即使用 Select 工具测试 Radix UI Select 组件(最常用、最关键的测试场景)。
+
+**本故事在 Epic 中的位置:** 第一个故事,建立包基础设施,为后续所有工具函数提供基础。
+
+### 相关架构决策
+
+从架构文档中提取的关键架构决策:
+
+**包结构决策(按功能分组):**
+```
+packages/e2e-test-utils/
+├── src/
+│   ├── index.ts              # 主导出,tree-shakeable
+│   ├── types.ts              # 共享类型定义
+│   ├── errors.ts             # 错误类和错误处理
+│   ├── constants.ts          # 常量定义(超时、选择器策略等)
+│   ├── radix-select.ts       # Radix UI Select 工具(后续故事)
+│   ├── file-upload.ts        # 文件上传工具(后续故事)
+│   ├── form-helper.ts        # 表单辅助函数(后续故事)
+│   ├── dialog.ts             # 对话框操作(后续故事)
+│   └── dynamic-list.ts       # 动态列表管理(后续故事)
+├── tests/
+│   ├── fixtures/             # 测试资源
+│   ├── unit/                 # Vitest 单元测试
+│   ├── integration/          # Playwright 集成测试
+│   └── stability/            # 稳定性测试
+├── package.json
+├── tsconfig.json
+├── vitest.config.ts
+└── README.md
+```
+
+**API 设计模式:** 3个必需参数 + 可选配置对象
+- 必需参数 ≤ 3 个
+- 复杂配置通过可选对象传递
+- 类型推断友好
+- JSDoc 完整
+
+**类型系统策略:** 分层类型(共享+特定)
+- `types.ts` 存放共享类型(`BaseOptions`)
+- 各模块文件存放特定类型(如 `AsyncSelectOptions`)
+
+**选择器策略:** 混合策略(testid → ARIA → 文本)
+1. `data-testid` - 最高优先级
+2. `aria-label` + role - 无障碍标准
+3. Text content + role - 兜底方案
+
+**错误处理策略:** 结构化错误类 + 友好消息
+```typescript
+export class E2ETestError extends Error {
+  constructor(
+    public readonly context: ErrorContext,
+    message?: string
+  ) { ... }
+}
+```
+
+### 技术栈约束
+
+**语言与类型系统:**
+- 纯 TypeScript 实现,目标 ES2020+
+- 严格类型检查,无 `any` 类型
+- 完整的 JSDoc 注释用于 IDE 提示
+
+**依赖管理:**
+- **Peer dependency**: `@playwright/test`(由测试项目提供)
+- **无运行时依赖**,保持轻量
+- **开发依赖**: TypeScript, Vitest(用于自测)
+
+### package.json 配置要求
+
+**参考现有的 `@d8d/shared-test-util` 包结构:**
+
+```json
+{
+  "name": "@d8d/e2e-test-utils",
+  "version": "1.0.0",
+  "description": "E2E testing utilities for Radix UI components",
+  "type": "module",
+  "main": "src/index.ts",
+  "types": "src/index.ts",
+  "exports": {
+    ".": {
+      "import": "./src/index.ts",
+      "require": "./src/index.ts",
+      "types": "./src/index.ts"
+    }
+  },
+  "files": [
+    "src"
+  ],
+  "scripts": {
+    "build": "tsc",
+    "dev": "tsc --watch",
+    "test": "vitest",
+    "test:unit": "vitest run tests/unit/**/*.test.ts",
+    "test:coverage": "vitest --coverage",
+    "typecheck": "tsc --noEmit"
+  },
+  "peerDependencies": {
+    "@playwright/test": "^1.40.0"
+  },
+  "devDependencies": {
+    "typescript": "^5.8.3",
+    "vitest": "^3.2.4",
+    "@vitest/coverage-v8": "^3.2.4"
+  },
+  "keywords": [
+    "e2e",
+    "testing",
+    "playwright",
+    "radix-ui",
+    "test-utilities"
+  ]
+}
+```
+
+**关键点:**
+1. 使用 `type: "module"` 启用 ES 模块
+2. `main` 和 `types` 都指向 `src/index.ts`(源代码直接使用)
+3. `exports` 配置支持 tree-shaking
+4. `peerDependencies` 指定 Playwright 版本范围(兼容最新稳定版和上一个 LTS 版本)
+5. 添加测试脚本(单元测试、覆盖率)
+
+### tsconfig.json 配置要求
+
+**参考项目 TypeScript 严格模式配置:**
+
+```json
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "module": "ESNext",
+    "lib": ["ES2020"],
+    "moduleResolution": "bundler",
+    "strict": true,
+    "noImplicitAny": true,
+    "strictNullChecks": true,
+    "strictFunctionTypes": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true,
+    "esModuleInterop": true,
+    "skipLibCheck": true,
+    "forceConsistentCasingInFileNames": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "declaration": true,
+    "declarationMap": true,
+    "sourceMap": true,
+    "outDir": "./dist",
+    "rootDir": "./src",
+    "baseUrl": ".",
+    "paths": {
+      "@d8d/e2e-test-utils": ["./src/index.ts"]
+    }
+  },
+  "include": ["src/**/*"],
+  "exclude": ["node_modules", "dist", "tests"]
+}
+```
+
+**关键点:**
+1. 启用所有严格模式选项(`strict: true` + 额外检查)
+2. 目标 ES2020+(`target: "ES2020"`)
+3. 启用声明文件生成(`declaration: true`)
+4. 配置正确的 `rootDir` 和 `outDir`
+
+### vitest.config.ts 配置要求
+
+```typescript
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+  test: {
+    dir: './tests/unit',
+    environment: 'node',
+    coverage: {
+      provider: 'v8',
+      reporter: ['text', 'json', 'html'],
+      statements: 80,
+      branches: 80,
+      functions: 80,
+      lines: 80,
+      exclude: [
+        'node_modules/',
+        'tests/',
+        '**/*.test.ts',
+        '**/*.spec.ts',
+        'src/index.ts'
+      ]
+    },
+    testTimeout: 10000,
+    globals: false
+  }
+});
+```
+
+**关键点:**
+1. 测试目录指向 `tests/unit`
+2. 覆盖率目标 ≥80%(所有指标)
+3. 测试超时 10 秒
+4. 排除 `src/index.ts` 从覆盖率(主导出文件)
+
+### 源代码文件结构
+
+**`src/index.ts` - 主导出文件(tree-shakeable):**
+
+```typescript
+// 导出类型定义
+export * from './types';
+
+// 导出错误类
+export * from './errors';
+
+// 导出常量
+export * from './constants';
+
+// Radix UI Select 工具(后续故事实现)
+// export * from './radix-select';
+```
+
+**`src/types.ts` - 共享类型定义:**
+
+```typescript
+import type { Page } from '@playwright/test';
+
+/**
+ * 基础配置选项,所有配置对象的基类
+ */
+export interface BaseOptions {
+  /** 超时时间(毫秒)*/
+  timeout?: number;
+}
+
+/**
+ * 错误上下文接口
+ */
+export interface ErrorContext {
+  /** 操作类型(如 'selectRadixOption')*/
+  operation: string;
+  /** 目标(如下拉框标签)*/
+  target: string;
+  /** 期望值 */
+  expected?: string;
+  /** 实际值 */
+  actual?: string;
+  /** 可用选项列表 */
+  available?: string[];
+  /** 修复建议 */
+  suggestion?: string;
+}
+
+// 重新导出 Playwright 类型以便使用者使用
+export type { Page } from '@playwright/test';
+```
+
+**`src/errors.ts` - 错误处理:**
+
+```typescript
+import type { ErrorContext } from './types';
+
+/**
+ * E2E 测试专用错误类
+ * 提供结构化的错误上下文信息
+ */
+export class E2ETestError extends Error {
+  constructor(
+    public readonly context: ErrorContext,
+    message?: string
+  ) {
+    super(message || formatErrorMessage(context));
+    this.name = 'E2ETestError';
+  }
+}
+
+/**
+ * 格式化错误消息
+ */
+function formatErrorMessage(context: ErrorContext): string {
+  const parts = [
+    `❌ ${context.operation} failed`,
+    `Target: ${context.target}`
+  ];
+
+  if (context.expected) {
+    parts.push(`Expected: ${context.expected}`);
+  }
+
+  if (context.actual) {
+    parts.push(`Actual: ${context.actual}`);
+  }
+
+  if (context.available && context.available.length > 0) {
+    parts.push(`Available: ${context.available.join(', ')}`);
+  }
+
+  if (context.suggestion) {
+    parts.push(`\n💡 ${context.suggestion}`);
+  }
+
+  return parts.join('\n');
+}
+```
+
+**`src/constants.ts` - 常量定义:**
+
+```typescript
+/**
+ * 默认超时配置(毫秒)
+ */
+export const DEFAULT_TIMEOUTS = {
+  /** 静态选项超时 */
+  static: 2000,
+  /** 异步选项超时 */
+  async: 5000,
+  /** 网络空闲超时 */
+  networkIdle: 10000
+} as const;
+
+/**
+ * 选择器策略常量
+ */
+export const SELECTOR_STRATEGIES = [
+  'data-testid',
+  'aria-label + role',
+  'text content + role'
+] as const;
+```
+
+### 目录创建命令参考
+
+```bash
+# 在项目根目录执行
+mkdir -p packages/e2e-test-utils/src
+mkdir -p packages/e2e-test-utils/tests/fixtures/images
+mkdir -p packages/e2e-test-utils/tests/fixtures/data
+mkdir -p packages/e2e-test-utils/tests/unit
+mkdir -p packages/e2e-test-utils/tests/integration
+mkdir -p packages/e2e-test-utils/tests/stability
+```
+
+### 验证步骤
+
+**1. 验证目录结构:**
+```bash
+ls -la packages/e2e-test-utils/
+# 应显示:src/, tests/, package.json, tsconfig.json, vitest.config.ts, README.md
+
+ls -la packages/e2e-test-utils/src/
+# 应显示:index.ts, types.ts, errors.ts, constants.ts
+
+ls -la packages/e2e-test-utils/tests/
+# 应显示:fixtures/, unit/, integration/, stability/
+```
+
+**2. 验证 TypeScript 配置:**
+```bash
+cd packages/e2e-test-utils
+pnpm typecheck
+# 应无错误输出
+```
+
+**3. 验证包可以被安装:**
+```bash
+# 在 monorepo 根目录
+pnpm install
+# 检查是否成功注册 workspace 包
+
+# 验证可以被引用(在 web/ 目录)
+pnpm add -D @d8d/e2e-test-utils@workspace:*
+```
+
+**4. 验证 Vitest 配置:**
+```bash
+cd packages/e2e-test-utils
+pnpm test:unit
+# 应显示 Vitest 成功启动(即使没有测试)
+```
+
+### Project Structure Notes
+
+**对齐项目 Monorepo 架构:**
+- 使用 `pnpm workspace` 协议
+- 包命名遵循 `@d8d/` 命名空间
+- 与现有 `@d8d/shared-test-util`(后端集成测试)分离
+- `@d8d/e2e-test-utils` 专门用于 Playwright E2E 测试
+
+**与项目标准对齐:**
+- 遵循 `docs/standards/testing-standards.md` 中的测试规范
+- 遵循 `docs/standards/coding-standards.md` 中的编码标准
+- 遵循 `docs/standards/e2e-radix-testing.md` 中的 Radix UI E2E 测试标准(核心标准文档)
+
+### References
+
+**PRD 来源:**
+- [PRD - E2E测试工具包](_bmad-output/planning-artifacts/prd.md) - 项目需求概述
+- [PRD - 包结构需求](_bmad-output/planning-artifacts/prd.md#包结构需求) - 详细的包结构设计
+
+**Architecture 来源:**
+- [Architecture - 包结构决策](_bmad-output/planning-artifacts/architecture.md#package-structure) - 按功能分组的决策
+- [Architecture - API 设计模式](_bmad-output/planning-artifacts/architecture.md#api-design-pattern) - 3参数+配置对象模式
+- [Architecture - 类型系统策略](_bmad-output/planning-artifacts/architecture.md#type-system-strategy) - 分层类型设计
+- [Architecture - 项目目录结构](_bmad-output/planning-artifacts/architecture.md#complete-project-directory-structure) - 完整目录结构
+
+**标准文档来源:**
+- [E2E Radix UI 测试标准](docs/standards/e2e-radix-testing.md) - 核心测试标准文档
+- [测试规范](docs/standards/testing-standards.md) - 项目测试规范
+- [编码标准](docs/standards/coding-standards.md) - 编码标准
+
+**Epic 来源:**
+- [Epic 1 - Story 1.1](_bmad-output/planning-artifacts/epics.md#story-11-创建包基础结构和配置) - 原始用户故事和验收标准
+
+**参考包:**
+- [@d8d/shared-test-util](packages/shared-test-util/package.json) - 现有的共享测试工具包(后端集成测试)
+
+## Dev Agent Record
+
+### Agent Model Used
+
+Claude (d8d-model) via create-story workflow
+
+### Debug Log References
+
+### Completion Notes List
+
+- 故事创建时间: 2026-01-08
+- 基于 PRD、Architecture、E2E Radix 测试标准文档创建
+- 包含完整的目录结构、配置文件模板、验证步骤
+- 为后续故事提供基础设施
+
+### File List
+
+**创建的文件:**
+- `packages/e2e-test-utils/package.json`
+- `packages/e2e-test-utils/tsconfig.json`
+- `packages/e2e-test-utils/vitest.config.ts`
+- `packages/e2e-test-utils/README.md`
+- `packages/e2e-test-utils/src/index.ts`
+- `packages/e2e-test-utils/src/types.ts`
+- `packages/e2e-test-utils/src/errors.ts`
+- `packages/e2e-test-utils/src/constants.ts`
+
+**创建的目录:**
+- `packages/e2e-test-utils/src/`
+- `packages/e2e-test-utils/tests/fixtures/images/`
+- `packages/e2e-test-utils/tests/fixtures/data/`
+- `packages/e2e-test-utils/tests/unit/`
+- `packages/e2e-test-utils/tests/integration/`
+- `packages/e2e-test-utils/tests/stability/`

+ 2 - 2
_bmad-output/implementation-artifacts/sprint-status.yaml

@@ -41,8 +41,8 @@ story_location: _bmad-output/implementation-artifacts
 
 development_status:
   # Epic 1: 测试工具包基础框架与 Select 支持
-  epic-1: backlog
-  1-1-create-package-structure: backlog
+  epic-1: in-progress
+  1-1-create-package-structure: ready-for-dev
   1-2-implement-types-errors: backlog
   1-3-static-select-tool: backlog
   1-4-async-select-tool: backlog