@lobehub/lobehub 2.0.0-next.277 → 2.0.0-next.278

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/.cursor/rules/db-migrations.mdc +1 -1
  2. package/.cursor/rules/debug-usage.mdc +7 -5
  3. package/.cursor/rules/desktop-controller-tests.mdc +2 -1
  4. package/.cursor/rules/desktop-feature-implementation.mdc +9 -5
  5. package/.cursor/rules/desktop-local-tools-implement.mdc +67 -66
  6. package/.cursor/rules/desktop-menu-configuration.mdc +21 -9
  7. package/.cursor/rules/desktop-window-management.mdc +17 -2
  8. package/.cursor/rules/drizzle-schema-style-guide.mdc +6 -6
  9. package/.cursor/rules/hotkey.mdc +1 -0
  10. package/.cursor/rules/i18n.mdc +1 -0
  11. package/.cursor/rules/project-structure.mdc +16 -3
  12. package/.cursor/rules/react.mdc +17 -5
  13. package/.cursor/rules/recent-data-usage.mdc +2 -1
  14. package/.cursor/rules/testing-guide/testing-guide.mdc +262 -238
  15. package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +1 -1
  16. package/.cursor/rules/zustand-action-patterns.mdc +1 -1
  17. package/.cursor/rules/zustand-slice-organization.mdc +4 -4
  18. package/CHANGELOG.md +25 -0
  19. package/CLAUDE.md +1 -1
  20. package/GEMINI.md +1 -1
  21. package/changelog/v1.json +5 -0
  22. package/docs/development/database-schema.dbml +16 -0
  23. package/locales/en-US/chat.json +24 -0
  24. package/locales/zh-CN/chat.json +24 -0
  25. package/package.json +1 -1
  26. package/packages/business/const/src/index.ts +3 -0
  27. package/packages/database/migrations/0069_add_topic_shares_table.sql +22 -0
  28. package/packages/database/migrations/meta/0069_snapshot.json +9704 -0
  29. package/packages/database/migrations/meta/_journal.json +7 -0
  30. package/packages/database/src/models/__tests__/topicShare.test.ts +318 -0
  31. package/packages/database/src/models/topicShare.ts +177 -0
  32. package/packages/database/src/schemas/topic.ts +44 -2
  33. package/packages/types/src/conversation.ts +5 -0
  34. package/packages/types/src/topic/topic.ts +46 -0
  35. package/src/app/[variants]/(main)/agent/features/Conversation/Header/ShareButton/index.tsx +24 -9
  36. package/src/app/[variants]/(main)/group/features/Conversation/Header/ShareButton/index.tsx +26 -9
  37. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +1 -2
  38. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ImageNum.tsx +54 -173
  39. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ResolutionSelect.tsx +22 -67
  40. package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +18 -0
  41. package/src/app/[variants]/router/desktopRouter.config.tsx +18 -0
  42. package/src/app/[variants]/share/t/[id]/SharedMessageList.tsx +54 -0
  43. package/src/app/[variants]/share/t/[id]/_layout/index.tsx +170 -0
  44. package/src/app/[variants]/share/t/[id]/features/Portal/index.tsx +66 -0
  45. package/src/app/[variants]/share/t/[id]/index.tsx +112 -0
  46. package/src/app/robots.tsx +1 -1
  47. package/src/business/client/BusinessMobileRoutes.tsx +1 -1
  48. package/src/features/Conversation/ChatList/index.tsx +12 -5
  49. package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/index.tsx +8 -4
  50. package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +15 -10
  51. package/src/features/Conversation/Messages/AssistantGroup/Tools.tsx +3 -1
  52. package/src/features/Conversation/Messages/AssistantGroup/components/ContentBlock.tsx +3 -2
  53. package/src/features/Conversation/Messages/AssistantGroup/components/GroupItem.tsx +2 -2
  54. package/src/features/Conversation/Messages/Supervisor/components/ContentBlock.tsx +25 -26
  55. package/src/features/Conversation/Messages/Supervisor/components/Group.tsx +4 -2
  56. package/src/features/Conversation/Messages/Tool/Tool/index.tsx +16 -12
  57. package/src/features/Conversation/Messages/Tool/index.tsx +20 -11
  58. package/src/features/Conversation/Messages/index.tsx +1 -1
  59. package/src/features/Conversation/store/slices/data/action.ts +2 -1
  60. package/src/features/SharePopover/index.tsx +215 -0
  61. package/src/features/SharePopover/style.ts +10 -0
  62. package/src/libs/next/proxy/define-config.ts +4 -1
  63. package/src/locales/default/chat.ts +26 -0
  64. package/src/proxy.ts +1 -0
  65. package/src/server/routers/lambda/__tests__/message.test.ts +152 -0
  66. package/src/server/routers/lambda/__tests__/share.test.ts +227 -0
  67. package/src/server/routers/lambda/__tests__/topic.test.ts +174 -0
  68. package/src/server/routers/lambda/index.ts +2 -0
  69. package/src/server/routers/lambda/message.ts +37 -4
  70. package/src/server/routers/lambda/share.ts +55 -0
  71. package/src/server/routers/lambda/topic.ts +45 -0
  72. package/src/services/message/index.ts +1 -0
  73. package/src/services/topic/index.ts +16 -0
@@ -3,173 +3,199 @@ globs: *.test.ts,*.test.tsx
3
3
  alwaysApply: false
4
4
  ---
5
5
 
6
- # 测试指南 - LobeChat Testing Guide
6
+ # LobeChat Testing Guide
7
7
 
8
- ## 测试环境概览
8
+ ## Test Overview
9
9
 
10
- LobeChat 项目使用 Vitest 测试库,配置了两种不同的测试环境:
10
+ LobeChat testing consists of **E2E tests** and **Unit tests**. This guide focuses on **Unit tests**.
11
11
 
