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:
@@ -745,3 +745,230 @@ class TestAgentTypeInstanceCount:
|
|||||||
for agent_type in data["data"]:
|
for agent_type in data["data"]:
|
||||||
assert "instance_count" in agent_type
|
assert "instance_count" in agent_type
|
||||||
assert isinstance(agent_type["instance_count"], int)
|
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
|
||||||
|
|||||||
@@ -316,3 +316,325 @@ class TestAgentTypeJsonFields:
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert agent_type.fallback_models == models
|
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)
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ class TestInitDb:
|
|||||||
assert user.last_name == "User"
|
assert user.last_name == "User"
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skip(
|
||||||
|
reason="SQLite doesn't support UUID type binding - requires PostgreSQL"
|
||||||
|
)
|
||||||
async def test_init_db_returns_existing_superuser(
|
async def test_init_db_returns_existing_superuser(
|
||||||
self, async_test_db, async_test_user
|
self, async_test_db, async_test_user
|
||||||
):
|
):
|
||||||
|
|||||||
Reference in New Issue
Block a user