import { describe, expect, it } from 'vitest' import { findConflicts, wouldConflict } from '@/lib/timetable/conflict' import { ArtistEngagementStatus, type Performance } from '@/types/timetable' function p(overrides: Partial = {}): Performance { return { id: 'p1', engagement_id: 'e1', event_id: 'ev1', stage_id: 's1', lane: 0, lane_resolved: 0, start_at: '2026-07-10T18:00:00.000Z', end_at: '2026-07-10T19:00:00.000Z', version: 0, notes: null, warnings: [], created_at: null, updated_at: null, deleted_at: null, ...overrides, } } describe('findConflicts', () => { it('flags two overlapping performances on the same lane', () => { const conflicts = findConflicts([ p({ id: 'a', start_at: '2026-07-10T18:00:00Z', end_at: '2026-07-10T19:00:00Z' }), p({ id: 'b', start_at: '2026-07-10T18:30:00Z', end_at: '2026-07-10T19:30:00Z' }), ]) expect(conflicts).toEqual(new Set(['a', 'b'])) }) it('endpoint-touching is NOT overlap', () => { const conflicts = findConflicts([ p({ id: 'a', start_at: '2026-07-10T18:00:00Z', end_at: '2026-07-10T19:00:00Z' }), p({ id: 'b', start_at: '2026-07-10T19:00:00Z', end_at: '2026-07-10T20:00:00Z' }), ]) expect(conflicts.size).toBe(0) }) it('different lanes on same stage = no conflict', () => { const conflicts = findConflicts([ p({ id: 'a', lane_resolved: 0 }), p({ id: 'b', lane_resolved: 1 }), ]) expect(conflicts.size).toBe(0) }) it('different stages = no conflict', () => { const conflicts = findConflicts([ p({ id: 'a', stage_id: 's1' }), p({ id: 'b', stage_id: 's2' }), ]) expect(conflicts.size).toBe(0) }) it('cancelled performances do not participate', () => { const cancelled = p({ id: 'c', engagement: { booking_status: { value: ArtistEngagementStatus.CANCELLED, label: 'Geannuleerd' }, } as Performance['engagement'], }) const conflicts = findConflicts([ p({ id: 'a' }), cancelled, ]) expect(conflicts.size).toBe(0) }) it('parked performances (stage_id null) do not participate', () => { const conflicts = findConflicts([ p({ id: 'a', stage_id: null }), p({ id: 'b' }), ]) expect(conflicts.size).toBe(0) }) }) describe('wouldConflict', () => { it('detects 1-pixel overlap', () => { const others = [p({ id: 'x', start_at: '2026-07-10T18:00:00Z', end_at: '2026-07-10T19:00:00Z' })] const result = wouldConflict({ id: 'new', stage_id: 's1', lane: 0, start_at: '2026-07-10T18:59:00Z', end_at: '2026-07-10T20:00:00Z', }, others) expect(result).toBe(true) }) it('returns false when candidate is parked', () => { const others = [p({ id: 'x' })] const result = wouldConflict({ id: 'new', stage_id: null, lane: 0, start_at: '2026-07-10T18:00:00Z', end_at: '2026-07-10T19:00:00Z', }, others) expect(result).toBe(false) }) })