Files
fast-next-template/backend/tests/schemas/syndarix/test_agent_instance_schemas.py
Felipe Cardoso 742ce4c9c8 fix: Comprehensive validation and bug fixes
Infrastructure:
- Add Redis and Celery workers to all docker-compose files
- Fix celery migration race condition in entrypoint.sh
- Add healthchecks and resource limits to dev compose
- Update .env.template with Redis/Celery variables

Backend Models & Schemas:
- Rename Sprint.completed_points to velocity (per requirements)
- Add AgentInstance.name as required field
- Rename Issue external tracker fields for consistency
- Add IssueSource and TrackerType enums
- Add Project.default_tracker_type field

Backend Fixes:
- Add Celery retry configuration with exponential backoff
- Remove unused sequence counter from EventBus
- Add mypy overrides for test dependencies
- Fix test file using wrong schema (UserUpdate -> dict)

Frontend Fixes:
- Fix memory leak in useProjectEvents (proper cleanup)
- Fix race condition with stale closure in reconnection
- Sync TokenWithUser type with regenerated API client
- Fix expires_in null handling in useAuth
- Clean up unused imports in prototype pages
- Add ESLint relaxed rules for prototype files

CI/CD:
- Add E2E testing stage with Testcontainers
- Add security scanning with Trivy and pip-audit
- Add dependency caching for faster builds

Tests:
- Update all tests to use renamed fields (velocity, name, etc.)
- Fix 14 schema test failures
- All 1500 tests pass with 91% coverage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 10:35:30 +01:00

266 lines
9.3 KiB
Python

