Initial commit
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
"""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.entities.child import Child
|
||||
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)
|
||||
Reference in New Issue
Block a user