feat(ST-1112): wire story-promotion into saveTask and PATCH /api/tasks/:id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-30 00:22:58 +02:00
parent 8b779ccc0b
commit eb27079ba7
5 changed files with 188 additions and 28 deletions

View file

@ -11,10 +11,13 @@ vi.mock('@/lib/prisma', () => ({
},
story: {
findFirst: vi.fn(),
findUniqueOrThrow: vi.fn(),
update: vi.fn(),
},
task: {
findFirst: vi.fn(),
update: vi.fn(),
findMany: vi.fn(),
},
storyLog: {
create: vi.fn(),
@ -43,8 +46,16 @@ import { POST as postTodo } from '@/app/api/todos/route'
const mockPrisma = prisma as unknown as {
product: { findMany: ReturnType<typeof vi.fn>; findFirst: ReturnType<typeof vi.fn> }
sprint: { findFirst: ReturnType<typeof vi.fn> }
story: { findFirst: ReturnType<typeof vi.fn> }
task: { findFirst: ReturnType<typeof vi.fn>; update: ReturnType<typeof vi.fn> }
story: {
findFirst: ReturnType<typeof vi.fn>
findUniqueOrThrow: ReturnType<typeof vi.fn>
update: ReturnType<typeof vi.fn>
}
task: {
findFirst: ReturnType<typeof vi.fn>
update: ReturnType<typeof vi.fn>
findMany: ReturnType<typeof vi.fn>
}
storyLog: { create: ReturnType<typeof vi.fn> }
todo: { create: ReturnType<typeof vi.fn> }
$transaction: ReturnType<typeof vi.fn>
@ -85,6 +96,11 @@ function routeCtx(id: string) {
beforeEach(() => {
vi.clearAllMocks()
// Pass-through transaction so callers can `prisma.$transaction(async tx => ...)` in routes.
mockPrisma.$transaction.mockImplementation(async (run: unknown) => {
if (typeof run === 'function') return (run as (tx: typeof prisma) => Promise<unknown>)(prisma)
return run
})
})
// ─── GET /api/products ────────────────────────────────────────────────────────
@ -386,7 +402,15 @@ describe('PATCH /api/tasks/:id', () => {
id: 'task-1',
story: { product: { user_id: 'user-1' } },
})
mockPrisma.task.update.mockResolvedValue({ id: 'task-1', status: 'DONE' })
mockPrisma.task.update.mockResolvedValue({
id: 'task-1',
title: 'Task',
status: 'DONE',
story_id: 'story-1',
implementation_plan: null,
})
mockPrisma.task.findMany.mockResolvedValue([{ status: 'DONE' }])
mockPrisma.story.findUniqueOrThrow.mockResolvedValue({ status: 'DONE' })
const res = await patchTask(
makePatch('http://localhost/api/tasks/task-1', { status: 'done' }),