Cover the balance entry path and three unguarded rules
Entering a parent's Försäkringskassan balances had no tests at all, despite being how every number in the planner originates and despite it becoming the first thing a new user does. The scraper endpoints are pinned per test rather than read from the ambient configuration, because a local .env sets the flag opposite to the shipped default and a test that trusts it would pass here and fail in CI. Also covered: the hard expiry at twelve, whose rejection path nothing reached and whose boundary turns out to be inclusive; and the dubbeldagar count cap, which now drives past the limit and asserts the days beyond it fall back to a single parent. Two weak assertions were strengthened, including one that derived its expectation from the same response it was checking and so could not have failed on a shared error.
This commit is contained in:
@@ -12,6 +12,9 @@ property this test file cares about most.
|
||||
from datetime import date, datetime, timedelta
|
||||
from uuid import uuid4
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from app.config import settings
|
||||
from app.entities.leave_wish import LeaveWish
|
||||
from app.entities.parental_leave import ParentalLeaveFetch, TierData
|
||||
from app.entities.planned_leave import PlannedLeaveDay
|
||||
@@ -500,6 +503,135 @@ class TestApplyProposedDaysValidation:
|
||||
assert rows == []
|
||||
|
||||
|
||||
class TestApplyProposedDaysEligibleRange:
|
||||
"""`PlanningService._validate_eligible_range` (planning_service.py:748-775)
|
||||
rejects any planned day before the child's birth date or after
|
||||
`birth_date + LeaveRules.hard_expiry_age_years` (the Swedish 12-year hard
|
||||
expiry on FP days).
|
||||
|
||||
The upper bound is INCLUSIVE: the source only rejects `d.date >
|
||||
hard_expiry`, so the exact 12th-birthday date itself is still eligible
|
||||
-- confirmed by `test_hard_expiry_boundary_date_itself_is_inclusive_and_accepted`
|
||||
below, which would fail if that boundary were ever tightened to `>=`.
|
||||
|
||||
`seeded_ids`' child has a fixed `birth_date` of 2024-01-01
|
||||
(`tests/conftest.py`), which these tests rely on directly.
|
||||
"""
|
||||
|
||||
_BIRTH_DATE = date(2024, 1, 1)
|
||||
|
||||
async def test_day_after_the_hard_expiry_is_rejected(
|
||||
self,
|
||||
planning_service: PlanningService,
|
||||
planned_leave_repo: SQLitePlannedLeaveRepository,
|
||||
seeded_ids: SeededIds,
|
||||
) -> None:
|
||||
ws, child, parent = (
|
||||
seeded_ids.workspace_id,
|
||||
seeded_ids.child_id,
|
||||
seeded_ids.personal_data_uuid,
|
||||
)
|
||||
hard_expiry = self._BIRTH_DATE + relativedelta(years=settings.rules.hard_expiry_age_years)
|
||||
day_after = hard_expiry + timedelta(days=1)
|
||||
|
||||
result = await planning_service.apply_proposed_days(
|
||||
ws, [ProposedDayInput(day_after, parent, child, "sjukpenning")]
|
||||
)
|
||||
|
||||
assert result.accepted is False
|
||||
assert any(
|
||||
r.message_key == "planApply.rejection.outsideEligibleWindow" for r in result.rejections
|
||||
)
|
||||
rows = await planned_leave_repo.list(parent_personal_data_uuid=parent)
|
||||
assert rows == []
|
||||
|
||||
async def test_day_before_the_birth_date_is_rejected(
|
||||
self,
|
||||
planning_service: PlanningService,
|
||||
planned_leave_repo: SQLitePlannedLeaveRepository,
|
||||
seeded_ids: SeededIds,
|
||||
) -> None:
|
||||
ws, child, parent = (
|
||||
seeded_ids.workspace_id,
|
||||
seeded_ids.child_id,
|
||||
seeded_ids.personal_data_uuid,
|
||||
)
|
||||
day_before = self._BIRTH_DATE - timedelta(days=1)
|
||||
|
||||
result = await planning_service.apply_proposed_days(
|
||||
ws, [ProposedDayInput(day_before, parent, child, "sjukpenning")]
|
||||
)
|
||||
|
||||
assert result.accepted is False
|
||||
assert any(
|
||||
r.message_key == "planApply.rejection.outsideEligibleWindow" for r in result.rejections
|
||||
)
|
||||
rows = await planned_leave_repo.list(parent_personal_data_uuid=parent)
|
||||
assert rows == []
|
||||
|
||||
async def test_hard_expiry_boundary_date_itself_is_inclusive_and_accepted(
|
||||
self,
|
||||
planning_service: PlanningService,
|
||||
seeded_ids: SeededIds,
|
||||
) -> None:
|
||||
"""The 12th-birthday date exactly equal to `birth_date +
|
||||
hard_expiry_age_years` is still an eligible day -- the source rejects
|
||||
strictly-greater dates only, so this is the INCLUSIVE boundary."""
|
||||
ws, child, parent = (
|
||||
seeded_ids.workspace_id,
|
||||
seeded_ids.child_id,
|
||||
seeded_ids.personal_data_uuid,
|
||||
)
|
||||
hard_expiry = self._BIRTH_DATE + relativedelta(years=settings.rules.hard_expiry_age_years)
|
||||
|
||||
result = await planning_service.apply_proposed_days(
|
||||
ws, [ProposedDayInput(hard_expiry, parent, child, "sjukpenning")]
|
||||
)
|
||||
|
||||
assert result.accepted is True, result.rejections
|
||||
|
||||
async def test_birth_date_itself_is_inclusive_and_accepted(
|
||||
self,
|
||||
planning_service: PlanningService,
|
||||
seeded_ids: SeededIds,
|
||||
) -> None:
|
||||
ws, child, parent = (
|
||||
seeded_ids.workspace_id,
|
||||
seeded_ids.child_id,
|
||||
seeded_ids.personal_data_uuid,
|
||||
)
|
||||
|
||||
result = await planning_service.apply_proposed_days(
|
||||
ws, [ProposedDayInput(self._BIRTH_DATE, parent, child, "sjukpenning")]
|
||||
)
|
||||
|
||||
assert result.accepted is True, result.rejections
|
||||
|
||||
async def test_rejected_batch_writes_nothing_even_with_a_valid_day_included(
|
||||
self,
|
||||
planning_service: PlanningService,
|
||||
planned_leave_repo: SQLitePlannedLeaveRepository,
|
||||
seeded_ids: SeededIds,
|
||||
) -> None:
|
||||
"""All-or-nothing: one out-of-window day in the batch must sink the
|
||||
whole batch, including the otherwise-valid day alongside it."""
|
||||
ws, child, parent = (
|
||||
seeded_ids.workspace_id,
|
||||
seeded_ids.child_id,
|
||||
seeded_ids.personal_data_uuid,
|
||||
)
|
||||
hard_expiry = self._BIRTH_DATE + relativedelta(years=settings.rules.hard_expiry_age_years)
|
||||
day_after = hard_expiry + timedelta(days=1)
|
||||
valid_day = ProposedDayInput(date(2026, 6, 15), parent, child, "sjukpenning")
|
||||
invalid_day = ProposedDayInput(day_after, parent, child, "sjukpenning")
|
||||
|
||||
result = await planning_service.apply_proposed_days(ws, [valid_day, invalid_day])
|
||||
|
||||
assert result.accepted is False
|
||||
rows = await planned_leave_repo.list(parent_personal_data_uuid=parent)
|
||||
assert rows == []
|
||||
|
||||
|
||||
class TestApplyProposedDaysDeleteKeys:
|
||||
"""`delete_keys` folds explicit deletions into the same validated batch as
|
||||
|
||||
|
||||
Reference in New Issue
Block a user