diff --git a/program/tests/test_services.py b/program/tests/test_services.py index bcb122eefb585c2bb30aca7b704014f0b8e9c2c3..cd16d96ace71c9820a8c15ffcd247ede573cc2b2 100644 --- a/program/tests/test_services.py +++ b/program/tests/test_services.py @@ -1,14 +1,20 @@ from datetime import datetime, timedelta import pytest +from rest_framework.exceptions import ValidationError from django.utils.timezone import make_aware -from program.models import TimeSlot -from program.services import generate_conflicts, generate_timeslots, make_conflicts +from program.models import ScheduleConflictError, TimeSlot +from program.services import ( + generate_conflicts, + generate_timeslots, + make_conflicts, + resolve_conflicts, +) from program.tests.factories import TimeslotFactory from program.tests.test_schedules import schedule_data from program.tests.test_schedules import url as schedule_url -from program.typing import ScheduleData +from program.typing import ScheduleCreateUpdateData, ScheduleData pytestmark = pytest.mark.django_db @@ -188,3 +194,107 @@ def test_make_conflicts_extend_weekly_schedule_collisions(admin_api_client, show assert len(projected["collisions"]) == 1 assert projected["error"] is None assert projected["solution_choices"] == {"ours", "theirs"} + + +def test_resolve_conflicts_no_same_day_start_and_end(show, weekly_schedule): + data = ScheduleCreateUpdateData( + schedule=ScheduleData( + end_time=weekly_schedule.end_time.strftime("%H:%M:%S"), + first_date=weekly_schedule.first_date.strftime("%Y-%m-%d"), + last_date=weekly_schedule.first_date.strftime("%Y-%m-%d"), + rrule_id=weekly_schedule.rrule_id, + show_id=show.id, + start_time=weekly_schedule.start_time.strftime("%H:%M:%S"), + ) + ) + + with pytest.raises(ValidationError, match="Start and end dates must not be the same."): + resolve_conflicts(data, None, show.pk) + + +def test_resolve_conflicts_no_start_after_end(show, weekly_schedule): + data = ScheduleCreateUpdateData( + schedule=ScheduleData( + end_time=weekly_schedule.start_time.strftime("%H:%M:%S"), + first_date=weekly_schedule.first_date.strftime("%Y-%m-%d"), + last_date=(weekly_schedule.first_date - timedelta(days=1)).strftime("%Y-%m-%d"), + rrule_id=weekly_schedule.rrule_id, + show_id=show.id, + start_time=weekly_schedule.end_time.strftime("%H:%M:%S"), + ) + ) + + with pytest.raises(ValidationError, match="End date mustn't be before start."): + resolve_conflicts(data, None, show.pk) + + +def test_resolve_conflicts_one_solution_per_conflict(admin_api_client, show, weekly_schedule): + admin_api_client.post(schedule_url(), data=schedule_data(weekly_schedule, show), format="json") + + data = ScheduleCreateUpdateData( + schedule=ScheduleData( + end_time=weekly_schedule.end_time.strftime("%H:%M:%S"), + first_date=weekly_schedule.first_date.strftime("%Y-%m-%d"), + rrule_id=weekly_schedule.rrule_id, + show_id=show.id, + start_time=weekly_schedule.start_time.strftime("%H:%M:%S"), + ) + ) + + with pytest.raises( + ScheduleConflictError, match="Numbers of conflicts and solutions don't match." + ): + resolve_conflicts(data, None, show.pk) + + +def test_resolve_conflicts_unresolved_conflicts(admin_api_client, show, once_schedule): + admin_api_client.post(schedule_url(), data=schedule_data(once_schedule, show), format="json") + + data = ScheduleCreateUpdateData( + schedule=ScheduleData( + end_time=once_schedule.end_time.strftime("%H:%M:%S"), + first_date=once_schedule.first_date.strftime("%Y-%m-%d"), + rrule_id=once_schedule.rrule_id, + show_id=show.id, + start_time=once_schedule.start_time.strftime("%H:%M:%S"), + ), + solutions={"": "ours"}, + ) + + with pytest.raises(ScheduleConflictError, match="Not all conflicts have been resolved."): + resolve_conflicts(data, None, show.pk) + + +def test_resolve_conflicts_dry_run(admin_api_client, show, weekly_schedule): + data = ScheduleCreateUpdateData( + schedule=ScheduleData( + dryrun=True, + end_time=weekly_schedule.end_time.strftime("%H:%M:%S"), + first_date=weekly_schedule.first_date.strftime("%Y-%m-%d"), + rrule_id=weekly_schedule.rrule_id, + show_id=show.id, + start_time=weekly_schedule.start_time.strftime("%H:%M:%S"), + ) + ) + + schedule = resolve_conflicts(data, None, show.pk) + + assert len(schedule["create"]) == 52 or 53 + assert schedule["update"] == [] + assert schedule["delete"] == [] + + +def test_resolve_conflicts_no_errors(show, weekly_schedule): + data = ScheduleCreateUpdateData( + schedule=ScheduleData( + end_time=weekly_schedule.end_time.strftime("%H:%M:%S"), + first_date=weekly_schedule.first_date.strftime("%Y-%m-%d"), + rrule_id=weekly_schedule.rrule_id, + show_id=show.id, + start_time=weekly_schedule.start_time.strftime("%H:%M:%S"), + ) + ) + + schedule = resolve_conflicts(data, None, show.pk) + + assert "errors" not in schedule