229 lines
7.5 KiB
Python
229 lines
7.5 KiB
Python
"""Tests for the PlanningService (planned leave day planning).
|
|
|
|
Demonstrates service-layer testing with external service dependencies.
|
|
Aim for >=90% coverage on new code (ARCHITECTURE.md §10).
|
|
"""
|
|
|
|
from datetime import date
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
|
|
from app.services.planning_service import PlanningService
|
|
from app.utils.errors import NotFoundError, ValidationError
|
|
from tests.conftest import SeededIds
|
|
|
|
|
|
class TestPlanningService:
|
|
"""Test PlanningService business logic."""
|
|
|
|
async def test_add_planned_day_simple(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""Add a simple planned day (non-dubbeldag)."""
|
|
result = await planning_service.add_planned_day(
|
|
workspace_id=seeded_ids.workspace_id,
|
|
child_id=seeded_ids.child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
is_dubbeldag=False,
|
|
)
|
|
assert result.date == date(2026, 6, 15)
|
|
assert result.day_type == "vacation"
|
|
assert result.is_dubbeldag is False
|
|
|
|
async def test_add_double_booking_raises(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""Adding a second planned day on same date raises ValidationError."""
|
|
child_id = seeded_ids.child_id
|
|
|
|
await planning_service.add_planned_day(
|
|
workspace_id=seeded_ids.workspace_id,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
is_dubbeldag=False,
|
|
)
|
|
|
|
# Try to add another on same date
|
|
with pytest.raises(ValidationError, match="already exists"):
|
|
await planning_service.add_planned_day(
|
|
workspace_id=seeded_ids.workspace_id,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="lagsta",
|
|
is_dubbeldag=False,
|
|
)
|
|
|
|
async def test_remove_planned_day(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""Remove a planned day."""
|
|
created = await planning_service.add_planned_day(
|
|
workspace_id=seeded_ids.workspace_id,
|
|
child_id=seeded_ids.child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
)
|
|
|
|
await planning_service.remove_planned_day(created.id)
|
|
|
|
with pytest.raises(NotFoundError):
|
|
await planning_service.get(created.id)
|
|
|
|
async def test_remove_missing_raises(
|
|
self,
|
|
planning_service: PlanningService,
|
|
) -> None:
|
|
"""Removing a missing planned day raises NotFoundError."""
|
|
with pytest.raises(NotFoundError):
|
|
await planning_service.remove_planned_day(uuid4())
|
|
|
|
async def test_get_planned_day(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""Get a planned day by ID."""
|
|
created = await planning_service.add_planned_day(
|
|
workspace_id=seeded_ids.workspace_id,
|
|
child_id=seeded_ids.child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
)
|
|
|
|
fetched = await planning_service.get(created.id)
|
|
assert fetched.id == created.id
|
|
assert fetched.date == date(2026, 6, 15)
|
|
|
|
async def test_get_missing_raises(
|
|
self,
|
|
planning_service: PlanningService,
|
|
) -> None:
|
|
"""Getting a missing planned day raises NotFoundError."""
|
|
with pytest.raises(NotFoundError):
|
|
await planning_service.get(uuid4())
|
|
|
|
async def test_list_by_workspace(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""List all planned days in a workspace."""
|
|
ws = seeded_ids.workspace_id
|
|
child_id = seeded_ids.child_id
|
|
|
|
d1 = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
)
|
|
d2 = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 16),
|
|
day_type="vacation",
|
|
)
|
|
|
|
result = await planning_service.list_by_workspace(ws)
|
|
ids = {d.id for d in result}
|
|
assert d1.id in ids
|
|
assert d2.id in ids
|
|
|
|
async def test_list_by_date_range(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""List planned days within a date range."""
|
|
ws = seeded_ids.workspace_id
|
|
child_id = seeded_ids.child_id
|
|
|
|
d1 = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
)
|
|
d2 = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
date=date(2026, 6, 16),
|
|
day_type="vacation",
|
|
)
|
|
|
|
result = await planning_service.list_by_date_range(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
start_date=date(2026, 6, 15),
|
|
end_date=date(2026, 6, 16),
|
|
)
|
|
assert len(result) == 2
|
|
|
|
async def test_list_by_date_range_empty(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""Listing with no planned days in range returns empty."""
|
|
result = await planning_service.list_by_date_range(
|
|
workspace_id=seeded_ids.workspace_id,
|
|
child_id=uuid4(),
|
|
start_date=date(2026, 6, 15),
|
|
end_date=date(2026, 6, 16),
|
|
)
|
|
assert result == []
|
|
|
|
async def test_add_planned_day_different_day_types(
|
|
self,
|
|
planning_service: PlanningService,
|
|
seeded_ids: SeededIds,
|
|
) -> None:
|
|
"""Add planned days with different day types."""
|
|
ws = seeded_ids.workspace_id
|
|
child_id = seeded_ids.child_id
|
|
parent_uuid = seeded_ids.personal_data_uuid
|
|
|
|
vacation = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=parent_uuid,
|
|
date=date(2026, 6, 15),
|
|
day_type="vacation",
|
|
)
|
|
lagsta = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=parent_uuid,
|
|
date=date(2026, 6, 16),
|
|
day_type="lagsta",
|
|
)
|
|
sjuk = await planning_service.add_planned_day(
|
|
workspace_id=ws,
|
|
child_id=child_id,
|
|
parent_personal_data_uuid=parent_uuid,
|
|
date=date(2026, 6, 17),
|
|
day_type="sjukpenning",
|
|
)
|
|
|
|
assert vacation.day_type == "vacation"
|
|
assert lagsta.day_type == "lagsta"
|
|
assert sjuk.day_type == "sjukpenning"
|