@zhin.js/cli 1.0.14 → 1.0.16
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.
- package/CHANGELOG.md +13 -0
- package/TEST_GENERATION.md +398 -0
- package/lib/commands/new.d.ts.map +1 -1
- package/lib/commands/new.js +534 -4
- package/lib/commands/new.js.map +1 -1
- package/package.json +14 -14
- package/src/commands/new.ts +552 -6
- package/tests/new-integration.test.ts +232 -0
- package/tests/utils.test.ts +77 -0
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
# Zhin CLI 测试生成功能
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
Zhin CLI 的 `new` 命令现在支持自动生成测试文件,为开发者提供开箱即用的测试套件模板。
|
|
6
|
+
|
|
7
|
+
## 使用方法
|
|
8
|
+
|
|
9
|
+
### 创建插件时自动生成测试
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# 创建普通插件(默认)
|
|
13
|
+
zhin new my-plugin
|
|
14
|
+
|
|
15
|
+
# 创建服务
|
|
16
|
+
zhin new my-service --type service
|
|
17
|
+
|
|
18
|
+
# 创建适配器
|
|
19
|
+
zhin new my-adapter --type adapter
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 交互式创建
|
|
23
|
+
|
|
24
|
+
如果不指定类型,CLI 会询问你要创建的插件类型:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
zhin new my-plugin
|
|
28
|
+
# ? 请选择插件类型:
|
|
29
|
+
# > 普通插件 (Plugin)
|
|
30
|
+
# 服务 (Service)
|
|
31
|
+
# 适配器 (Adapter)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 生成的测试文件
|
|
35
|
+
|
|
36
|
+
所有插件类型都会在 `tests/index.test.ts` 中生成相应的测试模板。
|
|
37
|
+
|
|
38
|
+
### 1. 普通插件测试模板
|
|
39
|
+
|
|
40
|
+
生成位置:`plugins/my-plugin/tests/index.test.ts`
|
|
41
|
+
|
|
42
|
+
**包含的测试套件:**
|
|
43
|
+
|
|
44
|
+
#### Plugin Instance
|
|
45
|
+
- ✅ 创建插件实例
|
|
46
|
+
- ✅ 验证插件名称
|
|
47
|
+
- ✅ 验证父插件引用
|
|
48
|
+
- ✅ 验证 logger 存在
|
|
49
|
+
|
|
50
|
+
#### Plugin Lifecycle
|
|
51
|
+
- ✅ 成功启动
|
|
52
|
+
- ✅ 成功停止
|
|
53
|
+
- ✅ 触发 mounted 事件
|
|
54
|
+
- ✅ 触发 dispose 事件
|
|
55
|
+
|
|
56
|
+
#### Plugin Features
|
|
57
|
+
- ✅ 注册中间件
|
|
58
|
+
- ✅ 执行中间件链
|
|
59
|
+
|
|
60
|
+
#### Custom Tests
|
|
61
|
+
- 📝 预留自定义测试区域
|
|
62
|
+
|
|
63
|
+
**示例:**
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
describe('MyPlugin Plugin', () => {
|
|
67
|
+
let plugin: Plugin
|
|
68
|
+
let rootPlugin: Plugin
|
|
69
|
+
|
|
70
|
+
beforeEach(async () => {
|
|
71
|
+
rootPlugin = new Plugin('/test/root-plugin.ts')
|
|
72
|
+
plugin = new Plugin('/plugins/my-plugin/src/index.ts', rootPlugin)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
afterEach(async () => {
|
|
76
|
+
if (plugin && plugin.started) {
|
|
77
|
+
await plugin.stop()
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// ... 测试用例
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### 2. 服务测试模板
|
|
88
|
+
|
|
89
|
+
生成位置:`plugins/services/my-service/tests/index.test.ts`
|
|
90
|
+
|
|
91
|
+
**包含的测试套件:**
|
|
92
|
+
|
|
93
|
+
#### Service Instance
|
|
94
|
+
- ✅ 创建服务实例
|
|
95
|
+
- ✅ 验证服务类型
|
|
96
|
+
|
|
97
|
+
#### Service Methods
|
|
98
|
+
- 📝 验证必需方法存在
|
|
99
|
+
- 📝 测试方法执行
|
|
100
|
+
|
|
101
|
+
#### Service Lifecycle
|
|
102
|
+
- 📝 测试初始化
|
|
103
|
+
- 📝 测试清理逻辑
|
|
104
|
+
|
|
105
|
+
#### Service Dependencies
|
|
106
|
+
- 📝 测试依赖注入
|
|
107
|
+
|
|
108
|
+
#### Custom Tests
|
|
109
|
+
- 📝 预留自定义测试区域
|
|
110
|
+
|
|
111
|
+
**示例:**
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
describe('MyService Service', () => {
|
|
115
|
+
let plugin: Plugin
|
|
116
|
+
let service: any
|
|
117
|
+
|
|
118
|
+
beforeEach(async () => {
|
|
119
|
+
plugin = new Plugin('/test/service-plugin.ts')
|
|
120
|
+
// TODO: 初始化你的服务实例
|
|
121
|
+
// service = await createYourService(plugin)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
// ... 测试用例
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**需要开发者完成的部分:**
|
|
129
|
+
1. 实现服务实例的创建逻辑
|
|
130
|
+
2. 添加具体的方法测试
|
|
131
|
+
3. 测试服务的初始化和清理
|
|
132
|
+
4. 测试依赖注入
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### 3. 适配器测试模板
|
|
137
|
+
|
|
138
|
+
生成位置:`plugins/adapters/my-adapter/tests/index.test.ts`
|
|
139
|
+
|
|
140
|
+
**包含的测试套件:**
|
|
141
|
+
|
|
142
|
+
#### Adapter Instance
|
|
143
|
+
- ✅ 创建适配器实例
|
|
144
|
+
- ✅ 验证适配器名称
|
|
145
|
+
- ✅ 验证插件引用
|
|
146
|
+
- ✅ 验证 logger 存在
|
|
147
|
+
- ✅ 验证 bots 初始化
|
|
148
|
+
|
|
149
|
+
#### Bot Management
|
|
150
|
+
- ✅ 从配置创建 Bot
|
|
151
|
+
- ✅ 验证 createBot 方法
|
|
152
|
+
- ✅ 验证 Bot 属性
|
|
153
|
+
|
|
154
|
+
#### Adapter Lifecycle
|
|
155
|
+
- ✅ 启动适配器
|
|
156
|
+
- ✅ 停止适配器
|
|
157
|
+
- ✅ 添加到插件适配器列表
|
|
158
|
+
- ✅ 从插件适配器列表移除
|
|
159
|
+
- ✅ 停止时清理 bots
|
|
160
|
+
|
|
161
|
+
#### Event Handling
|
|
162
|
+
- ✅ 监听 call.recallMessage 事件
|
|
163
|
+
- ✅ 监听 call.sendMessage 事件
|
|
164
|
+
- ✅ 监听 message.receive 事件
|
|
165
|
+
- ✅ 停止时移除所有监听器
|
|
166
|
+
|
|
167
|
+
#### Message Sending
|
|
168
|
+
- ✅ 处理 sendMessage 事件
|
|
169
|
+
- ✅ Bot 不存在时抛出错误
|
|
170
|
+
|
|
171
|
+
#### Message Receiving
|
|
172
|
+
- ✅ 通过中间件处理接收的消息
|
|
173
|
+
|
|
174
|
+
#### Bot Methods
|
|
175
|
+
- ✅ connect 方法
|
|
176
|
+
- ✅ disconnect 方法
|
|
177
|
+
- ✅ sendMessage 方法
|
|
178
|
+
- ✅ recallMessage 方法
|
|
179
|
+
- ✅ 连接成功
|
|
180
|
+
- ✅ 断开连接成功
|
|
181
|
+
|
|
182
|
+
#### Custom Tests
|
|
183
|
+
- 📝 预留自定义测试区域
|
|
184
|
+
|
|
185
|
+
**示例:**
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Mock Bot 类(用于测试)
|
|
189
|
+
class MockMyAdapterBot extends EventEmitter implements Bot {
|
|
190
|
+
// ... Bot 实现
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Mock Adapter 类(用于测试)
|
|
194
|
+
class MockMyAdapterAdapter extends Adapter<any, any> {
|
|
195
|
+
// ... Adapter 实现
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
describe('MyAdapter Adapter', () => {
|
|
199
|
+
let plugin: Plugin
|
|
200
|
+
let adapter: MockMyAdapterAdapter
|
|
201
|
+
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
plugin = new Plugin('/test/adapter-plugin.ts')
|
|
204
|
+
adapter = new MockMyAdapterAdapter(plugin, 'my-adapter', [
|
|
205
|
+
{ name: 'test-bot', token: 'test-token' }
|
|
206
|
+
])
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
// ... 测试用例
|
|
210
|
+
})
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**需要开发者完成的部分:**
|
|
214
|
+
1. 将 Mock 类替换为实际的 Adapter 和 Bot 类
|
|
215
|
+
2. 添加平台特定的测试(如 webhook、polling 等)
|
|
216
|
+
3. 测试平台特定的消息格式
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 运行测试
|
|
221
|
+
|
|
222
|
+
生成的 `package.json` 包含以下测试脚本:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# 运行测试(单次)
|
|
226
|
+
pnpm test
|
|
227
|
+
|
|
228
|
+
# 监听模式
|
|
229
|
+
pnpm test:watch
|
|
230
|
+
|
|
231
|
+
# 生成覆盖率报告
|
|
232
|
+
pnpm test:coverage
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## 测试覆盖率目标
|
|
236
|
+
|
|
237
|
+
使用生成的测试模板,你可以快速达到以下覆盖率:
|
|
238
|
+
|
|
239
|
+
- **普通插件**: 60-70% 基础覆盖率
|
|
240
|
+
- **服务**: 50-60% 基础覆盖率(需要补充具体实现)
|
|
241
|
+
- **适配器**: 70-80% 基础覆盖率
|
|
242
|
+
|
|
243
|
+
通过添加自定义测试,可以进一步提高覆盖率至 90%+。
|
|
244
|
+
|
|
245
|
+
## 最佳实践
|
|
246
|
+
|
|
247
|
+
### 1. 立即运行测试
|
|
248
|
+
|
|
249
|
+
创建插件后,立即运行测试确保基础结构正常:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
cd plugins/my-plugin
|
|
253
|
+
pnpm test
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### 2. 逐步完善测试
|
|
257
|
+
|
|
258
|
+
生成的测试模板包含 TODO 注释,标记了需要开发者实现的部分:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// TODO: 初始化你的服务实例
|
|
262
|
+
// service = await createYourService(plugin)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 3. 添加自定义测试
|
|
266
|
+
|
|
267
|
+
在 `Custom Tests` 区域添加特定于你的插件的测试:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
describe('Custom Tests', () => {
|
|
271
|
+
it('should handle specific feature', () => {
|
|
272
|
+
// 你的测试逻辑
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 4. 使用 TDD 开发
|
|
278
|
+
|
|
279
|
+
1. 先写测试(修改生成的模板)
|
|
280
|
+
2. 运行测试(应该失败)
|
|
281
|
+
3. 实现功能
|
|
282
|
+
4. 运行测试(应该通过)
|
|
283
|
+
5. 重构代码
|
|
284
|
+
|
|
285
|
+
### 5. 保持测试更新
|
|
286
|
+
|
|
287
|
+
当你添加新功能时,同时添加对应的测试:
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
describe('New Feature', () => {
|
|
291
|
+
it('should work correctly', () => {
|
|
292
|
+
// 测试新功能
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## 示例工作流
|
|
298
|
+
|
|
299
|
+
### 创建一个新的服务
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
# 1. 创建服务
|
|
303
|
+
zhin new cache-service --type service
|
|
304
|
+
|
|
305
|
+
# 2. 进入目录
|
|
306
|
+
cd plugins/services/cache-service
|
|
307
|
+
|
|
308
|
+
# 3. 查看生成的测试
|
|
309
|
+
cat tests/index.test.ts
|
|
310
|
+
|
|
311
|
+
# 4. 实现服务逻辑
|
|
312
|
+
# 编辑 src/index.ts
|
|
313
|
+
|
|
314
|
+
# 5. 更新测试
|
|
315
|
+
# 编辑 tests/index.test.ts,取消 TODO 注释并实现
|
|
316
|
+
|
|
317
|
+
# 6. 运行测试
|
|
318
|
+
pnpm test
|
|
319
|
+
|
|
320
|
+
# 7. 查看覆盖率
|
|
321
|
+
pnpm test:coverage
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### 创建一个新的适配器
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
# 1. 创建适配器
|
|
328
|
+
zhin new wechat --type adapter
|
|
329
|
+
|
|
330
|
+
# 2. 进入目录
|
|
331
|
+
cd plugins/adapters/wechat
|
|
332
|
+
|
|
333
|
+
# 3. 实现适配器
|
|
334
|
+
# 编辑 src/index.ts
|
|
335
|
+
|
|
336
|
+
# 4. 更新测试中的 Mock 类为实际类
|
|
337
|
+
# 编辑 tests/index.test.ts
|
|
338
|
+
|
|
339
|
+
# 5. 添加平台特定测试
|
|
340
|
+
# 在 Custom Tests 区域添加
|
|
341
|
+
|
|
342
|
+
# 6. 运行测试
|
|
343
|
+
pnpm test
|
|
344
|
+
|
|
345
|
+
# 7. 持续开发
|
|
346
|
+
pnpm test:watch
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## 依赖
|
|
350
|
+
|
|
351
|
+
生成的 `package.json` 自动包含测试所需的依赖:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"devDependencies": {
|
|
356
|
+
"vitest": "latest",
|
|
357
|
+
"@vitest/coverage-v8": "latest"
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## 配置
|
|
363
|
+
|
|
364
|
+
测试使用项目根目录的 `vitest.config.ts` 配置。如果需要自定义配置,可以在插件目录创建自己的 `vitest.config.ts`。
|
|
365
|
+
|
|
366
|
+
## 故障排除
|
|
367
|
+
|
|
368
|
+
### 测试无法导入模块
|
|
369
|
+
|
|
370
|
+
确保已经构建了插件:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
pnpm build
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### 测试覆盖率低
|
|
377
|
+
|
|
378
|
+
1. 检查 TODO 注释,确保所有测试都已实现
|
|
379
|
+
2. 添加更多自定义测试
|
|
380
|
+
3. 测试边界情况和错误处理
|
|
381
|
+
|
|
382
|
+
### Mock 类型错误
|
|
383
|
+
|
|
384
|
+
确保 Mock 类实现了正确的接口:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
class MockBot extends EventEmitter implements Bot {
|
|
388
|
+
// 实现所有 Bot 接口方法
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## 贡献
|
|
393
|
+
|
|
394
|
+
如果你发现测试模板有改进空间,欢迎提交 PR 到 `@zhin.js/cli` 仓库!
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
**Happy Testing! 🎉**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,UAAU,SAwFnB,CAAC"}
|