12
- ### 客户端数据库测试环境 (DOM Environment)
12
+ Unit tests are organized into three main categories:
13
13
 
14
- - **配置文件**: [vitest.config.ts](mdc:vitest.config.ts)
15
- - **环境**: Happy DOM (浏览器环境模拟)
16
- - **数据库**: PGLite (浏览器环境的 PostgreSQL)
17
- - **用途**: 测试前端组件、客户端逻辑、React 组件等
18
- - **设置文件**: [tests/setup.ts](mdc:tests/setup.ts)
14
+ ```plaintext
15
+ +---------------------+---------------------------+-----------------------------+
16
+ | Category | Location | Config File |
17
+ +---------------------+---------------------------+-----------------------------+
18
+ | Next.js Webapp | src/**/*.test.ts(x) | vitest.config.ts |
19
+ | Packages | packages/*/**/*.test.ts | packages/*/vitest.config.ts |
20
+ | Desktop App | apps/desktop/**/*.test.ts | apps/desktop/vitest.config.ts |
21
+ +---------------------+---------------------------+-----------------------------+
22
+ ```
23
+
24
+ ### Next.js Webapp Tests
25
+
26
+ - **Config File**: `vitest.config.ts`
27
+ - **Environment**: Happy DOM (browser environment simulation)
28
+ - **Database**: PGLite (PostgreSQL for browser environments)
29
+ - **Setup File**: `tests/setup.ts`
30
+ - **Purpose**: Testing React components, hooks, stores, utilities, and client-side logic
31
+
32
+ ### Packages Tests
33
+
34
+ Most packages use standard Vitest configuration. However, the `database` package is special:
19
35
 
20
- ### 服务端数据库测试环境 (Node Environment)
36
+ #### Database Package (Special Case)
21
37
 
22
- 目前只有 `packages/database` 下的测试可以通过配置 `TEST_SERVER_DB=1` 环境变量来使用服务端数据库测试
38
+ The database package supports **dual-environment testing**:
23
39
 
24
- - **配置文件**: [packages/database/vitest.config.mts](mdc:packages/database/vitest.config.mts) 并且设置环境变量 `TEST_SERVER_DB=1`
25
- - **环境**: Node.js
26
- - **数据库**: 真实的 PostgreSQL 数据库
27
- - **并发限制**: 单线程运行 (`singleFork: true`)
28
- - **用途**: 测试数据库模型、服务端逻辑、API 端点等
29
- - **设置文件**: [packages/database/tests/setup-db.ts](mdc:packages/database/tests/setup-db.ts)
40
+ | Environment | Database | Config | Use Case |
41
+ |------------------|-----------------|---------------------------------------|-----------------------------------|
42
+ | Client (Default) | PGLite | `packages/database/vitest.config.mts` | Fast local development |
43
+ | Server | Real PostgreSQL | Set `TEST_SERVER_DB=1` | CI/CD, compatibility verification |
30
44
 
31
- ## 测试运行命令
45
+ Server environment details:
32
46
 
33
- ** 性能警告**: 项目包含 3000+ 测试用例,完整运行需要约 10 分钟。务必使用文件过滤或测试名称过滤。
47
+ - **Concurrency**: Single-threaded (`singleFork: true`)
48
+ - **Setup File**: `packages/database/tests/setup-db.ts`
49
+ - **Requirement**: `DATABASE_TEST_URL` environment variable must be set
34
50
 
35
- ### 正确的命令格式
51
+ ### Desktop App Tests
52
+
53
+ - **Config File**: `apps/desktop/vitest.config.ts`
54
+ - **Environment**: Node.js
55
+ - **Purpose**: Testing Electron main process controllers, IPC handlers, and desktop-specific logic
56
+
57
+ ## Test Commands
58
+
59
+ **Performance Warning**: The project contains 3000+ test cases. A full run takes approximately 10 minutes. Always use file filtering or test name filtering.
60
+
61
+ ### Recommended Command Format
36
62
 
37
63
  ```bash
38
- # 运行所有客户端/服务端测试
39
- bunx vitest run --silent='passed-only' # 客户端测试
40
- cd packages/database && TEST_SERVER_DB=1 bunx vitest run --silent='passed-only' # 服务端测试
64
+ # Run all client/server tests
65
+ bunx vitest run --silent='passed-only' # Client tests
66
+ cd packages/database && TEST_SERVER_DB=1 bunx vitest run --silent='passed-only' # Server tests
41
67
 
42
- # 运行特定测试文件 (支持模糊匹配)
68
+ # Run specific test file (supports fuzzy matching)
43
69
  bunx vitest run --silent='passed-only' user.test.ts
44
70
 
45
- # 运行特定测试用例名称 (使用 -t 参数)
71
+ # Run specific test case by name (using -t flag)
46
72
  bunx vitest run --silent='passed-only' -t "test case name"
47
73
 
48
- # 组合使用文件和测试名称过滤
74
+ # Combine file and test name filtering
49
75
  bunx vitest run --silent='passed-only' filename.test.ts -t "specific test"
50
76
 
51
- # 生成覆盖率报告 (使用 --coverage 参数)
77
+ # Generate coverage report (using --coverage flag)
52
78
  bunx vitest run --silent='passed-only' --coverage
53
79
  ```
54
80
 
55
- ### 避免的命令格式
81
+ ### Commands to Avoid
56
82
 
57
83
  ```bash
58
- # 这些命令会运行所有 3000+ 测试用例,耗时约 10 分钟!
84
+ # ❌ These commands run all 3000+ test cases, taking ~10 minutes!
59
85
  npm test
60
86
  npm test some-file.test.ts
61
87
 
62
- # 不要使用裸 vitest (会进入 watch 模式)
88
+ # ❌ Don't use bare vitest (enters watch mode)
63
89
  vitest test-file.test.ts
64
90
  ```
