PBI-50 F5: cross-repo blocker test voor SPRINT_BATCH
- task_cross_repo blocker fires bij task.repo_url ≠ product.repo_url - happy path: tasks zonder repo_url-override of met match → één SPRINT_IMPLEMENTATION-job (niet per-task). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d41e01f2e6
commit
fdd0447aad
1 changed files with 100 additions and 0 deletions
|
|
@ -201,6 +201,106 @@ describe('startSprintRunAction — pre-flight blockers', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('startSprintRunAction — SPRINT_BATCH', () => {
|
||||
const SPRINT_BATCH = {
|
||||
...SPRINT_OK,
|
||||
product: {
|
||||
id: 'prod-1',
|
||||
pr_strategy: 'SPRINT_BATCH',
|
||||
repo_url: 'https://github.com/example/main',
|
||||
},
|
||||
}
|
||||
|
||||
it('blokkeert task met afwijkende repo_url', async () => {
|
||||
mockPrisma.sprint.findUnique.mockResolvedValue(SPRINT_BATCH)
|
||||
mockPrisma.sprintRun.findFirst.mockResolvedValue(null)
|
||||
mockPrisma.story.findMany.mockResolvedValue([
|
||||
{
|
||||
...STORY_OK,
|
||||
tasks: [
|
||||
{
|
||||
id: 'task-1',
|
||||
code: 'T-1',
|
||||
title: 'In main repo',
|
||||
priority: 1,
|
||||
sort_order: 1,
|
||||
implementation_plan: 'plan',
|
||||
repo_url: null,
|
||||
},
|
||||
{
|
||||
id: 'task-2',
|
||||
code: 'T-2',
|
||||
title: 'Cross-repo',
|
||||
priority: 1,
|
||||
sort_order: 2,
|
||||
implementation_plan: 'plan',
|
||||
repo_url: 'https://github.com/example/other',
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
mockPrisma.claudeQuestion.findMany.mockResolvedValue([])
|
||||
|
||||
const result = await startSprintRunAction({ sprint_id: 'sprint-1' })
|
||||
|
||||
expect(result).toMatchObject({ ok: false, error: 'PRE_FLIGHT_BLOCKED' })
|
||||
if (result.ok === false && 'blockers' in result) {
|
||||
expect(result.blockers).toContainEqual({
|
||||
type: 'task_cross_repo',
|
||||
id: 'task-2',
|
||||
label: 'T-2: Cross-repo',
|
||||
})
|
||||
}
|
||||
expect(mockPrisma.sprintRun.create).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('staat tasks toe wanneer repo_url leeg is of gelijk aan product.repo_url', async () => {
|
||||
mockPrisma.sprint.findUnique.mockResolvedValue(SPRINT_BATCH)
|
||||
mockPrisma.sprintRun.findFirst.mockResolvedValue(null)
|
||||
mockPrisma.story.findMany.mockResolvedValue([
|
||||
{
|
||||
...STORY_OK,
|
||||
tasks: [
|
||||
{
|
||||
id: 'task-1',
|
||||
code: 'T-1',
|
||||
title: 'No override',
|
||||
priority: 1,
|
||||
sort_order: 1,
|
||||
implementation_plan: 'plan',
|
||||
repo_url: null,
|
||||
},
|
||||
{
|
||||
id: 'task-2',
|
||||
code: 'T-2',
|
||||
title: 'Same repo',
|
||||
priority: 1,
|
||||
sort_order: 2,
|
||||
implementation_plan: 'plan',
|
||||
repo_url: 'https://github.com/example/main',
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
mockPrisma.claudeQuestion.findMany.mockResolvedValue([])
|
||||
mockPrisma.sprintRun.create.mockResolvedValue({ id: 'run-batch' })
|
||||
mockPrisma.claudeJob.create.mockResolvedValue({ id: 'job-sprint' })
|
||||
|
||||
const result = await startSprintRunAction({ sprint_id: 'sprint-1' })
|
||||
|
||||
expect(result).toMatchObject({ ok: true, sprint_run_id: 'run-batch' })
|
||||
// Eén SPRINT_IMPLEMENTATION-job, niet per-task
|
||||
expect(mockPrisma.claudeJob.create).toHaveBeenCalledTimes(1)
|
||||
expect(mockPrisma.claudeJob.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
kind: 'SPRINT_IMPLEMENTATION',
|
||||
sprint_run_id: 'run-batch',
|
||||
product_id: 'prod-1',
|
||||
}),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('startSprintRunAction — guards', () => {
|
||||
it('weigert wanneer Sprint niet ACTIVE is', async () => {
|
||||
mockPrisma.sprint.findUnique.mockResolvedValue({ ...SPRINT_OK, status: 'COMPLETED' })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue