Files
WechatExplorer/tests/unit/scheduled-report-service.test.ts
T
Wxw-Gu 1c8bbae1f0 fix: 增加thinking disabled
修改退群监控模板
定时日报保存日报历史
2026-09-01 11:40:14 +08:00

115 lines
4.3 KiB
TypeScript

import { mkdtemp, readFile } from 'fs/promises'
import { tmpdir } from 'os'
import { join } from 'path'
import { describe, expect, it, vi } from 'vitest'
vi.mock('electron', () => ({ app: { getPath: () => '/tmp/tracememo-test-user-data' } }))
import {
calculateNextRunAt,
ScheduledReportService,
validateScheduleTime
} from '../../src/main/services/scheduled-report-service'
import type { PersonalWechatSendCapability } from '../../src/shared/personal-wechat'
const capability: PersonalWechatSendCapability = {
supported: true,
ready: true,
status: 'ready',
capabilities: { text: true, image: true, voice: true },
senderStatus: {} as never,
message: 'ready'
}
describe('scheduled report scheduling', () => {
it('validates daily HH:mm and computes the next local occurrence', () => {
expect(validateScheduleTime('09:05')).toBe(true)
expect(validateScheduleTime('24:00')).toBe(false)
const from = new Date('2026-08-27T10:00:00+08:00')
expect(calculateNextRunAt('09:05', from)).toBe('2026-08-28T01:05:00.000Z')
expect(calculateNextRunAt('11:05', from)).toBe('2026-08-27T03:05:00.000Z')
})
it('persists lifecycle, executes generation and image sending, and restores tasks', async () => {
const storageDir = await mkdtemp(join(tmpdir(), 'tracememo-scheduled-report-'))
const now = new Date('2026-08-27T01:00:00.000Z')
const generatedPath = join(storageDir, 'report.png')
let generated = 0
let sent = 0
const saveHistory = vi.fn().mockResolvedValue({ success: true })
const service = new ScheduledReportService({
storageDir,
now: () => now,
getCapability: async () => capability,
generateReport: async () => {
generated += 1
return { success: true, pngPath: generatedPath }
},
send: async () => {
sent += 1
return { success: true, status: capability.senderStatus }
},
saveGeneratedReport: saveHistory,
isDatabaseReady: () => true
})
const created = await service.createTask({
name: '每日群报',
group: '研发群',
target: '研发群@chatroom',
scheduleTime: '09:00'
})
expect(created.success).toBe(true)
expect(created.data?.reportRange).toBe('yesterday')
const taskId = created.data!.id
const run = await service.runScheduledReportNow(taskId)
expect(run.data?.status).toBe('success')
expect(generated).toBe(1)
expect(sent).toBe(1)
expect(saveHistory).toHaveBeenCalledWith(
expect.objectContaining({
contactName: '研发群',
reportDate: undefined,
pngPath: generatedPath,
messageCount: 0
})
)
expect(await service.listExecutions(taskId)).toHaveLength(1)
const restored = new ScheduledReportService({
storageDir,
getCapability: async () => capability
})
expect((await restored.listTasks())[0].id).toBe(taskId)
await service.setTaskEnabled(taskId, false)
expect((await service.listTasks())[0].enabled).toBe(false)
await service.deleteTask(taskId)
expect(await service.listTasks()).toHaveLength(0)
expect(
JSON.parse(await readFile(join(storageDir, 'executions.json'), 'utf8'))[0].message
).toContain('微信发送成功')
})
it('does not send a generated report when history persistence fails', async () => {
const storageDir = await mkdtemp(join(tmpdir(), 'tracememo-scheduled-report-history-'))
const generatedPath = join(storageDir, 'report.png')
const send = vi.fn().mockResolvedValue({ success: true, status: capability.senderStatus })
const service = new ScheduledReportService({
storageDir,
getCapability: async () => capability,
generateReport: async () => ({ success: true, pngPath: generatedPath }),
saveGeneratedReport: vi.fn().mockResolvedValue({ success: false, error: '磁盘不可写' }),
send,
isDatabaseReady: () => true
})
const created = await service.createTask({
name: '历史失败日报',
group: '研发群',
target: '研发群@chatroom',
scheduleTime: '09:00'
})
const result = await service.runScheduledReportNow(created.data!.id)
expect(result.success).toBe(false)
expect(result.data?.error).toContain('report_history_save_failed:磁盘不可写')
expect(send).not.toHaveBeenCalled()
})
})