65
91
 
66
- ## 测试修复原则
92
+ ## Test Fixing Principles
67
93
 
68
- ### 核心原则
94
+ ### Core Principles
69
95
 
70
- 1. **收集足够的上下文**
71
- 在修复测试之前,务必做到:
72
- - 完整理解测试的意图和实现
73
- - 强烈建议阅读当前的 git diff PR diff
96
+ 1. **Gather Sufficient Context**
97
+ Before fixing tests, ensure you:
98
+ - Fully understand the test's intent and implementation
99
+ - Strongly recommended: review the current git diff and PR diff
74
100
 
75
- 2. **测试优先修复**
76
- 如果是测试本身写错了,应优先修改测试,而不是实现代码。
101
+ 2. **Prioritize Test Fixes**
102
+ If the test itself is incorrect, fix the test first rather than the implementation code.
77
103
 
78
- 3. **专注单一问题**
79
- 只修复指定的测试,不要顺带添加额外测试。
104
+ 3. **Focus on a Single Issue**
105
+ Only fix the specified test; don't add extra tests along the way.
80
106
 
81
- 4. **不自作主张**
82
- 发现其他问题时,不要直接修改,需先提出并讨论。
107
+ 4. **Don't Act Unilaterally**
108
+ When discovering other issues, don't modify them directly—raise and discuss first.
83
109
 
84
- ### 测试协作最佳实践
110
+ ### Testing Collaboration Best Practices
85
111
 
86
- 基于实际开发经验总结的重要协作原则:
112
+ Important collaboration principles based on real development experience:
87
113
 
88
- #### 1. 失败处理策略
114
+ #### 1. Failure Handling Strategy
89
115
 
90
- **核心原则**: 避免盲目重试,快速识别问题并寻求帮助。
116
+ **Core Principle**: Avoid blind retries; quickly identify problems and seek help.
91
117
 
92
- - **失败阈值**: 当连续尝试修复测试 1-2 次都失败后,应立即停止继续尝试
93
- - **问题总结**: 分析失败原因,整理已尝试的解决方案及其失败原因
94
- - **寻求帮助**: 带着清晰的问题摘要和尝试记录向团队寻求帮助
95
- - **避免陷阱**: 不要陷入"不断尝试相同或类似方法"的循环
118
+ - **Failure Threshold**: After 1-2 consecutive failed fix attempts, stop immediately
119
+ - **Problem Summary**: Analyze failure reasons and document attempted solutions with their failure causes
120
+ - **Seek Help**: Approach the team with a clear problem summary and attempt history
121
+ - **Avoid the Trap**: Don't fall into the loop of repeatedly trying the same or similar approaches
96
122
 
97
123
  ```typescript
98
- // 错误做法:连续失败后继续盲目尝试
99
- // 第3次、第4次仍在用相似的方法修复同一个问题
124
+ // ❌ Wrong approach: Keep blindly trying after consecutive failures
125
+ // 3rd, 4th attempts still using similar methods to fix the same problem
100
126
 
101
- // 正确做法:失败1-2次后总结问题
127
+ // ✅ Correct approach: Summarize after 1-2 failures
102
128
  /*
103
- 问题总结:
104
- 1. 尝试过的方法:修改 mock 数据结构
105
- 2. 失败原因:仍然提示类型不匹配
106
- 3. 具体错误:Expected 'UserData' but received 'UserProfile'
107
- 4. 需要帮助:不确定最新的 UserData 接口定义
129
+ Problem Summary:
130
+ 1. Attempted method: Modified mock data structure
131
+ 2. Failure reason: Still getting type mismatch error
132
+ 3. Specific error: Expected 'UserData' but received 'UserProfile'
133
+ 4. Help needed: Unsure about the latest UserData interface definition
108
134
  */
109
135
  ```
110
136
 
111
- #### 2. 测试用例命名规范
137
+ #### 2. Test Case Naming Conventions
112
138
 
113
- **核心原则**: 测试应该关注"行为",而不是"实现细节"
139
+ **Core Principle**: Tests should focus on "behavior," not "implementation details."
114
140
 
115
- - **描述业务场景**: `describe` `it` 的标题应该描述具体的业务场景和预期行为
116
- - **避免实现绑定**: 不要在测试名称中提及具体的代码行号、覆盖率目标或实现细节
117
- - **保持稳定性**: 测试名称应该在代码重构后仍然有意义
141
+ - **Describe Business Scenarios**: `describe` and `it` titles should describe specific business scenarios and expected behaviors
142
+ - **Avoid Implementation Binding**: Don't mention specific line numbers, coverage goals, or implementation details in test names
143
+ - **Maintain Stability**: Test names should remain meaningful after code refactoring
118
144
 
119
145
  ```typescript
120
- // 错误的测试命名
146
+ // ❌ Poor test naming
121
147
  describe('User component coverage', () => {
122
148
  it('covers line 45-50 in getUserData', () => {
123
- // 为了覆盖第45-50行而写的测试
149
+ // Test written just to cover lines 45-50
124
150
  });
125
151
 
126
152
  it('tests the else branch', () => {
127
- // 仅为了测试某个分支而存在
153
+ // Exists only to test a specific branch
128
154
  });
129
155
  });
130
156
 
131
- // 正确的测试命名
157
+ // ✅ Good test naming
132
158
  describe('<UserAvatar />', () => {
133
159
  it('should render fallback icon when image url is not provided', () => {
134
- // 测试具体的业务场景,自然会覆盖相关代码分支
160
+ // Tests a specific business scenario, naturally covering relevant code branches
135
161
  });
136
162
 
137
163
  it('should display user initials when avatar image fails to load', () => {
138
- // 描述用户行为和预期结果
164
+ // Describes user behavior and expected outcome
139
165
  });
140
166
  });
141
167
  ```
