Files
F-r-ldraledigplannerare/backend/tests/unit/test_child_service.py
T
2026-06-01 20:30:17 +02:00

268 lines
8.5 KiB
Python

"""Tests for the Child service.
Demonstrates service-layer testing patterns: test business logic, validation,
and error handling. Aim for >=90% coverage on new code (ARCHITECTURE.md §10).
"""
from datetime import date
from uuid import uuid4
import pytest
from app.services.child_service import ChildService
from app.utils.errors import NotFoundError, ValidationError
from tests.conftest import SeededIds
class TestChildService:
"""Test ChildService business logic."""
async def test_create_with_valid_inputs(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Create a child with valid inputs."""
result = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Alice",
birth_date=date(2024, 6, 15),
preschool_start_date=date(2027, 8, 1),
)
assert result.name == "Alice"
assert result.birth_date == date(2024, 6, 15)
assert result.preschool_start_date == date(2027, 8, 1)
async def test_create_without_preschool_start_date(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Create a child without preschool start date (optional)."""
result = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Bob",
birth_date=date(2024, 3, 10),
preschool_start_date=None,
)
assert result.name == "Bob"
assert result.preschool_start_date is None
async def test_create_with_preschool_before_birth_raises(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Creating with preschool_start_date <= birth_date raises ValidationError."""
with pytest.raises(ValidationError, match="preschool_start_date must be after birth_date"):
await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Charlie",
birth_date=date(2024, 6, 15),
preschool_start_date=date(2024, 6, 15),
)
async def test_create_with_preschool_same_date_raises(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Creating with preschool_start_date == birth_date raises ValidationError."""
with pytest.raises(ValidationError):
await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Charlie",
birth_date=date(2024, 6, 15),
preschool_start_date=date(2024, 6, 14),
)
async def test_get_existing_child(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Get an existing child by ID."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Diana",
birth_date=date(2025, 1, 1),
)
fetched = await child_service.get(created.id)
assert fetched.id == created.id
assert fetched.name == "Diana"
async def test_get_missing_child_raises(
self,
child_service: ChildService,
) -> None:
"""Getting a missing child raises NotFoundError."""
with pytest.raises(NotFoundError, match="not found"):
await child_service.get(uuid4())
async def test_list_by_workspace(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""List all children in a workspace."""
ws = seeded_ids.workspace_id
c1 = await child_service.create(
workspace_id=ws,
name="Child1",
birth_date=date(2024, 1, 1),
)
c2 = await child_service.create(
workspace_id=ws,
name="Child2",
birth_date=date(2024, 6, 1),
)
result = await child_service.list_by_workspace(ws)
assert len(result) >= 2
ids = {c.id for c in result}
assert c1.id in ids
assert c2.id in ids
async def test_list_by_workspace_empty(
self,
child_service: ChildService,
) -> None:
"""Listing children for workspace with none returns empty list."""
result = await child_service.list_by_workspace(uuid4())
assert result == []
async def test_update_name_only(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Update only the name."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Old Name",
birth_date=date(2024, 6, 15),
)
updated = await child_service.update(
child_id=created.id,
name="New Name",
)
assert updated.name == "New Name"
assert updated.birth_date == date(2024, 6, 15)
async def test_update_birth_date_only(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Update only the birth date."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Emma",
birth_date=date(2024, 6, 15),
)
updated = await child_service.update(
child_id=created.id,
birth_date=date(2024, 7, 20),
)
assert updated.name == "Emma"
assert updated.birth_date == date(2024, 7, 20)
async def test_update_add_preschool_date(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Add preschool start date to a child that didn't have one."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Frank",
birth_date=date(2024, 6, 15),
preschool_start_date=None,
)
updated = await child_service.update(
child_id=created.id,
preschool_start_date=date(2027, 8, 1),
)
assert updated.preschool_start_date == date(2027, 8, 1)
async def test_update_with_invalid_preschool_date_raises(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Updating with invalid preschool date raises ValidationError."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Grace",
birth_date=date(2024, 6, 15),
)
with pytest.raises(ValidationError):
await child_service.update(
child_id=created.id,
preschool_start_date=date(2024, 6, 15),
)
async def test_update_missing_child_raises(
self,
child_service: ChildService,
) -> None:
"""Updating a missing child raises NotFoundError."""
with pytest.raises(NotFoundError):
await child_service.update(
child_id=uuid4(),
name="Henry",
)
async def test_delete_existing_child(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Delete an existing child."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Iris",
birth_date=date(2024, 6, 15),
)
await child_service.delete(created.id)
with pytest.raises(NotFoundError):
await child_service.get(created.id)
async def test_delete_missing_child_raises(
self,
child_service: ChildService,
) -> None:
"""Deleting a missing child raises NotFoundError."""
with pytest.raises(NotFoundError):
await child_service.delete(uuid4())
async def test_update_multiple_fields(
self,
child_service: ChildService,
seeded_ids: SeededIds,
) -> None:
"""Update multiple fields at once."""
created = await child_service.create(
workspace_id=seeded_ids.workspace_id,
name="Jack",
birth_date=date(2024, 6, 15),
preschool_start_date=date(2027, 8, 1),
)
updated = await child_service.update(
child_id=created.id,
name="Jake",
birth_date=date(2024, 7, 1),
preschool_start_date=date(2027, 9, 1),
)
assert updated.name == "Jake"
assert updated.birth_date == date(2024, 7, 1)
assert updated.preschool_start_date == date(2027, 9, 1)