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.
This commit is contained in:
2026-09-17 19:56:52 +02:00
parent ed5680253e
commit 9e27fef78a
+66 -164
View File
@@ -465,41 +465,77 @@ class TestLeaveWishService:
) )
assert result.recurrence == recurrence assert result.recurrence == recurrence
async def test_create_rejects_invalid_recurrence( # Placeholder resolved to seeded_ids.personal_data_uuid at test time, since
self, # parametrize case values are collected before fixtures exist.
leave_wish_service: LeaveWishService, _MISSING_UUID = object()
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",
)
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, self,
leave_wish_service: LeaveWishService, leave_wish_service: LeaveWishService,
seeded_ids: SeededIds, seeded_ids: SeededIds,
overrides: dict[str, object],
match: str | None,
) -> None: ) -> None:
with pytest.raises(ValidationError, match="parent_mode"): kwargs = {**self._REJECTION_BASE_KWARGS, **overrides}
await leave_wish_service.create( if kwargs.get("parent_personal_data_uuid") is self._MISSING_UUID:
workspace_id=seeded_ids.workspace_id, kwargs["parent_personal_data_uuid"] = seeded_ids.personal_data_uuid
name="Wish",
window_start_month=1, with pytest.raises(ValidationError, match=match):
window_start_day=1, await leave_wish_service.create(workspace_id=seeded_ids.workspace_id, **kwargs)
window_end_month=1,
window_end_day=10,
target_weeks=1,
first_year=2027,
parent_mode="everyone",
)
async def test_create_specific_parent_mode_requires_uuid( async def test_create_specific_parent_mode_requires_uuid(
self, self,
@@ -540,25 +576,6 @@ class TestLeaveWishService:
assert result.parent_mode == "specific" assert result.parent_mode == "specific"
assert result.parent_personal_data_uuid == seeded_ids.personal_data_uuid 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) ------------------------------------------------ # -- window_mode (§10.1) ------------------------------------------------
async def test_create_defaults_to_fixed_window_mode( async def test_create_defaults_to_fixed_window_mode(
@@ -578,24 +595,6 @@ class TestLeaveWishService:
) )
assert result.window_mode == "fixed" 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( async def test_create_accepts_flexible_window_mode_with_wide_enough_bound(
self, self,
leave_wish_service: LeaveWishService, leave_wish_service: LeaveWishService,
@@ -615,27 +614,6 @@ class TestLeaveWishService:
) )
assert result.window_mode == "flexible" 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( async def test_update_can_switch_window_mode_to_flexible(
self, self,
leave_wish_service: LeaveWishService, leave_wish_service: LeaveWishService,
@@ -673,29 +651,6 @@ class TestLeaveWishService:
with pytest.raises(ValidationError, match="flexible"): with pytest.raises(ValidationError, match="flexible"):
await leave_wish_service.update(created.id, window_mode="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( async def test_create_accepts_leap_day(
self, self,
leave_wish_service: LeaveWishService, leave_wish_service: LeaveWishService,
@@ -752,24 +707,6 @@ class TestLeaveWishService:
assert result.target_days is None assert result.target_days is None
assert result.target_span_days() == 14 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( async def test_create_flexible_wish_sized_by_target_days_rejects_short_bound(
self, self,
leave_wish_service: LeaveWishService, 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) result = await leave_wish_service.update(leave_wish_id=created.id, _clear_target_days=True)
assert result.target_days is None 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( async def test_create_allows_last_year_equal_first_year(
self, self,
leave_wish_service: LeaveWishService, leave_wish_service: LeaveWishService,