142
168
 
143
- **覆盖率提升的正确思路**:
169
+ **The Right Approach to Improving Coverage**:
144
170
 
145
- - 通过设计各种业务场景(正常流程、边缘情况、错误处理)来自然提升覆盖率
146
- - 不要为了达到覆盖率数字而写测试,更不要在测试中注释"为了覆盖 xxx 行"
171
+ - Naturally improve coverage by designing various business scenarios (happy paths, edge cases, error handling)
172
+ - Don't write tests just to hit coverage numbers, and never comment "to cover line xxx" in tests
147
173
 
148
- #### 3. 测试组织结构
174
+ #### 3. Test Organization Structure
149
175
 
150
- **核心原则**: 维护清晰的测试层次结构,避免冗余的顶级测试块。
176
+ **Core Principle**: Maintain a clear test hierarchy; avoid redundant top-level test blocks.
151
177
 
152
- - **复用现有结构**: 添加新测试时,优先在现有的 `describe` 块中寻找合适的位置
153
- - **逻辑分组**: 相关的测试用例应该组织在同一个 `describe` 块内
154
- - **避免碎片化**: 不要为了单个测试用例就创建新的顶级 `describe`
178
+ - **Reuse Existing Structure**: When adding new tests, first look for an appropriate place in existing `describe` blocks
179
+ - **Logical Grouping**: Related test cases should be organized within the same `describe` block
180
+ - **Avoid Fragmentation**: Don't create a new top-level `describe` block for a single test case
155
181
 
156
182
  ```typescript
157
- // 错误的组织方式:创建过多顶级块
183
+ // ❌ Poor organization: Too many top-level blocks
158
184
  describe('<UserProfile />', () => {
159
185
  it('should render user name', () => {});
160
186
  });
161
187
 
162
188
  describe('UserProfile new prop test', () => {
163
- // 不必要的新块
189
+ // Unnecessary new block
164
190
  it('should handle email display', () => {});
165
191
  });
166
192
 
167
193
  describe('UserProfile edge cases', () => {
168
- // 不必要的新块
194
+ // Unnecessary new block
169
195
  it('should handle missing avatar', () => {});
170
196
  });
171
197
 
172
- // 正确的组织方式:合并相关测试
198
+ // ✅ Good organization: Merge related tests
173
199
  describe('<UserProfile />', () => {
174
200
  it('should render user name', () => {});
175
201
 
@@ -178,78 +204,78 @@ describe('<UserProfile />', () => {
178
204
  it('should handle missing avatar', () => {});
179
205
 
180
206
  describe('when user data is incomplete', () => {
181
- // 只有在有多个相关子场景时才创建子组
207
+ // Only create sub-groups when there are multiple related sub-scenarios
182
208
  it('should show placeholder for missing name', () => {});
183
209
  it('should hide email section when email is undefined', () => {});
184
210
  });
185
211
  });
186
212
  ```
187
213
 
188
- **组织决策流程**:
214
+ **Organization Decision Flow**:
189
215
 
190
- 1. 是否存在逻辑相关的现有 `describe` 块?如果有,添加到其中
191
- 2. 是否有多个(3个以上)相关的测试用例?如果有,可以考虑创建新的子 `describe`
192
- 3. 是否是独立的、无关联的功能模块?如果是,才考虑创建新的顶级 `describe`
216
+ 1. Is there a logically related existing `describe` block?If yes, add to it
217
+ 2. Are there multiple (3+) related test cases? If yes, consider creating a new sub-`describe`
218
+ 3. Is it an independent, unrelated feature module? Only then consider creating a new top-level `describe`
193
219
 
194
- ### 测试修复流程
220
+ ### Test Fixing Workflow
195
221
 
196
- 1. **复现问题**: 定位并运行失败的测试,确认能在本地复现
197
- 2. **分析原因**: 阅读测试代码、错误日志和相关文件的 Git 修改历史
198
- 3. **建立假设**: 判断问题出在测试逻辑、实现代码还是环境配置
199
- 4. **修复验证**: 根据假设进行修复,重新运行测试确认通过
200
- 5. **扩大验证**: 运行当前文件内所有测试,确保没有引入新问题
201
- 6. **撰写总结**: 说明错误原因和修复方法
222
+ 1. **Reproduce the Issue**: Locate and run the failing test; confirm it can be reproduced locally
223
+ 2. **Analyze the Cause**: Read test code, error logs, and Git history of related files
224
+ 3. **Form a Hypothesis**: Determine if the problem is in test logic, implementation code, or environment configuration
225
+ 4. **Fix and Verify**: Apply the fix based on your hypothesis; rerun the test to confirm it passes
226
+ 5. **Expand Verification**: Run all tests in the current file to ensure no new issues were introduced
227
+ 6. **Write a Summary**: Document the error cause and fix method
202
228
 
203
- ### 修复完成后的总结
229
+ ### Post-Fix Summary
204
230
 
205
- 测试修复完成后,应该提供简要说明,包括:
231
+ After completing a test fix, provide a brief explanation including:
206
232
 
207
- 1. **错误原因分析**: 说明测试失败的根本原因
208
- - 测试逻辑错误
209
- - 实现代码bug
210
- - 环境配置问题
211
- - 依赖变更导致的问题
233
+ 1. **Root Cause Analysis**: Explain the fundamental reason for the test failure
234
+ - Test logic error
235
+ - Implementation bug
236
+ - Environment configuration issue
237
+ - Dependency change
212
238
 
