fix(voice): restore failed transcription recovery

This commit is contained in:
zhangheng
2026-07-22 15:35:48 +08:00
parent c54f4214df
commit 146e78e335
15 changed files with 603 additions and 64 deletions

103
tests/voice-state.test.js Normal file
View File

@@ -0,0 +1,103 @@
const assert = require('node:assert/strict')
const test = require('node:test')
const {
getVoiceFailureHint,
getVoicePrimaryAction,
getVoicePrimaryActionText
} = require('../.test-dist/pages/feedback/voice-state.js')
const { runWithSessionRefresh } = require('../.test-dist/pages/feedback/voice-actions.js')
function session(overrides = {}) {
return {
id: 'session-1',
profileId: null,
feedbackDate: '2026-07-22',
content: '',
status: 'active',
lessonCount: 1,
totalDurationMs: 2800,
processingSegmentCount: 0,
failedSegmentCount: 0,
needsGeneration: false,
lessons: [],
createdAt: 0,
updatedAt: 0,
...overrides
}
}
test('failed segments take priority over processing and generation', () => {
const value = session({
failedSegmentCount: 2,
processingSegmentCount: 1,
needsGeneration: true
})
const action = getVoicePrimaryAction(value)
assert.equal(action, 'retry')
assert.equal(getVoicePrimaryActionText(action, value.failedSegmentCount), '重试转录2')
})
test('voice primary action follows retry, processing, then generation states', () => {
assert.equal(getVoicePrimaryAction(session({ failedSegmentCount: 1 })), 'retry')
assert.equal(getVoicePrimaryAction(session({ processingSegmentCount: 1 })), 'processing')
assert.equal(getVoicePrimaryAction(session({ needsGeneration: true })), 'generate')
})
test('no clear speech failures provide an actionable explanation', () => {
const value = session({
failedSegmentCount: 1,
lessons: [
{
segments: [
{
id: 'segment-1',
sequence: 1,
durationMs: 2800,
status: 'failed',
errorMessage: 'FunASR HTTP 422: no clear speech was recognized'
}
]
}
]
})
const hint = getVoiceFailureHint(value)
assert.match(hint, /录音过短、静音或环境噪声/)
assert.match(hint, /放弃后重新录制/)
})
test('session refresh runs after a failed API action', async () => {
const expected = new Error('generation rejected')
let refreshCount = 0
await assert.rejects(
runWithSessionRefresh(
async () => {
throw expected
},
async () => {
refreshCount += 1
}
),
expected
)
assert.equal(refreshCount, 1)
})
test('refresh failure does not replace the original API error', async () => {
const expected = new Error('generation rejected with request id')
await assert.rejects(
runWithSessionRefresh(
async () => {
throw expected
},
async () => {
throw new Error('refresh failed')
}
),
expected
)
})