Initial commit
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
"""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"
|
||||
Reference in New Issue
Block a user