from datetime import datetime, timedelta from calendar_out.freebusy import ( annotate_conflicts, check_conflicts, load_ics_busy, propose_times, ) from calendar_out.ics import events_to_ics from server.schema import ActionPlan, Event def _event_at(hour, minutes=60): start = (datetime.now() + timedelta(days=1)).replace( hour=hour, minute=0, second=0, microsecond=0 ) return Event(title="Lunch", start=start.isoformat(), end=(start + timedelta(minutes=minutes)).isoformat()) def _busy_overlapping(ev): start = datetime.fromisoformat(ev.start) clash = Event(title="Standup", start=start.isoformat(), end=(start + timedelta(minutes=30)).isoformat()) return load_ics_busy(events_to_ics([clash])) def test_overlap_detected_and_alternatives_proposed(): ev = _event_at(13) busy = _busy_overlapping(ev) conflicts = check_conflicts([ev], busy) assert conflicts and conflicts[0].severity == "overlap" alts = propose_times(ev, busy) assert alts # non-empty alternatives def test_clear_calendar_has_no_conflicts(): ev = _event_at(13) far = Event(title="Faraway", start=(datetime.fromisoformat(ev.start) + timedelta(days=10)).isoformat()) busy = load_ics_busy(events_to_ics([far])) assert check_conflicts([ev], busy) == [] def test_annotate_fills_plan(): ev = _event_at(13) plan = ActionPlan(events=[ev]) plan = annotate_conflicts(plan, _busy_overlapping(ev)) assert plan.conflicts and plan.proposed_times