import { beforeEach, describe, expect, it, vi } from 'vitest' import { createRun } from '@/lib/run-runtime/service' import { submitTask } from '@/lib/task/submitter' import { TASK_STATUS, TASK_TYPE } from '@/lib/task/types' import { prisma } from '../helpers/prisma' import { resetBillingState } from '../helpers/db-reset' import { createTestUser } from '../helpers/billing-fixtures' const addTaskJobMock = vi.hoisted(() => vi.fn(async () => ({ id: 'mock-job' }))) const publishTaskEventMock = vi.hoisted(() => vi.fn(async () => ({}))) vi.mock('@/lib/task/queues', () => ({ addTaskJob: addTaskJobMock, })) vi.mock('@/lib/task/publisher', () => ({ publishTaskEvent: publishTaskEventMock, })) describe('regression - reusable active run reattach', () => { beforeEach(async () => { await resetBillingState() vi.clearAllMocks() process.env.BILLING_MODE = 'OFF' }) it('reattaches a new run-centric task to the existing active run when the linked task is already terminal', async () => { const user = await createTestUser() const failedTask = await prisma.task.create({ data: { userId: user.id, projectId: 'project-regression-run', episodeId: 'episode-regression-run', type: TASK_TYPE.SCRIPT_TO_STORYBOARD_RUN, targetType: 'NovelPromotionEpisode', targetId: 'episode-regression-run', status: TASK_STATUS.FAILED, errorCode: 'TEST_FAILED', errorMessage: 'old task already failed', payload: { episodeId: 'episode-regression-run', analysisModel: 'model-core', meta: { locale: 'zh' }, }, queuedAt: new Date(), finishedAt: new Date(), }, }) const run = await createRun({ userId: user.id, projectId: 'project-regression-run', episodeId: 'episode-regression-run', workflowType: TASK_TYPE.SCRIPT_TO_STORYBOARD_RUN, taskType: TASK_TYPE.SCRIPT_TO_STORYBOARD_RUN, taskId: failedTask.id, targetType: 'NovelPromotionEpisode', targetId: 'episode-regression-run', input: { episodeId: 'episode-regression-run', analysisModel: 'model-core', meta: { locale: 'zh' }, }, }) const result = await submitTask({ userId: user.id, locale: 'zh', projectId: 'project-regression-run', episodeId: 'episode-regression-run', type: TASK_TYPE.SCRIPT_TO_STORYBOARD_RUN, targetType: 'NovelPromotionEpisode', targetId: 'episode-regression-run', payload: { episodeId: 'episode-regression-run', analysisModel: 'model-core', }, dedupeKey: 'script_to_storyboard:episode-regression-run', }) expect(result.deduped).toBe(false) expect(result.runId).toBe(run.id) expect(result.taskId).not.toBe(failedTask.id) const refreshedRun = await prisma.graphRun.findUnique({ where: { id: run.id } }) const newTask = await prisma.task.findUnique({ where: { id: result.taskId } }) expect(refreshedRun?.taskId).toBe(result.taskId) expect(newTask?.status).toBe(TASK_STATUS.QUEUED) expect(newTask?.payload).toMatchObject({ runId: run.id, }) }) })