diff --git a/shiftregister/app/tests.py b/shiftregister/app/tests.py index 7ce503c..b607e8b 100644 --- a/shiftregister/app/tests.py +++ b/shiftregister/app/tests.py @@ -1,3 +1,142 @@ from django.test import TestCase +from datetime import timedelta +from django.utils import timezone -# Create your tests here. +from .models import Helper, Room, Shift, ShiftRegistration + + +class ShiftOverlapTests(TestCase): + def setUp(self): + # Create a room + self.room = Room.objects.create( + name="Test Room", required_helpers=1, meeting_location="Test Location" + ) + + # Create a helper + self.helper = Helper.objects.create( + phone="+491234567890", name="Test Helper", number_validated=True + ) + + # Create a base shift for testing overlaps + self.base_shift = Shift.objects.create( + room=self.room, + start_at=timezone.now() + timedelta(hours=1), + duration=timedelta(hours=2), + required_helpers=1, + ) + + # Register the helper for the base shift + self.base_registration = ShiftRegistration.objects.create( + shift=self.base_shift, + helper=self.helper, + state=ShiftRegistration.RegState.REGISTERED, + ) + + def test_no_overlap_before(self): + """Test a shift that ends before the base shift starts""" + shift_before = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at - timedelta(hours=3), + duration=timedelta(hours=1), + required_helpers=1, + ) + self.assertIsNone(self.helper.has_overlapping_shift(shift_before)) + + def test_no_overlap_after(self): + """Test a shift that starts after the base shift ends""" + shift_after = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at + timedelta(hours=4), + duration=timedelta(hours=1), + required_helpers=1, + ) + self.assertIsNone(self.helper.has_overlapping_shift(shift_after)) + + def test_overlap_start(self): + """Test a shift that starts during the base shift""" + shift_overlap_start = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at + timedelta(hours=1), + duration=timedelta(hours=2), + required_helpers=1, + ) + self.assertIsNotNone(self.helper.has_overlapping_shift(shift_overlap_start)) + + def test_overlap_end(self): + """Test a shift that ends during the base shift""" + shift_overlap_end = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at - timedelta(hours=1), + duration=timedelta(hours=2), + required_helpers=1, + ) + self.assertIsNotNone(self.helper.has_overlapping_shift(shift_overlap_end)) + + def test_overlap_contained(self): + """Test a shift that is completely contained within the base shift""" + shift_contained = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at + timedelta(minutes=30), + duration=timedelta(hours=1), + required_helpers=1, + ) + self.assertIsNotNone(self.helper.has_overlapping_shift(shift_contained)) + + def test_overlap_contains(self): + """Test a shift that completely contains the base shift""" + shift_contains = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at - timedelta(hours=1), + duration=timedelta(hours=4), + required_helpers=1, + ) + self.assertIsNotNone(self.helper.has_overlapping_shift(shift_contains)) + + def test_exact_same_time(self): + """Test a shift that has exactly the same time as the base shift""" + shift_same_time = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at, + duration=self.base_shift.duration, + required_helpers=1, + ) + self.assertIsNotNone(self.helper.has_overlapping_shift(shift_same_time)) + + def test_deleted_shift_no_overlap(self): + """Test that deleted shifts are not considered for overlap""" + self.base_shift.deleted = True + self.base_shift.save() + + shift_same_time = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at, + duration=self.base_shift.duration, + required_helpers=1, + ) + self.assertIsNone(self.helper.has_overlapping_shift(shift_same_time)) + + def test_cancelled_registration_no_overlap(self): + """Test that cancelled registrations are not considered for overlap""" + self.base_registration.state = ShiftRegistration.RegState.CANCELED + self.base_registration.save() + + shift_same_time = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at, + duration=self.base_shift.duration, + required_helpers=1, + ) + self.assertIsNone(self.helper.has_overlapping_shift(shift_same_time)) + + def test_failed_registration_no_overlap(self): + """Test that failed registrations are not considered for overlap""" + self.base_registration.state = ShiftRegistration.RegState.FAILED + self.base_registration.save() + + shift_same_time = Shift.objects.create( + room=self.room, + start_at=self.base_shift.start_at, + duration=self.base_shift.duration, + required_helpers=1, + ) + self.assertIsNone(self.helper.has_overlapping_shift(shift_same_time))