213
- 2. **修复方法说明**: 简述采用的修复方式
214
- - 修改了哪些文件
215
- - 采用了什么解决方案
216
- - 为什么选择这种修复方式
239
+ 2. **Fix Description**: Briefly describe the fix approach
240
+ - Which files were modified
241
+ - What solution was applied
242
+ - Why this fix approach was chosen
217
243
 
218
- **示例格式**:
244
+ **Example Format**:
219
245
 
220
246
  ```markdown
221
- ## 测试修复总结
247
+ ## Test Fix Summary
222
248
 
223
- **错误原因**: 测试中的 mock 数据格式与实际 API 返回格式不匹配,导致断言失败。
249
+ **Root Cause**: The mock data format in the test didn't match the actual API response format, causing assertion failures.
224
250
 
225
- **修复方法**: 更新了测试文件中的 mock 数据结构,使其与最新的 API 响应格式保持一致。具体修改了 `user.test.ts` 中的 `mockUserData` 对象结构。
251
+ **Fix**: Updated the mock data structure in the test file to match the latest API response format. Specifically modified the `mockUserData` object structure in `user.test.ts`.
226
252
  ```
227
253
 
228
- ## 测试编写最佳实践
254
+ ## Test Writing Best Practices
229
255
 
230
- ### Mock 数据策略:追求"低成本的真实性"
256
+ ### Mock Data Strategy: Aim for "Low-Cost Authenticity"
231
257
 
232
- **核心原则**: 测试数据应默认追求真实性,只有在引入"高昂的测试成本"时才进行简化。
258
+ **Core Principle**: Test data should default to authenticity; only simplify when it introduces "high testing costs."
233
259
 
234
- #### 什么是"高昂的测试成本"
260
+ #### What Are "High Testing Costs"?
235
261
 
236
- "高成本"指的是测试中引入了外部依赖,使测试变慢、不稳定或复杂:
262
+ "High cost" refers to introducing external dependencies in tests that make them slow, unstable, or complex:
237
263
 
238
- - **文件 I/O 操作**:读写硬盘文件
239
- - **网络请求**:HTTP 调用、数据库连接
240
- - **系统调用**:获取系统时间、环境变量等
264
+ - **File I/O Operations**: Reading/writing disk files
265
+ - **Network Requests**: HTTP calls, database connections
266
+ - **System Calls**: Getting system time, environment variables, etc.
241
267
 
242
- #### 推荐做法:Mock 依赖,保留真实数据
268
+ #### Recommended Approach: Mock Dependencies, Keep Real Data
243
269
 
244
270
  ```typescript
245
- // 好的做法:Mock I/O 操作,但使用真实的文件内容格式
271
+ // ✅ Good approach: Mock I/O operations but use real file content formats
246
272
  describe('parseContentType', () => {
247
273
  beforeEach(() => {
248
- // Mock 文件读取操作(避免真实 I/O
274
+ // Mock file read operation (avoid real I/O)
249
275
  vi.spyOn(fs, 'readFileSync').mockImplementation((path) => {
250
- // 但返回真实的文件内容格式
251
- if (path.includes('.pdf')) return '%PDF-1.4\n%âãÏÓ'; // 真实 PDF 文件头
252
- if (path.includes('.png')) return '\x89PNG\r\n\x1a\n'; // 真实 PNG 文件头
276
+ // But return real file content formats
277
+ if (path.includes('.pdf')) return '%PDF-1.4\n%âãÏÓ'; // Real PDF header
278
+ if (path.includes('.png')) return '\x89PNG\r\n\x1a\n'; // Real PNG header
253
279
  return '';
254
280
  });
255
281
  });
@@ -260,40 +286,38 @@ describe('parseContentType', () => {
260
286
  });
261
287
  });
262
288
 
263
- // 过度简化:使用不真实的数据
289
+ // ❌ Over-simplified: Using unrealistic data
264
290
  describe('parseContentType', () => {
265
291
  it('should detect PDF content type correctly', () => {
266
- // 这种简化数据没有测试价值
292
+ // This simplified data has no test value
267
293
  const result = parseContentType('fake-pdf-content');
268
294
  expect(result).toBe('application/pdf');
269
295
  });
270
296
  });
271
297
  ```
272
298
 
273
- #### 真实标识符的价值
299
+ #### The Value of Real Identifiers
274
300
 
275
301
  ```typescript
276
- // ✅ 使用真实标识符
302
+ // ✅ Use real identifiers
277
303
  const result = parseModelString('openai', '+gpt-4,+gpt-3.5-turbo');
278
304
 
279
- // ❌ 使用占位符(价值较低)
305
+ // ❌ Use placeholders (lower value)
280
306
  const result = parseModelString('test-provider', '+model1,+model2');
281
307
  ```
282
308
 
283
- ### 现代化Mock技巧:环境设置与Mock方法
284
-
285
- **环境设置 + Mock方法结合使用**
309
+ ### Modern Mocking Techniques: Environment Setup and Mock Methods
286
310
 
287
- 客户端代码测试时,推荐使用环境注释配合现代化Mock方法:
311
+ When testing client-side code, use environment annotations with modern mock methods:
288
312
 
289
313
  ```typescript
290
314
  /**
291
- * @vitest-environment happy-dom // 提供浏览器API
315
+ * @vitest-environment happy-dom // Provides browser APIs
292
316
  */
293
317
  import { beforeEach, vi } from 'vitest';
294
318
 
295
319
  beforeEach(() => {
296
- // 现代方法1:使用vi.stubGlobal替代global.xxx = ...
320
+ // Modern method 1: Use vi.stubGlobal instead of global.xxx = ...
297
321
  const mockImage = vi.fn().mockImplementation(() => ({
298
322
  addEventListener: vi.fn(),
299
323
  naturalHeight: 600,
@@ -301,72 +325,72 @@ beforeEach(() => {
301
325
  }));
302
326
  vi.stubGlobal('Image', mockImage);
303
327
 
304
- // 现代方法2:使用vi.spyOn保留原功能,只mock特定方法
328
+ // Modern method 2: Use vi.spyOn to preserve original functionality, only mock specific methods
305
329
  vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock-url');
306
330
  vi.spyOn(URL, 'revokeObjectURL').mockImplementation(() => {});
307
331
  });
308
332
  ```
