Files
roboco/tests/unit/api/test_schemas_prompter.py
T

213 lines
6.6 KiB
Python
Raw Normal View History

"""Unit tests for Prompter API schemas.
Covers schema validation for both the session-based and legacy schemas.
"""
from __future__ import annotations
from uuid import uuid4
import pytest
from pydantic import ValidationError as PydanticValidationError
from roboco.api.schemas.prompter import (
ChatMessage,
PrompterChatRequest,
PrompterDraftTask,
PrompterMessageRequest,
PrompterSessionCreateRequest,
TaskConfirmRequest,
)
# =============================================================================
# ChatMessage
# =============================================================================
def test_chat_message_valid_roles() -> None:
for role in ("user", "assistant", "system"):
msg = ChatMessage(role=role, content="Hello")
assert msg.role == role
def test_chat_message_invalid_role() -> None:
with pytest.raises(PydanticValidationError) as exc_info:
ChatMessage(role="admin", content="Hello")
assert "role must be one of" in str(exc_info.value)
def test_chat_message_empty_content() -> None:
with pytest.raises(PydanticValidationError):
ChatMessage(role="user", content="")
# =============================================================================
# PrompterSessionCreateRequest
# =============================================================================
def test_session_create_request_defaults() -> None:
req = PrompterSessionCreateRequest()
assert req.context == {}
def test_session_create_request_with_context() -> None:
req = PrompterSessionCreateRequest(context={"team": "backend"})
assert req.context == {"team": "backend"}
# =============================================================================
# PrompterMessageRequest
# =============================================================================
def test_message_request_valid() -> None:
req = PrompterMessageRequest(content="I need a feature")
assert req.content == "I need a feature"
assert req.context == {}
def test_message_request_empty_content() -> None:
with pytest.raises(PydanticValidationError):
PrompterMessageRequest(content="")
def test_message_request_with_context() -> None:
req = PrompterMessageRequest(content="Hello", context={"key": "value"})
assert req.context["key"] == "value"
# =============================================================================
# TaskConfirmRequest
# =============================================================================
def test_task_confirm_request_all_optional() -> None:
req = TaskConfirmRequest()
assert req.project_id is None
assert req.product_id is None
assert req.assigned_to is None
assert req.overrides == {}
def test_task_confirm_request_with_project() -> None:
pid = uuid4()
req = TaskConfirmRequest(project_id=pid)
assert req.project_id == pid
# =============================================================================
# PrompterDraftTask
# =============================================================================
def test_draft_task_valid() -> None:
draft = PrompterDraftTask(
title="Add login page",
description="Implement a secure login page with email and password",
acceptance_criteria=["User can log in"],
team="frontend",
task_type="code",
nature="technical",
estimated_complexity="medium",
)
assert draft.title == "Add login page"
assert draft.source == "prompter"
assert draft.confirmed_by_human is False
def test_draft_task_title_too_long() -> None:
with pytest.raises(PydanticValidationError):
PrompterDraftTask(
title="x" * 201,
description="Implement a secure login page with email and password",
acceptance_criteria=["User can log in"],
team="frontend",
task_type="code",
nature="technical",
estimated_complexity="medium",
)
def test_draft_task_description_too_short() -> None:
with pytest.raises(PydanticValidationError):
PrompterDraftTask(
title="Add login page",
description="short", # <20 chars
acceptance_criteria=["User can log in"],
team="frontend",
task_type="code",
nature="technical",
estimated_complexity="medium",
)
def test_draft_task_empty_acceptance_criteria() -> None:
with pytest.raises(PydanticValidationError):
PrompterDraftTask(
title="Add login page",
description="Implement a secure login page with email and password",
acceptance_criteria=[],
team="frontend",
task_type="code",
nature="technical",
estimated_complexity="medium",
)
def test_draft_task_invalid_team() -> None:
with pytest.raises(PydanticValidationError):
PrompterDraftTask(
title="Add login page",
description="Implement a secure login page with email and password",
acceptance_criteria=["User can log in"],
team="infra", # invalid
task_type="code",
nature="technical",
estimated_complexity="medium",
)
def test_draft_task_priority_bounds() -> None:
# Valid bounds
for p in (0, 1, 2, 3):
d = PrompterDraftTask(
title="Add login page",
description="Implement a secure login page with email and password",
acceptance_criteria=["User can log in"],
team="frontend",
task_type="code",
nature="technical",
estimated_complexity="medium",
priority=p,
)
assert d.priority == p
# Out of bounds
with pytest.raises(PydanticValidationError):
PrompterDraftTask(
title="Add login page",
description="Implement a secure login page with email and password",
acceptance_criteria=["User can log in"],
team="frontend",
task_type="code",
nature="technical",
estimated_complexity="medium",
priority=4,
)
# =============================================================================
# PrompterChatRequest (legacy)
# =============================================================================
def test_chat_request_requires_messages() -> None:
with pytest.raises(PydanticValidationError):
PrompterChatRequest(messages=[])
def test_chat_request_valid() -> None:
req = PrompterChatRequest(messages=[ChatMessage(role="user", content="Hello")])
assert len(req.messages) == 1
assert req.context == {}