# tests/schemas/syndarix/test_agent_instance_schemas.py
"""
Tests for AgentInstance schema validation.
"""
from decimal import Decimal
import pytest
from pydantic import ValidationError
from app.schemas.syndarix import (
AgentInstanceCreate,
AgentInstanceUpdate,
AgentStatus,
)
class TestAgentInstanceCreateValidation:
"""Tests for AgentInstanceCreate schema validation."""
def test_valid_agent_instance_create(self, valid_agent_instance_data):
"""Test creating agent instance with valid data."""
instance = AgentInstanceCreate(**valid_agent_instance_data)
assert instance.agent_type_id is not None
assert instance.project_id is not None
def test_agent_instance_create_defaults(self, valid_agent_instance_data):
"""Test that defaults are applied correctly."""
instance = AgentInstanceCreate(**valid_agent_instance_data)
assert instance.status == AgentStatus.IDLE
assert instance.current_task is None
assert instance.short_term_memory == {}
assert instance.long_term_memory_ref is None
assert instance.session_id is None
def test_agent_instance_create_with_all_fields(self, valid_uuid):
"""Test creating agent instance with all optional fields."""
instance = AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="WorkingAgent",
status=AgentStatus.WORKING,
current_task="Processing feature request",
short_term_memory={"context": "working"},
long_term_memory_ref="project-123/agent-456",
session_id="session-abc",
)
assert instance.status == AgentStatus.WORKING
assert instance.current_task == "Processing feature request"
assert instance.short_term_memory == {"context": "working"}
assert instance.long_term_memory_ref == "project-123/agent-456"
assert instance.session_id == "session-abc"
def test_agent_instance_create_agent_type_id_required(self, valid_uuid):
"""Test that agent_type_id is required."""
with pytest.raises(ValidationError) as exc_info:
AgentInstanceCreate(
project_id=valid_uuid,
name="TestAgent",
)
errors = exc_info.value.errors()
assert any("agent_type_id" in str(e).lower() for e in errors)
def test_agent_instance_create_project_id_required(self, valid_uuid):
"""Test that project_id is required."""
with pytest.raises(ValidationError) as exc_info:
AgentInstanceCreate(
agent_type_id=valid_uuid,
name="TestAgent",
)
errors = exc_info.value.errors()
assert any("project_id" in str(e).lower() for e in errors)
def test_agent_instance_create_name_required(self, valid_uuid):
"""Test that name is required."""
with pytest.raises(ValidationError) as exc_info:
AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
)
errors = exc_info.value.errors()
assert any("name" in str(e).lower() for e in errors)
class TestAgentInstanceUpdateValidation:
"""Tests for AgentInstanceUpdate schema validation."""
def test_agent_instance_update_partial(self):
"""Test updating only some fields."""
update = AgentInstanceUpdate(
status=AgentStatus.WORKING,
)
assert update.status == AgentStatus.WORKING
assert update.current_task is None
assert update.short_term_memory is None
def test_agent_instance_update_all_fields(self):
"""Test updating all fields."""
from datetime import UTC, datetime
now = datetime.now(UTC)
update = AgentInstanceUpdate(
status=AgentStatus.WORKING,
current_task="New task",
short_term_memory={"new": "context"},
long_term_memory_ref="new-ref",
session_id="new-session",
last_activity_at=now,
tasks_completed=5,
tokens_used=10000,
cost_incurred=Decimal("1.5000"),
)
assert update.status == AgentStatus.WORKING
assert update.current_task == "New task"
assert update.tasks_completed == 5
assert update.tokens_used == 10000
assert update.cost_incurred == Decimal("1.5000")
def test_agent_instance_update_tasks_completed_negative_fails(self):
"""Test that negative tasks_completed raises ValidationError."""
with pytest.raises(ValidationError) as exc_info:
AgentInstanceUpdate(tasks_completed=-1)
errors = exc_info.value.errors()
assert any("tasks_completed" in str(e).lower() for e in errors)
def test_agent_instance_update_tokens_used_negative_fails(self):
"""Test that negative tokens_used raises ValidationError."""
with pytest.raises(ValidationError) as exc_info:
AgentInstanceUpdate(tokens_used=-1)
errors = exc_info.value.errors()
assert any("tokens_used" in str(e).lower() for e in errors)
def test_agent_instance_update_cost_incurred_negative_fails(self):
"""Test that negative cost_incurred raises ValidationError."""
with pytest.raises(ValidationError) as exc_info:
AgentInstanceUpdate(cost_incurred=Decimal("-0.01"))
errors = exc_info.value.errors()
assert any("cost_incurred" in str(e).lower() for e in errors)
class TestAgentStatusEnum:
"""Tests for AgentStatus enum validation."""
def test_valid_agent_statuses(self, valid_uuid):
"""Test all valid agent statuses."""
for status in AgentStatus:
instance = AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name=f"Agent{status.value}",
status=status,
)
assert instance.status == status
def test_invalid_agent_status(self, valid_uuid):
"""Test that invalid agent status raises ValidationError."""
with pytest.raises(ValidationError):
AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="TestAgent",
status="invalid", # type: ignore
)
class TestAgentInstanceShortTermMemory:
"""Tests for AgentInstance short_term_memory validation."""
def test_short_term_memory_empty_dict(self, valid_uuid):
"""Test that empty short_term_memory is valid."""
instance = AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="TestAgent",
short_term_memory={},
)
assert instance.short_term_memory == {}
def test_short_term_memory_complex(self, valid_uuid):
"""Test complex short_term_memory structure."""
memory = {
"conversation_history": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there"},
],
"recent_files": ["file1.py", "file2.py"],
"decisions": {"key": "value"},
"context_tokens": 1024,
}
instance = AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="MemoryAgent",
short_term_memory=memory,
)
assert instance.short_term_memory == memory
class TestAgentInstanceStringFields:
"""Tests for AgentInstance string field validation."""
def test_long_term_memory_ref_max_length(self, valid_uuid):
"""Test long_term_memory_ref max length."""
long_ref = "a" * 500 # Max length is 500
instance = AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="TestAgent",
long_term_memory_ref=long_ref,
)
assert instance.long_term_memory_ref == long_ref
def test_long_term_memory_ref_too_long(self, valid_uuid):
"""Test that too long long_term_memory_ref raises ValidationError."""
too_long = "a" * 501
with pytest.raises(ValidationError) as exc_info:
AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="TestAgent",
long_term_memory_ref=too_long,
)
errors = exc_info.value.errors()
assert any("long_term_memory_ref" in str(e).lower() for e in errors)
def test_session_id_max_length(self, valid_uuid):
"""Test session_id max length."""
long_session = "a" * 255 # Max length is 255
instance = AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="TestAgent",
session_id=long_session,
)
assert instance.session_id == long_session
def test_session_id_too_long(self, valid_uuid):
"""Test that too long session_id raises ValidationError."""
too_long = "a" * 256
with pytest.raises(ValidationError) as exc_info:
AgentInstanceCreate(
agent_type_id=valid_uuid,
project_id=valid_uuid,
name="TestAgent",
session_id=too_long,
)
errors = exc_info.value.errors()
assert any("session_id" in str(e).lower() for e in errors)