309
333
 
310
- **环境选择优先级**
334
+ #### Environment Selection Priority
311
335
 
312
- 1. **@vitest-environment happy-dom** (推荐) - 轻量、快速,项目已安装
313
- 2. **@vitest-environment jsdom** - 功能完整,但需要额外安装jsdom
314
- 3. **不设置环境** - Node.js环境,需要手动mock所有浏览器API
336
+ 1. **@vitest-environment happy-dom** (Recommended) - Lightweight, fast, already installed in the project
337
+ 2. **@vitest-environment jsdom** - Full-featured, but requires additional jsdom package installation
338
+ 3. **No environment set** - Node.js environment, requires manually mocking all browser APIs
315
339
 
316
- **Mock方法对比**
340
+ #### Mock Method Comparison
317
341
 
318
342
  ```typescript
319
- // ❌ 旧方法:直接操作global对象(类型问题)
343
+ // ❌ Old method: Directly manipulating global object (type issues)
320
344
  global.Image = mockImage;
321
345
  global.URL = { ...global.URL, createObjectURL: mockFn };
322
346
 
323
- // ✅ 现代方法:类型安全的vi API
324
- vi.stubGlobal('Image', mockImage); // 完全替换全局对象
325
- vi.spyOn(URL, 'createObjectURL'); // 部分mock,保留其他功能
347
+ // ✅ Modern method: Type-safe vi API
348
+ vi.stubGlobal('Image', mockImage); // Completely replace global object
349
+ vi.spyOn(URL, 'createObjectURL'); // Partial mock, preserve other functionality
326
350
  ```
327
351
 
328
- ### 测试覆盖率原则:代码分支优于用例数量
352
+ ### Test Coverage Principles: Code Branches Over Test Quantity
329
353
 
330
- **核心原则**: 优先覆盖所有代码分支,而非编写大量重复用例
354
+ **Core Principle**: Prioritize covering all code branches rather than writing many repetitive test cases.
331
355
 
332
356
  ```typescript
333
- // ❌ 过度测试:29个测试用例都验证相同分支
357
+ // ❌ Over-testing: 29 test cases all validating the same branch
334
358
  describe('getImageDimensions', () => {
335
359
  it('should reject .txt files');
336
360
  it('should reject .pdf files');
337
- // ... 25个类似测试,都走相同的验证分支
361
+ // ... 25 similar tests, all hitting the same validation branch
338
362
  });
339
363
 
340
- // ✅ 精简测试:4个核心用例覆盖所有分支
364
+ // ✅ Lean testing: 4 core cases covering all branches
341
365
  describe('getImageDimensions', () => {
342
- it('should return dimensions for valid File object'); // 成功路径 - File
343
- it('should return dimensions for valid data URI'); // 成功路径 - String
344
- it('should return undefined for invalid inputs'); // 输入验证分支
345
- it('should return undefined when image fails to load'); // 错误处理分支
366
+ it('should return dimensions for valid File object'); // Success path - File
367
+ it('should return dimensions for valid data URI'); // Success path - String
368
+ it('should return undefined for invalid inputs'); // Input validation branch
369
+ it('should return undefined when image fails to load'); // Error handling branch
346
370
  });
347
371
  ```
348
372
 
349
- **分支覆盖策略**
373
+ #### Branch Coverage Strategy
350
374
 
351
- 1. **成功路径** - 每种输入类型1个测试即可
352
- 2. **边界条件** - 合并类似场景到单个测试
353
- 3. **错误处理** - 测试代表性错误即可
354
- 4. **业务逻辑** - 覆盖所有if/else分支
375
+ 1. **Success Paths** - One test per input type is sufficient
376
+ 2. **Boundary Conditions** - Consolidate similar scenarios into a single test
377
+ 3. **Error Handling** - Test representative errors only
378
+ 4. **Business Logic** - Cover all if/else branches
355
379
 
356
- **合理测试数量**
380
+ #### Reasonable Test Counts
357
381
 
358
- - 简单工具函数:2-5个测试
359
- - 复杂业务逻辑:5-10个测试
360
- - 核心安全功能:适当增加,但避免重复路径
382
+ - Simple utility functions: 2-5 tests
383
+ - Complex business logic: 5-10 tests
384
+ - Core security features: Add more as needed, but avoid duplicate paths
361
385
 
362
- ### 错误处理测试:测试"行为"而非"文本"
386
+ ### Error Handling Tests: Test "Behavior" Not "Text"
363
387
 
364
- **核心原则**: 测试应该验证程序在错误发生时的行为是可预测的,而不是验证易变的错误信息文本。
388
+ **Core Principle**: Tests should verify that program behavior is predictable when errors occur, not verify error message text that may change.
365
389
 
366
- #### 推荐的错误测试方式
390
+ #### Recommended Error Testing Approach
367
391
 
368
392
  ```typescript
369
- // ✅ 测试错误类型和属性
393
+ // ✅ Test error types and properties
370
394
  expect(() => validateUser({})).toThrow(ValidationError);
371
395
  expect(() => processPayment({})).toThrow(
372
396
  expect.objectContaining({
@@ -375,136 +399,136 @@ expect(() => processPayment({})).toThrow(
375
399
  }),
376
400
  );
377
401
 
378
- // ❌ 避免测试具体错误文本
379
- expect(() => processUser({})).toThrow('用户数据不能为空,请检查输入参数');
402
+ // ❌ Avoid testing specific error text
403
+ expect(() => processUser({})).toThrow('User data cannot be empty, please check input parameters');
380
404
  ```
