test(agents): add validation tests for category and display fields

Added comprehensive unit and API tests to validate AgentType category and display fields:
- Category validation for valid, null, and invalid values
- Icon, color, and sort_order field constraints
- Typical tasks and collaboration hints handling (stripping, removing empty strings, normalization)
- New API tests for field creation, filtering, updating, and grouping
This commit is contained in:
2026-01-06 17:19:21 +01:00
parent f262d08be2
commit a0ec5fa2cc
3 changed files with 552 additions and 0 deletions

View File

@@ -316,3 +316,325 @@ class TestAgentTypeJsonFields:
)
assert agent_type.fallback_models == models
class TestAgentTypeCategoryFieldsValidation:
"""Tests for AgentType category and display field validation."""
def test_valid_category_values(self):
"""Test that all valid category values are accepted."""
valid_categories = [
"development",
"design",
"quality",
"operations",
"ai_ml",
"data",
"leadership",
"domain_expert",
]
for category in valid_categories:
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
category=category,
)
assert agent_type.category.value == category
def test_category_null_allowed(self):
"""Test that null category is allowed."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
category=None,
)
assert agent_type.category is None
def test_invalid_category_rejected(self):
"""Test that invalid category values are rejected."""
with pytest.raises(ValidationError):
AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
category="invalid_category",
)
def test_valid_hex_color(self):
"""Test that valid hex colors are accepted."""
valid_colors = ["#3B82F6", "#EC4899", "#10B981", "#ffffff", "#000000"]
for color in valid_colors:
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
color=color,
)
assert agent_type.color == color
def test_invalid_hex_color_rejected(self):
"""Test that invalid hex colors are rejected."""
invalid_colors = [
"not-a-color",
"3B82F6", # Missing #
"#3B82F", # Too short
"#3B82F6A", # Too long
"#GGGGGG", # Invalid hex chars
"rgb(59, 130, 246)", # RGB format not supported
]
for color in invalid_colors:
with pytest.raises(ValidationError):
AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
color=color,
)
def test_color_null_allowed(self):
"""Test that null color is allowed."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
color=None,
)
assert agent_type.color is None
def test_sort_order_valid_range(self):
"""Test that valid sort_order values are accepted."""
for sort_order in [0, 1, 500, 1000]:
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
sort_order=sort_order,
)
assert agent_type.sort_order == sort_order
def test_sort_order_default_zero(self):
"""Test that sort_order defaults to 0."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
)
assert agent_type.sort_order == 0
def test_sort_order_negative_rejected(self):
"""Test that negative sort_order is rejected."""
with pytest.raises(ValidationError):
AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
sort_order=-1,
)
def test_sort_order_exceeds_max_rejected(self):
"""Test that sort_order > 1000 is rejected."""
with pytest.raises(ValidationError):
AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
sort_order=1001,
)
def test_icon_max_length(self):
"""Test that icon field respects max length."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
icon="x" * 50,
)
assert len(agent_type.icon) == 50
def test_icon_exceeds_max_length_rejected(self):
"""Test that icon exceeding max length is rejected."""
with pytest.raises(ValidationError):
AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
icon="x" * 51,
)
class TestAgentTypeTypicalTasksValidation:
"""Tests for typical_tasks field validation."""
def test_typical_tasks_list(self):
"""Test typical_tasks as a list."""
tasks = ["Write code", "Review PRs", "Debug issues"]
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
typical_tasks=tasks,
)
assert agent_type.typical_tasks == tasks
def test_typical_tasks_default_empty(self):
"""Test typical_tasks defaults to empty list."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
)
assert agent_type.typical_tasks == []
def test_typical_tasks_strips_whitespace(self):
"""Test that typical_tasks items are stripped."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
typical_tasks=[" Write code ", " Debug "],
)
assert agent_type.typical_tasks == ["Write code", "Debug"]
def test_typical_tasks_removes_empty_strings(self):
"""Test that empty strings are removed from typical_tasks."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
typical_tasks=["Write code", "", " ", "Debug"],
)
assert agent_type.typical_tasks == ["Write code", "Debug"]
class TestAgentTypeCollaborationHintsValidation:
"""Tests for collaboration_hints field validation."""
def test_collaboration_hints_list(self):
"""Test collaboration_hints as a list."""
hints = ["backend-engineer", "qa-engineer"]
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
collaboration_hints=hints,
)
assert agent_type.collaboration_hints == hints
def test_collaboration_hints_default_empty(self):
"""Test collaboration_hints defaults to empty list."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
)
assert agent_type.collaboration_hints == []
def test_collaboration_hints_normalized_lowercase(self):
"""Test that collaboration_hints are normalized to lowercase."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
collaboration_hints=["Backend-Engineer", "QA-ENGINEER"],
)
assert agent_type.collaboration_hints == ["backend-engineer", "qa-engineer"]
def test_collaboration_hints_strips_whitespace(self):
"""Test that collaboration_hints are stripped."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
collaboration_hints=[" backend-engineer ", " qa-engineer "],
)
assert agent_type.collaboration_hints == ["backend-engineer", "qa-engineer"]
def test_collaboration_hints_removes_empty_strings(self):
"""Test that empty strings are removed from collaboration_hints."""
agent_type = AgentTypeCreate(
name="Test Agent",
slug="test-agent",
personality_prompt="Test",
primary_model="claude-opus-4-5-20251101",
collaboration_hints=["backend-engineer", "", " ", "qa-engineer"],
)
assert agent_type.collaboration_hints == ["backend-engineer", "qa-engineer"]
class TestAgentTypeUpdateCategoryFields:
"""Tests for AgentTypeUpdate category and display fields."""
def test_update_category_field(self):
"""Test updating category field."""
update = AgentTypeUpdate(category="ai_ml")
assert update.category.value == "ai_ml"
def test_update_icon_field(self):
"""Test updating icon field."""
update = AgentTypeUpdate(icon="brain")
assert update.icon == "brain"
def test_update_color_field(self):
"""Test updating color field."""
update = AgentTypeUpdate(color="#8B5CF6")
assert update.color == "#8B5CF6"
def test_update_sort_order_field(self):
"""Test updating sort_order field."""
update = AgentTypeUpdate(sort_order=50)
assert update.sort_order == 50
def test_update_typical_tasks_field(self):
"""Test updating typical_tasks field."""
update = AgentTypeUpdate(typical_tasks=["New task"])
assert update.typical_tasks == ["New task"]
def test_update_typical_tasks_strips_whitespace(self):
"""Test that typical_tasks are stripped on update."""
update = AgentTypeUpdate(typical_tasks=[" New task "])
assert update.typical_tasks == ["New task"]
def test_update_collaboration_hints_field(self):
"""Test updating collaboration_hints field."""
update = AgentTypeUpdate(collaboration_hints=["new-collaborator"])
assert update.collaboration_hints == ["new-collaborator"]
def test_update_collaboration_hints_normalized(self):
"""Test that collaboration_hints are normalized on update."""
update = AgentTypeUpdate(collaboration_hints=[" New-Collaborator "])
assert update.collaboration_hints == ["new-collaborator"]
def test_update_invalid_color_rejected(self):
"""Test that invalid color is rejected on update."""
with pytest.raises(ValidationError):
AgentTypeUpdate(color="invalid")
def test_update_invalid_sort_order_rejected(self):
"""Test that invalid sort_order is rejected on update."""
with pytest.raises(ValidationError):
AgentTypeUpdate(sort_order=-1)