from datetime import datetime import pytest from django.utils.timezone import make_aware from program.models import TimeSlot from program.services import generate_conflicts from program.tests.factories import TimeslotFactory pytestmark = pytest.mark.django_db def create_timeslot(once_schedule) -> None: """creates and saves a timeslot instance for a "once" schedule for 2024-05-21 16:00-18:00.""" TimeslotFactory.create( start=make_aware(datetime(2024, 5, 21, 16, 0)), end=make_aware(datetime(2024, 5, 21, 18, 0)), schedule=once_schedule, ) def build_timeslot(once_schedule, start: tuple[int, int], end: tuple[int, int]) -> TimeSlot: """builds and returns a timeslot object for a "once" schedule for 2020-05-21 `start`-`end`.""" start_hour, start_minute = start end_hour, end_minute = end return TimeslotFactory.build( start=make_aware(datetime(2024, 5, 21, start_hour, start_minute)), end=make_aware(datetime(2024, 5, 21, end_hour, end_minute)), schedule=once_schedule, ) def test_generate_conflicts_partially_overlapping_end(once_schedule): create_timeslot(once_schedule) # 16:00 - 18:00 # Partly overlapping timeslot: start before existing start, end before existing end timeslots = [build_timeslot(once_schedule, start=(15, 30), end=(17, 30))] conflicts = generate_conflicts(timeslots) assert "theirs-end" and "ours-end" in conflicts["projected"][0]["solution_choices"] def test_generate_conflicts_partially_overlapping_start(once_schedule): create_timeslot(once_schedule) # 16:00 - 18:00 # Partly overlapping timeslots: start after existing start, end after existing end timeslots = [build_timeslot(once_schedule, start=(16, 30), end=(18, 30))] conflicts = generate_conflicts(timeslots) assert "theirs-start" and "ours-start" in conflicts["projected"][0]["solution_choices"] def test_generate_conflicts_fully_overlapping_theirs(once_schedule): create_timeslot(once_schedule) # 16:00 - 18:00 # Fully overlapping timeslot: start before existing start, end after existing end timeslots = [build_timeslot(once_schedule, start=(15, 30), end=(18, 30))] conflicts = generate_conflicts(timeslots) assert ( "theirs-end" and "theirs-start" and "theirs-both" in conflicts["projected"][0]["solution_choices"] ) def test_generate_conflicts_fully_overlapping_ours(once_schedule): create_timeslot(once_schedule) # 16:00 - 18:00 # Fully overlapping: start after existing start, end before existing end timeslots = [build_timeslot(once_schedule, start=(16, 30), end=(17, 30))] conflicts = generate_conflicts(timeslots) assert ( "ours-end" and "ours-start" and "ours-both" in conflicts["projected"][0]["solution_choices"] ) def test_generate_conflicts_overlapping_ours_theirs(once_schedule): create_timeslot(once_schedule) # 16:00 - 18:00 # Fully overlapping: starts and ends are equal timeslots = [build_timeslot(once_schedule, start=(16, 0), end=(18, 0))] conflicts = generate_conflicts(timeslots) assert "ours" and "theirs" in conflicts["projected"][0]["solution_choices"]