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

@@ -745,3 +745,230 @@ class TestAgentTypeInstanceCount:
for agent_type in data["data"]:
assert "instance_count" in agent_type
assert isinstance(agent_type["instance_count"], int)
@pytest.mark.asyncio
class TestAgentTypeCategoryFields:
"""Tests for agent type category and display fields."""
async def test_create_agent_type_with_category_fields(
self, client, superuser_token
):
"""Test creating agent type with all category and display fields."""
unique_slug = f"category-type-{uuid.uuid4().hex[:8]}"
response = await client.post(
"/api/v1/agent-types",
json={
"name": "Categorized Agent Type",
"slug": unique_slug,
"description": "An agent type with category fields",
"expertise": ["python"],
"personality_prompt": "You are a helpful assistant.",
"primary_model": "claude-opus-4-5-20251101",
# Category and display fields
"category": "development",
"icon": "code",
"color": "#3B82F6",
"sort_order": 10,
"typical_tasks": ["Write code", "Review PRs"],
"collaboration_hints": ["backend-engineer", "qa-engineer"],
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
assert response.status_code == status.HTTP_201_CREATED
data = response.json()
assert data["category"] == "development"
assert data["icon"] == "code"
assert data["color"] == "#3B82F6"
assert data["sort_order"] == 10
assert data["typical_tasks"] == ["Write code", "Review PRs"]
assert data["collaboration_hints"] == ["backend-engineer", "qa-engineer"]
async def test_create_agent_type_with_nullable_category(
self, client, superuser_token
):
"""Test creating agent type with null category."""
unique_slug = f"null-category-{uuid.uuid4().hex[:8]}"
response = await client.post(
"/api/v1/agent-types",
json={
"name": "Uncategorized Agent",
"slug": unique_slug,
"expertise": ["general"],
"personality_prompt": "You are a helpful assistant.",
"primary_model": "claude-opus-4-5-20251101",
"category": None,
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
assert response.status_code == status.HTTP_201_CREATED
data = response.json()
assert data["category"] is None
async def test_create_agent_type_invalid_color_format(
self, client, superuser_token
):
"""Test that invalid color format is rejected."""
unique_slug = f"invalid-color-{uuid.uuid4().hex[:8]}"
response = await client.post(
"/api/v1/agent-types",
json={
"name": "Invalid Color Agent",
"slug": unique_slug,
"expertise": ["python"],
"personality_prompt": "You are a helpful assistant.",
"primary_model": "claude-opus-4-5-20251101",
"color": "not-a-hex-color",
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
async def test_create_agent_type_invalid_category(self, client, superuser_token):
"""Test that invalid category value is rejected."""
unique_slug = f"invalid-category-{uuid.uuid4().hex[:8]}"
response = await client.post(
"/api/v1/agent-types",
json={
"name": "Invalid Category Agent",
"slug": unique_slug,
"expertise": ["python"],
"personality_prompt": "You are a helpful assistant.",
"primary_model": "claude-opus-4-5-20251101",
"category": "not_a_valid_category",
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
async def test_update_agent_type_category_fields(
self, client, superuser_token, test_agent_type
):
"""Test updating category and display fields."""
agent_type_id = test_agent_type["id"]
response = await client.patch(
f"/api/v1/agent-types/{agent_type_id}",
json={
"category": "ai_ml",
"icon": "brain",
"color": "#8B5CF6",
"sort_order": 50,
"typical_tasks": ["Train models", "Analyze data"],
"collaboration_hints": ["data-scientist"],
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["category"] == "ai_ml"
assert data["icon"] == "brain"
assert data["color"] == "#8B5CF6"
assert data["sort_order"] == 50
assert data["typical_tasks"] == ["Train models", "Analyze data"]
assert data["collaboration_hints"] == ["data-scientist"]
@pytest.mark.asyncio
class TestAgentTypeCategoryFilter:
"""Tests for agent type category filtering."""
async def test_list_agent_types_filter_by_category(
self, client, superuser_token, user_token
):
"""Test filtering agent types by category."""
# Create agent types in different categories
for cat in ["development", "design"]:
unique_slug = f"filter-test-{cat}-{uuid.uuid4().hex[:8]}"
await client.post(
"/api/v1/agent-types",
json={
"name": f"Filter Test {cat.capitalize()}",
"slug": unique_slug,
"expertise": ["python"],
"personality_prompt": "Test prompt",
"primary_model": "claude-opus-4-5-20251101",
"category": cat,
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
# Filter by development category
response = await client.get(
"/api/v1/agent-types",
params={"category": "development"},
headers={"Authorization": f"Bearer {user_token}"},
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
# All returned types should have development category
for agent_type in data["data"]:
assert agent_type["category"] == "development"
@pytest.mark.asyncio
class TestAgentTypeGroupedEndpoint:
"""Tests for the grouped by category endpoint."""
async def test_list_agent_types_grouped(self, client, superuser_token, user_token):
"""Test getting agent types grouped by category."""
# Create agent types in different categories
categories = ["development", "design", "quality"]
for cat in categories:
unique_slug = f"grouped-test-{cat}-{uuid.uuid4().hex[:8]}"
await client.post(
"/api/v1/agent-types",
json={
"name": f"Grouped Test {cat.capitalize()}",
"slug": unique_slug,
"expertise": ["python"],
"personality_prompt": "Test prompt",
"primary_model": "claude-opus-4-5-20251101",
"category": cat,
"sort_order": 10,
},
headers={"Authorization": f"Bearer {superuser_token}"},
)
# Get grouped agent types
response = await client.get(
"/api/v1/agent-types/grouped",
headers={"Authorization": f"Bearer {user_token}"},
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
# Should be a dict with category keys
assert isinstance(data, dict)
# Check that at least one of our created categories exists
assert any(cat in data for cat in categories)
async def test_list_agent_types_grouped_filter_inactive(
self, client, superuser_token, user_token
):
"""Test grouped endpoint with is_active filter."""
response = await client.get(
"/api/v1/agent-types/grouped",
params={"is_active": False},
headers={"Authorization": f"Bearer {user_token}"},
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert isinstance(data, dict)
async def test_list_agent_types_grouped_unauthenticated(self, client):
"""Test that unauthenticated users cannot access grouped endpoint."""
response = await client.get("/api/v1/agent-types/grouped")
assert response.status_code == status.HTTP_401_UNAUTHORIZED