docs+tests(sort-order): update for code-binding order on stories/tasks

- Rewrite docs/patterns/sort-order.md: float-insertion PBI only; story/task
  sort_order = parseCodeNumber(code), never drag/membership mutated
- Update plan-to-pbi-flow.md: sort_order auto, sprint_id param, priority=label
- Update make-plan.md: priority=label, array order = execution order
- Update rest-contract.md: fix sprint-tasks ordering, remove reorder endpoint
- Add ADR-0011: code is bindende volgordesleutel voor stories/taken
- Regenerate docs/INDEX.md via npm run docs
- Remove reorderStoriesAction/reorderTasksAction mocks from backlog tests
- Remove dnd-kit mocks from task-panel test (panel no longer uses dnd)
- Extend materializeIdeaPlanAction test: assert sort_order=parseCodeNumber(code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scrum4Me Agent 2026-05-14 18:13:42 +02:00
parent 3a5aba2824
commit 3a7141114c
9 changed files with 150 additions and 76 deletions

View file

@ -25,18 +25,16 @@ Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, wri
// Mock server actions
vi.mock('@/actions/stories', () => ({
reorderStoriesAction: vi.fn().mockResolvedValue({ success: true }),
reorderPbisAction: vi.fn().mockResolvedValue({ success: true }),
updatePbiPriorityAction: vi.fn().mockResolvedValue({ success: true }),
}))
vi.mock('@/actions/pbis', () => ({ deletePbiAction: vi.fn().mockResolvedValue({ success: true }) }))
vi.mock('@/actions/tasks', () => ({ reorderTasksAction: vi.fn().mockResolvedValue({ success: true }) }))
vi.mock('@/actions/user-settings', () => ({
updateUserSettingsAction: vi.fn().mockResolvedValue({ success: true, settings: {} }),
}))
vi.mock('sonner', () => ({ toast: { error: vi.fn(), success: vi.fn() } }))
// Mock dnd-kit
// Mock dnd-kit (still needed for PBI panel which supports drag-and-drop)
vi.mock('@dnd-kit/core', () => ({
DndContext: ({ children }: { children: React.ReactNode }) => <>{children}</>,
PointerSensor: class {},

View file

@ -33,37 +33,8 @@ function setActiveStoryAndTasks(storyId: string | null, tasks: BacklogTask[] = [
const mockPush = vi.fn()
vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mockPush }) }))
// Mock reorderTasksAction
vi.mock('@/actions/tasks', () => ({ reorderTasksAction: vi.fn().mockResolvedValue({ success: true }) }))
vi.mock('sonner', () => ({ toast: { error: vi.fn(), success: vi.fn() } }))
// Mock dnd-kit to avoid jsdom drag complexity
vi.mock('@dnd-kit/core', () => ({
DndContext: ({ children }: { children: React.ReactNode }) => <>{children}</>,
PointerSensor: class {},
KeyboardSensor: class {},
useSensor: vi.fn(),
useSensors: vi.fn(() => []),
closestCenter: vi.fn(),
DragOverlay: () => null,
}))
vi.mock('@dnd-kit/sortable', () => ({
SortableContext: ({ children }: { children: React.ReactNode }) => <>{children}</>,
useSortable: () => ({
attributes: {}, listeners: {}, setNodeRef: vi.fn(),
transform: null, transition: undefined, isDragging: false,
}),
rectSortingStrategy: {},
sortableKeyboardCoordinates: {},
arrayMove: (arr: unknown[], from: number, to: number) => {
const next = [...arr]
next.splice(from, 1)
next.splice(to, 0, arr[from])
return next
},
}))
vi.mock('@dnd-kit/utilities', () => ({ CSS: { Transform: { toString: () => '' } } }))
import { TaskPanel } from '@/components/backlog/task-panel'
const PRODUCT_ID = 'prod-1'
@ -141,12 +112,4 @@ describe('TaskPanel', () => {
expect((btn as HTMLButtonElement).disabled).toBe(true)
})
it('cards have no drag listeners in demo mode (whole-card drag disabled)', () => {
setActiveStoryAndTasks(STORY_ID, TASKS)
// In demo mode, listeners ({} from useSortable mock) are not spread onto the card.
// The mock always returns empty listeners, so we just verify the cards render without error.
renderPanel(true)
expect(screen.getByText('Eerste taak')).toBeTruthy()
expect(screen.getByText('Tweede taak')).toBeTruthy()
})
})