381
405
 
382
- ### 疑难解答:警惕模块污染
406
+ ### Troubleshooting: Beware of Module Pollution
383
407
 
384
- **识别信号**: 当你的测试出现以下"灵异"现象时,优先怀疑模块污染:
408
+ **Warning Signs**: When your tests exhibit these "mysterious" behaviors, suspect module pollution first:
385
409
 
386
- - 单独运行某个测试通过,但和其他测试一起运行就失败
387
- - 测试的执行顺序影响结果
388
- - Mock 设置看起来正确,但实际使用的是旧的 Mock 版本
410
+ - A test passes when run alone but fails when run with other tests
411
+ - Test execution order affects results
412
+ - Mock setup appears correct but actually uses an old mock version
389
413
 
390
- #### 典型场景:动态 Mock 同一模块
414
+ #### Typical Scenario: Dynamic Mocking of the Same Module
391
415
 
392
416
  ```typescript
393
- // ❌ 问题:动态Mock同一模块
417
+ // ❌ Problem: Dynamic mocking of the same module
394
418
  it('dev mode', async () => {
395
419
  vi.doMock('./config', () => ({ isDev: true }));
396
- const { getSettings } = await import('./service'); // 可能使用缓存
420
+ const { getSettings } = await import('./service'); // May use cache
397
421
  });
398
422
 
399
- // ✅ 解决:清除模块缓存
423
+ // ✅ Solution: Clear module cache
400
424
  beforeEach(() => {
401
- vi.resetModules(); // 确保每个测试都是干净环境
425
+ vi.resetModules(); // Ensure each test has a clean environment
402
426
  });
403
427
  ```
404
428
 
405
- **记住**: `vi.resetModules()` 是解决测试"灵异"失败的终极武器。
429
+ **Remember**: `vi.resetModules()` is the ultimate weapon for resolving "mysterious" test failures.
406
430
 
407
- ## 测试文件组织
431
+ ## Test File Organization
408
432
 
409
- ### 文件命名约定
433
+ ### File Naming Convention
410
434
 
411
- `*.test.ts`, `*.test.tsx` (任意位置)
435
+ `*.test.ts`, `*.test.tsx` (any location)
412
436
 
413
- ### 测试文件组织风格
437
+ ### Test File Organization Style
414
438
 
415
- 项目采用 **测试文件与源文件同目录** 的组织风格:
439
+ The project uses a **co-located test files** organization style:
416
440
 
417
- - 测试文件放在对应源文件的同一目录下
418
- - 命名格式:`原文件名.test.ts` `原文件名.test.tsx`
441
+ - Test files are placed in the same directory as the corresponding source files
442
+ - Naming format: `originalFileName.test.ts` or `originalFileName.test.tsx`
419
443
 
420
- 例如:
444
+ Example:
421
445
 
422
446
  ```plaintext
423
447
  src/components/Button/
424
- ├── index.tsx # 源文件
425
- └── index.test.tsx # 测试文件
448
+ ├── index.tsx # Source file
449
+ └── index.test.tsx # Test file
426
450
  ```
427
451
 
428
- - 也有少数情况会统一放到 `__tests__` 文件夹, 例如 `packages/database/src/models/__tests__`
429
- - 测试使用的辅助文件放到 fixtures 文件夹
452
+ - In some cases, tests are consolidated in a `__tests__` folder, e.g., `packages/database/src/models/__tests__`
453
+ - Test helper files are placed in a fixtures folder
430
454
 
431
- ## 测试调试技巧
455
+ ## Test Debugging Tips
432
456
 
433
- ### 测试调试步骤
457
+ ### Test Debugging Steps
434
458
 
435
- 1. **确定测试环境**: 根据文件路径选择正确的配置文件
436
- 2. **隔离问题**: 使用 `-t` 参数只运行失败的测试用例
437
- 3. **分析错误**: 仔细阅读错误信息、堆栈跟踪和最近的文件修改记录
438
- 4. **添加调试**: 在测试中添加 `console.log` 了解执行流程
459
+ 1. **Determine Test Environment**: Select the correct config file based on file path
460
+ 2. **Isolate the Problem**: Use the `-t` flag to run only the failing test case
461
+ 3. **Analyze the Error**: Carefully read error messages, stack traces, and recent file modification history
462
+ 4. **Add Debugging**: Add `console.log` statements in tests to understand execution flow
439
463
 
440
- ### TypeScript 类型处理
464
+ ### TypeScript Type Handling
441
465
 
442
- 在测试中,为了提高编写效率和可读性,可以适当放宽 TypeScript 类型检测:
466
+ In tests, you can relax TypeScript type checking to improve writing efficiency and readability:
443
467
 
444
- #### 推荐的类型放宽策略
468
+ #### Recommended Type Relaxation Strategies
445
469
 
446
470
  ```typescript
447
- // 使用非空断言访问测试中确定存在的属性
471
+ // Use non-null assertion to access properties you're certain exist in tests
448
472
  const result = await someFunction();
449
473
  expect(result!.data).toBeDefined();
450
474
  expect(result!.status).toBe('success');
451
475
 
452
- // 使用 any 类型简化复杂的 Mock 设置
476
+ // Use any type to simplify complex mock setups
453
477
  const mockStream = new ReadableStream() as any;
454
478
  mockStream.toReadableStream = () => mockStream;
455
479
 
456
- // 访问私有成员
457
- await instance['getFromCache']('key'); // 推荐中括号
458
- await (instance as any).getFromCache('key'); // 避免as any
480
+ // Access private members
481
+ await instance['getFromCache']('key'); // Bracket notation recommended
482
+ await (instance as any).getFromCache('key'); // Avoid as any
459
483
  ```
