feat: refine UI, improve UX, optimize the analysis pipeline, and add character standing positions
This commit is contained in:
49
tests/unit/helpers/recovery-probe.test.ts
Normal file
49
tests/unit/helpers/recovery-probe.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
recoveryProbeTestUtils,
|
||||
startRecoveryProbe,
|
||||
} from '@/lib/query/hooks/run-stream/recovery-probe'
|
||||
|
||||
describe('recovery probe', () => {
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
recoveryProbeTestUtils.clearSuccessfulProbeScopes()
|
||||
})
|
||||
|
||||
it('retries active run recovery when the first probe misses and a later probe finds a run', async () => {
|
||||
vi.useFakeTimers()
|
||||
|
||||
const resolveActiveRunId = vi
|
||||
.fn<({ projectId, storageScopeKey }: { projectId: string; storageScopeKey?: string }) => Promise<string | null>>()
|
||||
.mockResolvedValueOnce(null)
|
||||
.mockResolvedValueOnce('run-2')
|
||||
const onRecovered = vi.fn()
|
||||
|
||||
const cleanup = startRecoveryProbe({
|
||||
projectId: 'project-1',
|
||||
storageKey: 'scope:story-to-script:episode-1',
|
||||
storageScopeKey: 'episode-1',
|
||||
hasRunState: () => false,
|
||||
resolveActiveRunId,
|
||||
onRecovered,
|
||||
})
|
||||
|
||||
await vi.advanceTimersByTimeAsync(0)
|
||||
expect(resolveActiveRunId).toHaveBeenCalledTimes(1)
|
||||
expect(resolveActiveRunId).toHaveBeenLastCalledWith({
|
||||
projectId: 'project-1',
|
||||
storageScopeKey: 'episode-1',
|
||||
})
|
||||
expect(onRecovered).not.toHaveBeenCalled()
|
||||
|
||||
await vi.advanceTimersByTimeAsync(
|
||||
recoveryProbeTestUtils.PROBE_RETRY_INTERVAL_MS,
|
||||
)
|
||||
|
||||
expect(resolveActiveRunId).toHaveBeenCalledTimes(2)
|
||||
expect(onRecovered).toHaveBeenCalledTimes(1)
|
||||
expect(onRecovered).toHaveBeenCalledWith('run-2')
|
||||
|
||||
cleanup()
|
||||
})
|
||||
})
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { TASK_TYPE } from '@/lib/task/types'
|
||||
import { getTaskFlowMeta } from '@/lib/llm-observe/stage-pipeline'
|
||||
import { normalizeTaskPayload } from '@/lib/task/submitter'
|
||||
import { isActiveTaskStatus, normalizeTaskPayload, shouldAttachNewTaskToReusableRun } from '@/lib/task/submitter'
|
||||
|
||||
describe('task submitter helpers', () => {
|
||||
it('fills default flow metadata when payload misses flow fields', () => {
|
||||
@@ -56,4 +56,14 @@ describe('task submitter helpers', () => {
|
||||
expect(meta.flowStageTotal).toBe(7)
|
||||
expect(meta.flowStageTitle).toBe('Meta')
|
||||
})
|
||||
|
||||
it('reuses linked runs only while the existing task is still active', () => {
|
||||
expect(isActiveTaskStatus('queued')).toBe(true)
|
||||
expect(isActiveTaskStatus('processing')).toBe(true)
|
||||
expect(isActiveTaskStatus('completed')).toBe(false)
|
||||
expect(shouldAttachNewTaskToReusableRun('queued')).toBe(false)
|
||||
expect(shouldAttachNewTaskToReusableRun('processing')).toBe(false)
|
||||
expect(shouldAttachNewTaskToReusableRun('failed')).toBe(true)
|
||||
expect(shouldAttachNewTaskToReusableRun(null)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user