mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-08-17 03:27:00 +08:00
121 lines
3.7 KiB
TypeScript
121 lines
3.7 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import type { Message } from '../../src/shared/types'
|
|
import type { VoiceModelStatus } from '../../src/shared/voice-recognition'
|
|
import {
|
|
toVoiceMessageReference,
|
|
transcribeVoiceMessages,
|
|
type VoiceTranscriptionProgress
|
|
} from '../../src/renderer/src/utils/voice-message-reference'
|
|
|
|
const status = (state: VoiceModelStatus['state']): VoiceModelStatus =>
|
|
({
|
|
modelId: 'fixture',
|
|
version: '1',
|
|
state,
|
|
downloadedBytes: 1,
|
|
totalBytes: 1,
|
|
progress: 1,
|
|
platform: 'win32',
|
|
architecture: 'x64',
|
|
supported: true
|
|
}) as VoiceModelStatus
|
|
|
|
const voice = (id: string, localId: number, transcript?: string): Message => ({
|
|
id,
|
|
from: 'member',
|
|
type: '语音',
|
|
datetime: '2026-08-10 10:00:00',
|
|
content: '[语音]',
|
|
isSender: false,
|
|
sessionId: 'session',
|
|
localId,
|
|
createTime: 1_786_320_000,
|
|
contentData: { type: 'voice', duration: 2 },
|
|
voiceTranscript: transcript
|
|
})
|
|
|
|
describe('daily report voice transcription', () => {
|
|
it('creates a local voice reference from a parsed message', () => {
|
|
expect(toVoiceMessageReference(voice('voice-1', 7))).toEqual({
|
|
sessionId: 'session',
|
|
localId: 7,
|
|
createTime: 1_786_320_000,
|
|
svrId: undefined
|
|
})
|
|
})
|
|
|
|
it('reuses cached text and reports success/failure progress', async () => {
|
|
const recognize = vi
|
|
.fn()
|
|
.mockResolvedValueOnce({ success: true, transcript: '新转写内容' })
|
|
.mockResolvedValueOnce({ success: false, error: '音频缺失' })
|
|
const onProgress = vi.fn<(progress: VoiceTranscriptionProgress) => void>()
|
|
const result = await transcribeVoiceMessages(
|
|
[voice('cached', 1, '缓存内容'), voice('fresh', 2), voice('failed', 3)],
|
|
{
|
|
getModelStatus: vi.fn(async () => status('ready')),
|
|
recognize,
|
|
onProgress
|
|
}
|
|
)
|
|
|
|
expect(result.map((message) => message.voiceTranscript)).toEqual([
|
|
'缓存内容',
|
|
'新转写内容',
|
|
undefined
|
|
])
|
|
expect(result[2].voiceTranscriptError).toBe('音频缺失')
|
|
expect(recognize).toHaveBeenCalledTimes(2)
|
|
expect(onProgress).toHaveBeenLastCalledWith({
|
|
processed: 3,
|
|
total: 3,
|
|
succeeded: 2,
|
|
failed: 1
|
|
})
|
|
})
|
|
|
|
it('does not require the model when every transcript is cached', async () => {
|
|
const getModelStatus = vi.fn(async () => status('missing'))
|
|
const recognize = vi.fn()
|
|
const result = await transcribeVoiceMessages([voice('cached', 1, '已有文本')], {
|
|
getModelStatus,
|
|
recognize,
|
|
onProgress: vi.fn()
|
|
})
|
|
|
|
expect(result[0].voiceTranscript).toBe('已有文本')
|
|
expect(getModelStatus).not.toHaveBeenCalled()
|
|
expect(recognize).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('stops before recognition when the local model is not ready', async () => {
|
|
const recognize = vi.fn()
|
|
await expect(
|
|
transcribeVoiceMessages([voice('pending', 1)], {
|
|
getModelStatus: vi.fn(async () => status('missing')),
|
|
recognize,
|
|
onProgress: vi.fn()
|
|
})
|
|
).rejects.toThrow('准备离线语音识别模型')
|
|
expect(recognize).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('counts a voice message with incomplete local identifiers as failed', async () => {
|
|
const incomplete = { ...voice('incomplete', 1), sessionId: undefined }
|
|
const onProgress = vi.fn<(progress: VoiceTranscriptionProgress) => void>()
|
|
const result = await transcribeVoiceMessages([incomplete], {
|
|
getModelStatus: vi.fn(async () => status('ready')),
|
|
recognize: vi.fn(),
|
|
onProgress
|
|
})
|
|
|
|
expect(result[0].voiceTranscriptError).toContain('标识不完整')
|
|
expect(onProgress).toHaveBeenLastCalledWith({
|
|
processed: 1,
|
|
total: 1,
|
|
succeeded: 0,
|
|
failed: 1
|
|
})
|
|
})
|
|
})
|