@zhin.js/core 1.1.0 → 1.1.3
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/lib/adapter.d.ts +1 -26
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +20 -117
- package/lib/adapter.js.map +1 -1
- package/lib/built/adapter-process.d.ts +0 -4
- package/lib/built/adapter-process.d.ts.map +1 -1
- package/lib/built/adapter-process.js +0 -95
- package/lib/built/adapter-process.js.map +1 -1
- package/lib/built/agent-preset.d.ts +2 -0
- package/lib/built/agent-preset.d.ts.map +1 -1
- package/lib/built/agent-preset.js +4 -0
- package/lib/built/agent-preset.js.map +1 -1
- package/lib/built/command.d.ts +4 -0
- package/lib/built/command.d.ts.map +1 -1
- package/lib/built/command.js +6 -0
- package/lib/built/command.js.map +1 -1
- package/lib/built/component.d.ts.map +1 -1
- package/lib/built/component.js +1 -0
- package/lib/built/component.js.map +1 -1
- package/lib/built/dispatcher.d.ts.map +1 -1
- package/lib/built/dispatcher.js +0 -13
- package/lib/built/dispatcher.js.map +1 -1
- package/lib/built/message-filter.d.ts +2 -0
- package/lib/built/message-filter.d.ts.map +1 -1
- package/lib/built/message-filter.js +5 -0
- package/lib/built/message-filter.js.map +1 -1
- package/lib/built/skill.d.ts +11 -0
- package/lib/built/skill.d.ts.map +1 -1
- package/lib/built/skill.js +14 -0
- package/lib/built/skill.js.map +1 -1
- package/lib/built/tool.d.ts +11 -44
- package/lib/built/tool.d.ts.map +1 -1
- package/lib/built/tool.js +14 -353
- package/lib/built/tool.js.map +1 -1
- package/lib/plugin.d.ts +1 -25
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +1 -77
- package/lib/plugin.js.map +1 -1
- package/lib/types.d.ts +0 -25
- package/lib/types.d.ts.map +1 -1
- package/package.json +10 -7
- package/CHANGELOG.md +0 -561
- package/REFACTORING_COMPLETE.md +0 -178
- package/REFACTORING_STATUS.md +0 -263
- package/src/adapter.ts +0 -275
- package/src/ai/index.ts +0 -55
- package/src/ai/providers/anthropic.ts +0 -379
- package/src/ai/providers/base.ts +0 -175
- package/src/ai/providers/index.ts +0 -13
- package/src/ai/providers/ollama.ts +0 -302
- package/src/ai/providers/openai.ts +0 -174
- package/src/ai/types.ts +0 -348
- package/src/bot.ts +0 -37
- package/src/built/adapter-process.ts +0 -177
- package/src/built/agent-preset.ts +0 -136
- package/src/built/ai-trigger.ts +0 -259
- package/src/built/command.ts +0 -108
- package/src/built/common-adapter-tools.ts +0 -242
- package/src/built/component.ts +0 -130
- package/src/built/config.ts +0 -335
- package/src/built/cron.ts +0 -156
- package/src/built/database.ts +0 -134
- package/src/built/dispatcher.ts +0 -496
- package/src/built/login-assist.ts +0 -131
- package/src/built/message-filter.ts +0 -390
- package/src/built/permission.ts +0 -151
- package/src/built/schema-feature.ts +0 -190
- package/src/built/skill.ts +0 -221
- package/src/built/tool.ts +0 -948
- package/src/command.ts +0 -87
- package/src/component.ts +0 -565
- package/src/cron.ts +0 -4
- package/src/errors.ts +0 -46
- package/src/feature.ts +0 -7
- package/src/index.ts +0 -53
- package/src/jsx-dev-runtime.ts +0 -2
- package/src/jsx-runtime.ts +0 -12
- package/src/jsx.ts +0 -135
- package/src/message.ts +0 -48
- package/src/models/system-log.ts +0 -20
- package/src/models/user.ts +0 -15
- package/src/notice.ts +0 -98
- package/src/plugin.ts +0 -896
- package/src/prompt.ts +0 -293
- package/src/request.ts +0 -95
- package/src/scheduler/index.ts +0 -19
- package/src/scheduler/scheduler.ts +0 -372
- package/src/scheduler/types.ts +0 -74
- package/src/tool-zod.ts +0 -115
- package/src/types-generator.ts +0 -78
- package/src/types.ts +0 -505
- package/src/utils.ts +0 -227
- package/tests/adapter.test.ts +0 -638
- package/tests/ai/ai-trigger.test.ts +0 -368
- package/tests/ai/providers.integration.test.ts +0 -227
- package/tests/ai/setup.ts +0 -308
- package/tests/ai/tool.test.ts +0 -800
- package/tests/bot.test.ts +0 -151
- package/tests/command.test.ts +0 -737
- package/tests/component-new.test.ts +0 -361
- package/tests/config.test.ts +0 -372
- package/tests/cron.test.ts +0 -82
- package/tests/dispatcher.test.ts +0 -293
- package/tests/errors.test.ts +0 -21
- package/tests/expression-evaluation.test.ts +0 -258
- package/tests/features-builtin.test.ts +0 -191
- package/tests/jsx-runtime.test.ts +0 -45
- package/tests/jsx.test.ts +0 -319
- package/tests/message-filter.test.ts +0 -566
- package/tests/message.test.ts +0 -402
- package/tests/notice.test.ts +0 -198
- package/tests/plugin.test.ts +0 -779
- package/tests/prompt.test.ts +0 -78
- package/tests/redos-protection.test.ts +0 -198
- package/tests/request.test.ts +0 -221
- package/tests/schema.test.ts +0 -248
- package/tests/skill-feature.test.ts +0 -179
- package/tests/test-utils.ts +0 -59
- package/tests/tool-feature.test.ts +0 -254
- package/tests/types.test.ts +0 -162
- package/tests/utils.test.ts +0 -135
- package/tsconfig.json +0 -24
package/tests/config.test.ts
DELETED
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
-
import { ConfigLoader } from '../src/built/config'
|
|
3
|
-
import fs from 'fs'
|
|
4
|
-
import path from 'path'
|
|
5
|
-
|
|
6
|
-
describe('ConfigLoader', () => {
|
|
7
|
-
const testConfigPath = path.join(process.cwd(), 'test-config.json')
|
|
8
|
-
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
// 清理测试文件
|
|
11
|
-
if (fs.existsSync(testConfigPath)) {
|
|
12
|
-
fs.unlinkSync(testConfigPath)
|
|
13
|
-
}
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
describe('Proxy behavior', () => {
|
|
17
|
-
it('should handle array methods correctly', () => {
|
|
18
|
-
const config = {
|
|
19
|
-
items: ['item1', 'item2', 'item3'],
|
|
20
|
-
bots: [
|
|
21
|
-
{ context: 'sandbox', name: 'bot1' },
|
|
22
|
-
{ context: 'sandbox', name: 'bot2' }
|
|
23
|
-
]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
27
|
-
const proxiedData = loader.data
|
|
28
|
-
|
|
29
|
-
// 测试数组的 map 方法
|
|
30
|
-
expect(() => {
|
|
31
|
-
const mapped = proxiedData.items.map((item: string) => item.toUpperCase())
|
|
32
|
-
expect(mapped).toEqual(['ITEM1', 'ITEM2', 'ITEM3'])
|
|
33
|
-
}).not.toThrow()
|
|
34
|
-
|
|
35
|
-
// 测试数组的 filter 方法
|
|
36
|
-
expect(() => {
|
|
37
|
-
const filtered = proxiedData.bots.filter((bot: any) => bot.name === 'bot1')
|
|
38
|
-
expect(filtered).toHaveLength(1)
|
|
39
|
-
}).not.toThrow()
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('should handle nested objects', () => {
|
|
43
|
-
const config = {
|
|
44
|
-
database: {
|
|
45
|
-
dialect: 'sqlite',
|
|
46
|
-
filename: './data/bot.db'
|
|
47
|
-
},
|
|
48
|
-
http: {
|
|
49
|
-
port: 8086,
|
|
50
|
-
username: '${username}',
|
|
51
|
-
password: '${password}'
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
56
|
-
const proxiedData = loader.data
|
|
57
|
-
|
|
58
|
-
expect(proxiedData.database.dialect).toBe('sqlite')
|
|
59
|
-
expect(proxiedData.http.port).toBe(8086)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('should resolve environment variables', () => {
|
|
63
|
-
process.env.TEST_VAR = 'test_value'
|
|
64
|
-
|
|
65
|
-
const config = {
|
|
66
|
-
testValue: '${TEST_VAR}'
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
70
|
-
const proxiedData = loader.data
|
|
71
|
-
|
|
72
|
-
expect(proxiedData.testValue).toBe('test_value')
|
|
73
|
-
|
|
74
|
-
delete process.env.TEST_VAR
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('should handle escaped environment variables', () => {
|
|
78
|
-
const config = {
|
|
79
|
-
escapedValue: '\\${NOT_A_VAR}'
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
83
|
-
const proxiedData = loader.data
|
|
84
|
-
|
|
85
|
-
expect(proxiedData.escapedValue).toBe('${NOT_A_VAR}')
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('should handle default values for missing env vars', () => {
|
|
89
|
-
const config = {
|
|
90
|
-
valueWithDefault: '${MISSING_VAR:default_value}'
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
94
|
-
const proxiedData = loader.data
|
|
95
|
-
|
|
96
|
-
expect(proxiedData.valueWithDefault).toBe('default_value')
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it('should not proxy function properties', () => {
|
|
100
|
-
const config = {
|
|
101
|
-
items: [1, 2, 3]
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
105
|
-
const proxiedData = loader.data
|
|
106
|
-
|
|
107
|
-
// 确保数组方法可以正常调用
|
|
108
|
-
expect(typeof proxiedData.items.map).toBe('function')
|
|
109
|
-
expect(typeof proxiedData.items.filter).toBe('function')
|
|
110
|
-
expect(typeof proxiedData.items.reduce).toBe('function')
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
it('should handle Set operations from array', () => {
|
|
114
|
-
const config = {
|
|
115
|
-
bots: [
|
|
116
|
-
{ context: 'sandbox', name: 'bot1' },
|
|
117
|
-
{ context: 'process', name: 'bot2' },
|
|
118
|
-
{ context: 'sandbox', name: 'bot3' }
|
|
119
|
-
]
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
123
|
-
const proxiedData = loader.data
|
|
124
|
-
|
|
125
|
-
// 模拟 setup.ts 中的操作
|
|
126
|
-
expect(() => {
|
|
127
|
-
const contexts = new Set(proxiedData.bots.map((bot: any) => bot.context))
|
|
128
|
-
expect(contexts.size).toBe(2)
|
|
129
|
-
expect(contexts.has('sandbox')).toBe(true)
|
|
130
|
-
expect(contexts.has('process')).toBe(true)
|
|
131
|
-
}).not.toThrow()
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
describe('Raw data access', () => {
|
|
136
|
-
it('should provide raw data without proxy', () => {
|
|
137
|
-
const config = {
|
|
138
|
-
value: '${TEST_VAR}'
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
142
|
-
|
|
143
|
-
// raw 应该返回原始值,不解析环境变量
|
|
144
|
-
expect(loader.raw.value).toBe('${TEST_VAR}')
|
|
145
|
-
|
|
146
|
-
// data 应该尝试解析环境变量
|
|
147
|
-
expect(loader.data.value).toBeTruthy()
|
|
148
|
-
})
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
describe('File operations', () => {
|
|
152
|
-
it('should save and load JSON config', () => {
|
|
153
|
-
const jsonPath = path.join(process.cwd(), 'test-config.json')
|
|
154
|
-
const config = {
|
|
155
|
-
name: 'test',
|
|
156
|
-
value: 123
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const loader = new ConfigLoader(jsonPath, config)
|
|
160
|
-
loader.save(jsonPath)
|
|
161
|
-
|
|
162
|
-
expect(fs.existsSync(jsonPath)).toBe(true)
|
|
163
|
-
|
|
164
|
-
const content = fs.readFileSync(jsonPath, 'utf-8')
|
|
165
|
-
const parsed = JSON.parse(content)
|
|
166
|
-
expect(parsed.name).toBe('test')
|
|
167
|
-
expect(parsed.value).toBe(123)
|
|
168
|
-
|
|
169
|
-
fs.unlinkSync(jsonPath)
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
it('should save and load YAML config', () => {
|
|
173
|
-
const yamlPath = path.join(process.cwd(), 'test-config.yml')
|
|
174
|
-
const config = {
|
|
175
|
-
name: 'test',
|
|
176
|
-
value: 123
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const loader = new ConfigLoader(yamlPath, config)
|
|
180
|
-
loader.save(yamlPath)
|
|
181
|
-
|
|
182
|
-
expect(fs.existsSync(yamlPath)).toBe(true)
|
|
183
|
-
|
|
184
|
-
fs.unlinkSync(yamlPath)
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
it('should auto-save on property change', () => {
|
|
188
|
-
const config = {
|
|
189
|
-
value: 'initial'
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
193
|
-
loader.save(testConfigPath)
|
|
194
|
-
|
|
195
|
-
// 修改属性应该触发自动保存
|
|
196
|
-
const proxiedData = loader.data
|
|
197
|
-
proxiedData.value = 'changed'
|
|
198
|
-
|
|
199
|
-
// 重新读取文件验证保存
|
|
200
|
-
const content = fs.readFileSync(testConfigPath, 'utf-8')
|
|
201
|
-
const parsed = JSON.parse(content)
|
|
202
|
-
expect(parsed.value).toBe('changed')
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
it('should auto-save on property deletion', () => {
|
|
206
|
-
const config = {
|
|
207
|
-
value: 'test',
|
|
208
|
-
other: 'keep'
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
212
|
-
loader.save(testConfigPath)
|
|
213
|
-
|
|
214
|
-
// 删除属性应该触发自动保存
|
|
215
|
-
const proxiedData = loader.data as any
|
|
216
|
-
delete proxiedData.value
|
|
217
|
-
|
|
218
|
-
// 重新读取文件验证保存
|
|
219
|
-
const content = fs.readFileSync(testConfigPath, 'utf-8')
|
|
220
|
-
const parsed = JSON.parse(content)
|
|
221
|
-
expect(parsed.value).toBeUndefined()
|
|
222
|
-
expect(parsed.other).toBe('keep')
|
|
223
|
-
})
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
describe('ConfigService', () => {
|
|
227
|
-
it('should load and cache configs', async () => {
|
|
228
|
-
const { ConfigService } = await import('../src/built/config')
|
|
229
|
-
const service = new ConfigService()
|
|
230
|
-
|
|
231
|
-
const config = { test: 'value' }
|
|
232
|
-
service.load('test-config.json', config)
|
|
233
|
-
|
|
234
|
-
expect(service.configs.has('test-config.json')).toBe(true)
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
it('should throw error for unsupported format', async () => {
|
|
238
|
-
const { ConfigService } = await import('../src/built/config')
|
|
239
|
-
const service = new ConfigService()
|
|
240
|
-
|
|
241
|
-
expect(() => {
|
|
242
|
-
service.load('test.txt', {})
|
|
243
|
-
}).toThrow('不支持的配置文件格式')
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
it('should get config data', async () => {
|
|
247
|
-
const { ConfigService } = await import('../src/built/config')
|
|
248
|
-
const service = new ConfigService()
|
|
249
|
-
|
|
250
|
-
const config = { test: 'value' }
|
|
251
|
-
service.load(testConfigPath, config)
|
|
252
|
-
|
|
253
|
-
const data = service.get(testConfigPath)
|
|
254
|
-
expect(data.test).toBe('value')
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
it('should get raw config data', async () => {
|
|
258
|
-
const { ConfigService } = await import('../src/built/config')
|
|
259
|
-
const service = new ConfigService()
|
|
260
|
-
|
|
261
|
-
const config = { test: '${VAR}' }
|
|
262
|
-
service.load(testConfigPath, config)
|
|
263
|
-
|
|
264
|
-
const raw = service.getRaw(testConfigPath)
|
|
265
|
-
expect(raw.test).toBe('${VAR}')
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
it('should update config data', async () => {
|
|
269
|
-
const { ConfigService } = await import('../src/built/config')
|
|
270
|
-
const service = new ConfigService()
|
|
271
|
-
|
|
272
|
-
const config = { test: 'initial' }
|
|
273
|
-
service.load(testConfigPath, config)
|
|
274
|
-
|
|
275
|
-
service.set(testConfigPath, { test: 'updated' })
|
|
276
|
-
|
|
277
|
-
const data = service.get(testConfigPath)
|
|
278
|
-
expect(data.test).toBe('updated')
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
it('should throw error when getting non-existent config', async () => {
|
|
282
|
-
const { ConfigService } = await import('../src/built/config')
|
|
283
|
-
const service = new ConfigService()
|
|
284
|
-
|
|
285
|
-
service.load(testConfigPath, { test: 'value' })
|
|
286
|
-
service.configs.delete(testConfigPath) // 手动删除以模拟不存在的情况
|
|
287
|
-
|
|
288
|
-
// 由于 get 会自动加载,我们需要测试 set
|
|
289
|
-
expect(() => {
|
|
290
|
-
service.set('non-existent.json', {})
|
|
291
|
-
}).toThrow('配置文件 non-existent.json 未加载')
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
it('should auto-load config if not cached', async () => {
|
|
295
|
-
const { ConfigService } = await import('../src/built/config')
|
|
296
|
-
const service = new ConfigService()
|
|
297
|
-
|
|
298
|
-
const config = { test: 'value' }
|
|
299
|
-
// 先保存文件
|
|
300
|
-
const loader = new ConfigLoader(testConfigPath, config)
|
|
301
|
-
loader.save(testConfigPath)
|
|
302
|
-
|
|
303
|
-
// 不预先加载,直接 get
|
|
304
|
-
const data = service.get(testConfigPath, config)
|
|
305
|
-
expect(data.test).toBe('value')
|
|
306
|
-
expect(service.configs.has(testConfigPath)).toBe(true)
|
|
307
|
-
})
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
describe('Extension detection', () => {
|
|
311
|
-
it('should detect .json extension', () => {
|
|
312
|
-
const loader = new ConfigLoader('config.json', {})
|
|
313
|
-
expect(loader.extension).toBe('.json')
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
it('should detect .yml extension', () => {
|
|
317
|
-
const loader = new ConfigLoader('config.yml', {})
|
|
318
|
-
expect(loader.extension).toBe('.yml')
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
it('should detect .yaml extension', () => {
|
|
322
|
-
const loader = new ConfigLoader('config.yaml', {})
|
|
323
|
-
expect(loader.extension).toBe('.yaml')
|
|
324
|
-
})
|
|
325
|
-
})
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
// ============================================================================
|
|
329
|
-
// ConfigFeature 补全测试
|
|
330
|
-
// ============================================================================
|
|
331
|
-
describe('ConfigFeature', () => {
|
|
332
|
-
let feature: import('../src/built/config.js').ConfigFeature
|
|
333
|
-
|
|
334
|
-
beforeEach(async () => {
|
|
335
|
-
const { ConfigFeature } = await import('../src/built/config.js')
|
|
336
|
-
feature = new ConfigFeature()
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
it('应有正确的元数据', () => {
|
|
340
|
-
expect(feature.name).toBe('config')
|
|
341
|
-
expect(feature.icon).toBe('Settings')
|
|
342
|
-
expect(feature.desc).toBe('配置')
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
it('add 应添加配置记录', () => {
|
|
346
|
-
const record = { key: 'debug', defaultValue: false }
|
|
347
|
-
const dispose = feature.add(record, 'test-plugin')
|
|
348
|
-
expect(feature.items).toHaveLength(1)
|
|
349
|
-
expect(feature.items[0]).toBe(record)
|
|
350
|
-
expect(typeof dispose).toBe('function')
|
|
351
|
-
})
|
|
352
|
-
|
|
353
|
-
it('toJSON 应返回正确结构', () => {
|
|
354
|
-
feature.add({ key: 'debug', defaultValue: false }, 'test-plugin')
|
|
355
|
-
feature.add({ key: 'port', defaultValue: 8080 }, 'test-plugin')
|
|
356
|
-
|
|
357
|
-
const json = feature.toJSON()
|
|
358
|
-
expect(json.name).toBe('config')
|
|
359
|
-
expect(json.count).toBe(2)
|
|
360
|
-
expect(json.items[0]).toEqual({ name: 'debug' })
|
|
361
|
-
expect(json.items[1]).toEqual({ name: 'port' })
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
it('toJSON(pluginName) 应按插件过滤', () => {
|
|
365
|
-
feature.add({ key: 'a', defaultValue: 1 }, 'plugin-a')
|
|
366
|
-
feature.add({ key: 'b', defaultValue: 2 }, 'plugin-b')
|
|
367
|
-
|
|
368
|
-
const json = feature.toJSON('plugin-a')
|
|
369
|
-
expect(json.count).toBe(1)
|
|
370
|
-
expect(json.items[0].name).toBe('a')
|
|
371
|
-
})
|
|
372
|
-
})
|
package/tests/cron.test.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CronFeature 测试(Cron 类测试已迁移到 @zhin.js/kernel)
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
5
|
-
import { Cron } from '../src/cron'
|
|
6
|
-
|
|
7
|
-
describe('CronFeature', () => {
|
|
8
|
-
let feature: import('../src/built/cron.js').CronFeature
|
|
9
|
-
let mockCallback: ReturnType<typeof vi.fn>
|
|
10
|
-
|
|
11
|
-
beforeEach(async () => {
|
|
12
|
-
vi.useFakeTimers()
|
|
13
|
-
mockCallback = vi.fn()
|
|
14
|
-
const { CronFeature } = await import('../src/built/cron.js')
|
|
15
|
-
feature = new CronFeature()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
feature?.dispose()
|
|
20
|
-
vi.useRealTimers()
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('add 应自动启动任务', () => {
|
|
24
|
-
const cron = new Cron('* * * * * *', mockCallback)
|
|
25
|
-
feature.add(cron, 'test-plugin')
|
|
26
|
-
expect(cron.running).toBe(true)
|
|
27
|
-
expect(feature.items).toHaveLength(1)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('add 应返回 dispose 函数', () => {
|
|
31
|
-
const cron = new Cron('* * * * * *', mockCallback)
|
|
32
|
-
const dispose = feature.add(cron, 'test-plugin')
|
|
33
|
-
expect(typeof dispose).toBe('function')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('remove 应自动停止任务', () => {
|
|
37
|
-
const cron = new Cron('* * * * * *', mockCallback)
|
|
38
|
-
feature.add(cron, 'test-plugin')
|
|
39
|
-
feature.remove(cron)
|
|
40
|
-
expect(cron.running).toBe(false)
|
|
41
|
-
expect(feature.items).toHaveLength(0)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('stopAll 应停止所有任务', () => {
|
|
45
|
-
const cron1 = new Cron('* * * * * *', mockCallback)
|
|
46
|
-
const cron2 = new Cron('*/2 * * * * *', mockCallback)
|
|
47
|
-
feature.add(cron1, 'p1')
|
|
48
|
-
feature.add(cron2, 'p2')
|
|
49
|
-
feature.stopAll()
|
|
50
|
-
expect(cron1.running).toBe(false)
|
|
51
|
-
expect(cron2.running).toBe(false)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('startAll 应启动所有已停止的任务', () => {
|
|
55
|
-
const cron1 = new Cron('* * * * * *', mockCallback)
|
|
56
|
-
const cron2 = new Cron('*/2 * * * * *', mockCallback)
|
|
57
|
-
feature.add(cron1, 'p1')
|
|
58
|
-
feature.add(cron2, 'p2')
|
|
59
|
-
feature.stopAll()
|
|
60
|
-
feature.startAll()
|
|
61
|
-
expect(cron1.running).toBe(true)
|
|
62
|
-
expect(cron2.running).toBe(true)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('toJSON 应返回正确结构', () => {
|
|
66
|
-
const cron = new Cron('* * * * * *', mockCallback)
|
|
67
|
-
feature.add(cron, 'test-plugin')
|
|
68
|
-
const json = feature.toJSON()
|
|
69
|
-
expect(json.name).toBe('cron')
|
|
70
|
-
expect(json.icon).toBe('Clock')
|
|
71
|
-
expect(json.count).toBe(1)
|
|
72
|
-
expect(json.items[0]).toHaveProperty('expression')
|
|
73
|
-
expect(json.items[0]).toHaveProperty('running', true)
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('dispose 应停止所有任务', () => {
|
|
77
|
-
const cron = new Cron('* * * * * *', mockCallback)
|
|
78
|
-
feature.add(cron, 'test-plugin')
|
|
79
|
-
feature.dispose()
|
|
80
|
-
expect(cron.running).toBe(false)
|
|
81
|
-
})
|
|
82
|
-
})
|