460
484
 
461
- #### 适用场景
485
+ #### Applicable Scenarios
462
486
 
463
- - **Mock 对象**: 对于测试用的 Mock 数据,使用 `as any` 避免复杂的类型定义
464
- - **第三方库**: 处理复杂的第三方库类型时,适当使用 `any` 提高效率
465
- - **测试断言**: 在确定对象存在的测试场景中,使用 `!` 非空断言
466
- - **私有成员访问**: 优先使用中括号 `instance['privateMethod']()` 而不是 `(instance as any).privateMethod()`
467
- - **临时调试**: 快速编写测试时,先用 `any` 保证功能,后续可选择性地优化类型
487
+ - **Mock Objects**: Use `as any` for test mock data to avoid complex type definitions
488
+ - **Third-Party Libraries**: Use `any` appropriately when handling complex third-party library types
489
+ - **Test Assertions**: Use `!` non-null assertion in test scenarios where you're certain the object exists
490
+ - **Private Member Access**: Prefer bracket notation `instance['privateMethod']()` over `(instance as any).privateMethod()`
491
+ - **Temporary Debugging**: When quickly writing tests, use `any` first to ensure functionality, then optionally optimize types later
468
492
 
469
- #### 注意事项
493
+ #### Important Notes
470
494
 
471
- - **适度使用**: 不要过度依赖 `any`,核心业务逻辑的类型仍应保持严格
472
- - **私有成员访问优先级**: 中括号访问 > `as any` 转换,保持更好的类型安全性
473
- - **文档说明**: 对于使用 `any` 的复杂场景,添加注释说明原因
474
- - **测试覆盖**: 确保即使使用了 `any`,测试仍能有效验证功能正确性
495
+ - **Use Moderately**: Don't over-rely on `any`; core business logic types should remain strict
496
+ - **Private Member Access Priority**: Bracket notation > `as any` casting for better type safety
497
+ - **Documentation**: Add comments explaining the reason for complex `any` usage scenarios
498
+ - **Test Coverage**: Ensure tests still effectively verify correctness even when using `any`
475
499
 
476
- ### 检查最近修改记录
500
+ ### Checking Recent Modifications
477
501
 
478
- **核心原则**:测试突然失败时,优先检查最近的代码修改。
502
+ **Core Principle**: When tests suddenly fail, first check recent code changes.
479
503
 
480
- #### 快速检查方法
504
+ #### Quick Check Methods
481
505
 
482
506
  ```bash
483
- git status # 查看当前修改状态
484
- git diff HEAD -- '*.test.*' # 检查测试文件改动
485
- git diff main...HEAD # 对比主分支差异
486
- gh pr diff # 查看PR中的所有改动
507
+ git status # View current modification status
508
+ git diff HEAD -- '*.test.*' # Check test file changes
509
+ git diff main...HEAD # Compare with main branch
510
+ gh pr diff # View all changes in the PR
487
511
  ```
488
512
 
489
- #### 常见原因与解决
513
+ #### Common Causes and Solutions
490
514
 
491
- - **最新提交引入bug** → 检查并修复实现代码
492
- - **分支代码滞后** → `git rebase main` 同步主分支
515
+ - **Latest commit introduced a bug** → Check and fix the implementation code
516
+ - **Branch code is outdated** → `git rebase main` to sync with main branch
493
517
 
494
- ## 特殊场景的测试
518
+ ## Special Testing Scenarios
495
519
 
496
- 针对一些特殊场景的测试,需要阅读相关 rules
520
+ For special testing scenarios, refer to the related rules:
497
521
 
498
- - [Electron IPC 接口测试策略](mdc:./electron-ipc-test.mdc)
499
- - [数据库 Model 测试指南](mdc:./db-model-test.mdc)
522
+ - `electron-ipc-test.mdc` - Electron IPC Interface Testing Strategy
523
+ - `db-model-test.mdc` - Database Model Testing Guide
500
524
 
501
- ## 核心要点
525
+ ## Key Takeaways
502
526
 
503
- - **命令格式**: 使用 `bunx vitest run --silent='passed-only'` 并指定文件过滤
504
- - **修复原则**: 失败1-2次后寻求帮助,测试命名关注行为而非实现细节
505
- - **调试流程**: 复现分析假设修复验证总结
506
- - **文件组织**: 优先在现有 `describe` 块中添加测试,避免创建冗余顶级块
507
- - **数据策略**: 默认追求真实性,只有高成本(I/O、网络等)时才简化
508
- - **错误测试**: 测试错误类型和行为,避免依赖具体的错误信息文本
509
- - **模块污染**: 测试"灵异"失败时,优先怀疑模块污染,使用 `vi.resetModules()` 解决
510
- - **安全要求**: Model 测试必须包含权限检查,并在双环境下验证通过
527
+ - **Command Format**: Use `bunx vitest run --silent='passed-only'` with file filtering
528
+ - **Fix Principles**: Seek help after 1-2 failures; focus test naming on behavior, not implementation details
529
+ - **Debug Workflow**: Reproduce AnalyzeHypothesizeFixVerifySummarize
530
+ - **File Organization**: Prefer adding tests to existing `describe` blocks; avoid creating redundant top-level blocks
531
+ - **Data Strategy**: Default to authenticity; only simplify for high-cost scenarios (I/O, network, etc.)
532
+ - **Error Testing**: Test error types and behavior; avoid depending on specific error message text
533
+ - **Module Pollution**: When tests fail "mysteriously," suspect module pollution first; use `vi.resetModules()` to resolve
534
+ - **Security Requirements**: Model tests must include permission checks and pass in both environments