"""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 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", ) 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"