From 9e27fef78a4eb5cbe3739ecd56143ce353493303 Mon Sep 17 00:00:00 2001 From: Jacob Hagstedt Date: Thu, 17 Sep 2026 19:56:52 +0200 Subject: [PATCH] Fold the leave-wish rejection tests into one parametrised case Nine tests each rebuilt the same ten-line create call to vary one argument, which buried the rule every case was actually protecting. They are now one parametrised test over a shared base, with an id per case so a failure names the rule rather than an index. The count of assertions is unchanged: the month and day cases were already parametrised and are kept as separate entries rather than compressed, since losing a case to tidy the file would defeat the point. The tests asserting a successful create stay separate, because each checks a distinct resulting value rather than merely that nothing raised. --- .../tests/unit/test_leave_wish_repository.py | 230 +++++------------- 1 file changed, 66 insertions(+), 164 deletions(-) diff --git a/backend/tests/unit/test_leave_wish_repository.py b/backend/tests/unit/test_leave_wish_repository.py index 7c5c3ea..7f4868a 100644 --- a/backend/tests/unit/test_leave_wish_repository.py +++ b/backend/tests/unit/test_leave_wish_repository.py @@ -465,41 +465,77 @@ class TestLeaveWishService: ) assert result.recurrence == recurrence - async def test_create_rejects_invalid_recurrence( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - with pytest.raises(ValidationError, match="recurrence"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=1, - first_year=2027, - recurrence="monthly", - ) + # Placeholder resolved to seeded_ids.personal_data_uuid at test time, since + # parametrize case values are collected before fixtures exist. + _MISSING_UUID = object() - async def test_create_rejects_invalid_parent_mode( + _REJECTION_BASE_KWARGS: dict[str, object] = dict( + name="Wish", + window_start_month=1, + window_start_day=1, + window_end_month=1, + window_end_day=10, + target_weeks=1, + first_year=2027, + ) + + _REJECTION_CASES = [ + pytest.param({"recurrence": "monthly"}, "recurrence", id="invalid_recurrence"), + pytest.param({"parent_mode": "everyone"}, "parent_mode", id="invalid_parent_mode"), + pytest.param( + {"parent_mode": "either", "parent_personal_data_uuid": _MISSING_UUID}, + "parent_personal_data_uuid", + id="parent_uuid_forbidden_unless_specific", + ), + pytest.param({"window_mode": "whenever"}, "window_mode", id="invalid_window_mode"), + pytest.param( + { + "window_start_month": 3, + "window_start_day": 1, + "window_end_month": 3, + "window_end_day": 10, + "target_weeks": 2, + "window_mode": "flexible", + }, + "flexible", + id="flexible_bound_shorter_than_target_weeks", + ), + *[ + pytest.param( + { + "window_start_month": month, + "window_start_day": day, + "window_end_month": 6, + "window_end_day": 20, + }, + None, + id=f"invalid_month_day_{month}_{day}", + ) + for month, day in [(0, 15), (13, 15), (6, 0), (6, 32), (2, 30), (4, 31)] + ], + pytest.param({"target_days": 0}, "target_days", id="target_days_below_one"), + pytest.param({"target_weeks": 0}, "target_weeks", id="zero_target_weeks"), + pytest.param( + {"first_year": 2030, "last_year": 2029}, + "last_year", + id="last_year_before_first_year", + ), + ] + + @pytest.mark.parametrize("overrides,match", _REJECTION_CASES) + async def test_create_rejects_invalid_input( self, leave_wish_service: LeaveWishService, seeded_ids: SeededIds, + overrides: dict[str, object], + match: str | None, ) -> None: - with pytest.raises(ValidationError, match="parent_mode"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=1, - first_year=2027, - parent_mode="everyone", - ) + kwargs = {**self._REJECTION_BASE_KWARGS, **overrides} + if kwargs.get("parent_personal_data_uuid") is self._MISSING_UUID: + kwargs["parent_personal_data_uuid"] = seeded_ids.personal_data_uuid + + with pytest.raises(ValidationError, match=match): + await leave_wish_service.create(workspace_id=seeded_ids.workspace_id, **kwargs) async def test_create_specific_parent_mode_requires_uuid( self, @@ -540,25 +576,6 @@ class TestLeaveWishService: assert result.parent_mode == "specific" assert result.parent_personal_data_uuid == seeded_ids.personal_data_uuid - async def test_create_rejects_parent_uuid_when_not_specific( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - with pytest.raises(ValidationError, match="parent_personal_data_uuid"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=1, - first_year=2027, - parent_mode="either", - parent_personal_data_uuid=seeded_ids.personal_data_uuid, - ) - # -- window_mode (§10.1) ------------------------------------------------ async def test_create_defaults_to_fixed_window_mode( @@ -578,24 +595,6 @@ class TestLeaveWishService: ) assert result.window_mode == "fixed" - async def test_create_rejects_invalid_window_mode( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - with pytest.raises(ValidationError, match="window_mode"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=1, - first_year=2027, - window_mode="whenever", - ) - async def test_create_accepts_flexible_window_mode_with_wide_enough_bound( self, leave_wish_service: LeaveWishService, @@ -615,27 +614,6 @@ class TestLeaveWishService: ) assert result.window_mode == "flexible" - async def test_create_rejects_flexible_wish_whose_bound_is_shorter_than_target_weeks( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - # Bound = 2027-03-01 -> 2027-03-10 (10 days), target_weeks=2 (14 - # days) -- a legitimate future shortfall must not be silently - # accepted; this is a user-input error (§10.1). - with pytest.raises(ValidationError, match="flexible"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Vårlov", - window_start_month=3, - window_start_day=1, - window_end_month=3, - window_end_day=10, - target_weeks=2, - first_year=2027, - window_mode="flexible", - ) - async def test_update_can_switch_window_mode_to_flexible( self, leave_wish_service: LeaveWishService, @@ -673,29 +651,6 @@ class TestLeaveWishService: with pytest.raises(ValidationError, match="flexible"): await leave_wish_service.update(created.id, window_mode="flexible") - @pytest.mark.parametrize( - "month,day", - [(0, 15), (13, 15), (6, 0), (6, 32), (2, 30), (4, 31)], - ) - async def test_create_rejects_invalid_month_day( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - month: int, - day: int, - ) -> None: - with pytest.raises(ValidationError): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=month, - window_start_day=day, - window_end_month=6, - window_end_day=20, - target_weeks=1, - first_year=2027, - ) - async def test_create_accepts_leap_day( self, leave_wish_service: LeaveWishService, @@ -752,24 +707,6 @@ class TestLeaveWishService: assert result.target_days is None assert result.target_span_days() == 14 - async def test_create_rejects_target_days_below_one( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - with pytest.raises(ValidationError, match="target_days"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=1, - target_days=0, - first_year=2027, - ) - async def test_create_flexible_wish_sized_by_target_days_rejects_short_bound( self, leave_wish_service: LeaveWishService, @@ -837,41 +774,6 @@ class TestLeaveWishService: result = await leave_wish_service.update(leave_wish_id=created.id, _clear_target_days=True) assert result.target_days is None - async def test_create_rejects_zero_target_weeks( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - with pytest.raises(ValidationError, match="target_weeks"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=0, - first_year=2027, - ) - - async def test_create_rejects_last_year_before_first_year( - self, - leave_wish_service: LeaveWishService, - seeded_ids: SeededIds, - ) -> None: - with pytest.raises(ValidationError, match="last_year"): - await leave_wish_service.create( - workspace_id=seeded_ids.workspace_id, - name="Wish", - window_start_month=1, - window_start_day=1, - window_end_month=1, - window_end_day=10, - target_weeks=1, - first_year=2030, - last_year=2029, - ) - async def test_create_allows_last_year_equal_first_year( self, leave_wish_service: LeaveWishService,