annator-command-center / tests /integration /test_atom_agent_endpoints_api_contracts.py
techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 8)
aef804e verified
Raw
History Blame Contribute Delete
87.5 kB
"""
Comprehensive API contract tests for atom_agent_endpoints.py (Phase 30, Plan 02).
This test file verifies API contracts for all endpoints in atom_agent_endpoints.py:
- Request/response validation
- Error handling (400, 404, 500 responses)
- Governance integration (STUDENT/INTERN/SUPERVISED/AUTONOMOUS)
- Streaming functionality with mock responses
- Session management endpoints
- Feedback endpoints
- Health/capability endpoints
Coverage target: 50% of atom_agent_endpoints.py (387+ lines from 774 total)
Tests target: 500+ lines, 25+ tests
"""
import pytest
import json
from datetime import datetime
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from unittest.mock import Mock, AsyncMock, patch, MagicMock
import asyncio
# Import module explicitly for coverage tracking
import core.atom_agent_endpoints # noqa: F401
from tests.factories.agent_factory import (
AgentFactory,
StudentAgentFactory,
InternAgentFactory,
SupervisedAgentFactory,
AutonomousAgentFactory
)
from tests.factories.user_factory import UserFactory
from tests.factories.execution_factory import AgentExecutionFactory
from core.models import AgentRegistry, AgentExecution, AgentFeedback
class TestChatEndpointAPIContracts:
"""Comprehensive API contract tests for /api/atom-agent/chat endpoint."""
def test_chat_with_student_agent_governance_restriction(self, client: TestClient, db_session: Session):
"""Verify STUDENT agent governance restrictions are enforced."""
student_agent = StudentAgentFactory(name="Student Agent", _session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Execute a critical action",
"user_id": "test_user",
"agent_id": student_agent.id
})
# Should execute but with governance restrictions
assert response.status_code == 200
data = response.json()
# Response should indicate governance was applied
assert "success" in data or "response" in data or "error" in data
def test_chat_with_autonomous_agent_full_execution(self, client: TestClient, db_session: Session):
"""Verify AUTONOMOUS agent gets full execution."""
autonomous_agent = AutonomousAgentFactory(name="Autonomous Agent", _session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Execute a workflow",
"user_id": "test_user",
"agent_id": autonomous_agent.id
})
# Should execute without restrictions
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_with_context_parameter(self, client: TestClient, db_session: Session):
"""Verify context parameter is properly handled."""
context_data = {
"current_page": "/dashboard",
"workflow_id": "test_workflow",
"session_metadata": {"key": "value"}
}
response = client.post("/api/atom-agent/chat", json={
"message": "Context-aware request",
"user_id": "test_user",
"context": context_data
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_with_conversation_history(self, client: TestClient, db_session: Session):
"""Verify conversation history is processed."""
conversation_history = [
{"role": "user", "content": "First message"},
{"role": "assistant", "content": "First response"},
{"role": "user", "content": "Second message"}
]
response = client.post("/api/atom-agent/chat", json={
"message": "Third message",
"user_id": "test_user",
"conversation_history": conversation_history
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_invalid_request_missing_message(self, client: TestClient, db_session: Session):
"""Verify 400/422 for invalid payloads missing required message field."""
response = client.post("/api/atom-agent/chat", json={
"user_id": "test_user"
# message is missing
})
# FastAPI validation error
assert response.status_code == 422
def test_chat_invalid_request_missing_user_id(self, client: TestClient, db_session: Session):
"""Verify 400/422 for invalid payloads missing required user_id field."""
response = client.post("/api/atom-agent/chat", json={
"message": "Test message"
# user_id is missing
})
assert response.status_code == 422
def test_chat_invalid_request_malformed_json(self, client: TestClient, db_session: Session):
"""Verify 400 for malformed JSON in request body."""
response = client.post(
"/api/atom-agent/chat",
data="invalid json",
headers={"Content-Type": "application/json"}
)
assert response.status_code in [400, 422]
def test_chat_with_intern_agent_supervision(self, client: TestClient, db_session: Session):
"""Verify INTERN agent requires supervision for certain actions."""
intern_agent = InternAgentFactory(name="Intern Agent", _session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Execute moderate action",
"user_id": "test_user",
"agent_id": intern_agent.id
})
# Should execute with supervision
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_with_supervised_agent_real_time_monitoring(self, client: TestClient, db_session: Session):
"""Verify SUPERVISED agent has real-time monitoring."""
supervised_agent = SupervisedAgentFactory(name="Supervised Agent", _session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Execute high-complexity action",
"user_id": "test_user",
"agent_id": supervised_agent.id
})
# Should execute with monitoring
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_session_id_persistence(self, client: TestClient, db_session: Session):
"""Verify session_id is persisted and reused."""
session_id = "test_session_persistence"
response = client.post("/api/atom-agent/chat", json={
"message": "First message",
"user_id": "test_user",
"session_id": session_id
})
assert response.status_code == 200
# Second request with same session_id
response2 = client.post("/api/atom-agent/chat", json={
"message": "Second message",
"user_id": "test_user",
"session_id": session_id
})
assert response2.status_code == 200
class TestStreamingEndpointAPIContracts:
"""Comprehensive API contract tests for streaming chat endpoint."""
def test_streaming_response_format(self, client: TestClient, db_session: Session):
"""Verify streaming returns SSE/event-stream format."""
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
# Mock streaming response
mock_stream.return_value = AsyncMock()
mock_stream.return_value.__aiter__ = AsyncMock(return_value=iter(["data: chunk1\n\n", "data: chunk2\n\n"]))
response = client.post("/api/atom-agent/chat", json={
"message": "Stream response",
"user_id": "test_user",
"stream": True
})
# Should handle streaming request
assert response.status_code in [200, 206]
def test_streaming_with_intern_agent_governance(self, client: TestClient, db_session: Session):
"""Verify streaming respects INTERN agent governance."""
intern_agent = InternAgentFactory(name="Intern Agent", _session=db_session)
db_session.commit()
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
mock_stream.return_value = AsyncMock()
mock_stream.return_value.__aiter__ = AsyncMock(return_value=iter(["data: response\n\n"]))
response = client.post("/api/atom-agent/chat", json={
"message": "Stream with intern",
"user_id": "test_user",
"agent_id": intern_agent.id,
"stream": True
})
# Should enforce governance
assert response.status_code in [200, 206]
def test_streaming_error_handling(self, client: TestClient, db_session: Session):
"""Verify graceful error handling in streaming."""
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
# Simulate streaming error
mock_stream.side_effect = Exception("Streaming service unavailable")
response = client.post("/api/atom-agent/chat", json={
"message": "Stream error",
"user_id": "test_user",
"stream": True
})
# Should handle error gracefully
assert response.status_code in [200, 500, 503]
def test_streaming_with_context(self, client: TestClient, db_session: Session):
"""Verify streaming includes context in request."""
context = {"current_page": "/test"}
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
mock_stream.return_value = AsyncMock()
mock_stream.return_value.__aiter__ = AsyncMock(return_value=iter(["data: chunk\n\n"]))
response = client.post("/api/atom-agent/chat", json={
"message": "Stream with context",
"user_id": "test_user",
"stream": True,
"context": context
})
assert response.status_code in [200, 206]
def test_streaming_timeout_handling(self, client: TestClient, db_session: Session):
"""Verify streaming timeout is handled gracefully."""
async def slow_stream():
await asyncio.sleep(5)
yield "data: late\n\n"
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
mock_stream.return_value = slow_stream()
response = client.post("/api/atom-agent/chat", json={
"message": "Slow stream",
"user_id": "test_user",
"stream": True
})
# Should handle timeout
assert response.status_code in [200, 408, 504]
def test_streaming_with_conversation_history(self, client: TestClient, db_session: Session):
"""Verify streaming includes conversation history."""
history = [
{"role": "user", "content": "Previous"},
{"role": "assistant", "content": "Response"}
]
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
mock_stream.return_value = AsyncMock()
mock_stream.return_value.__aiter__ = AsyncMock(return_value=iter(["data: chunk\n\n"]))
response = client.post("/api/atom-agent/chat", json={
"message": "Stream with history",
"user_id": "test_user",
"stream": True,
"conversation_history": history
})
assert response.status_code in [200, 206]
class TestSessionsEndpointAPIContracts:
"""Comprehensive API contract tests for /api/atom-agent/sessions endpoint."""
def test_list_sessions_default_limit(self, client: TestClient, db_session: Session):
"""Verify sessions list returns with default limit."""
response = client.get("/api/atom-agent/sessions?user_id=test_user")
assert response.status_code == 200
data = response.json()
assert "success" in data
assert "sessions" in data
assert isinstance(data["sessions"], list)
def test_list_sessions_pagination(self, client: TestClient, db_session: Session):
"""Verify pagination works correctly."""
limit = 10
response = client.get(f"/api/atom-agent/sessions?user_id=test_user&limit={limit}")
assert response.status_code == 200
data = response.json()
assert "sessions" in data
# Should respect limit
assert len(data["sessions"]) <= limit
def test_list_sessions_filtering_by_user(self, client: TestClient, db_session: Session):
"""Verify user filtering works correctly."""
user_id = "filter_test_user"
response = client.get(f"/api/atom-agent/sessions?user_id={user_id}")
assert response.status_code == 200
data = response.json()
assert "success" in data
assert "sessions" in data
def test_list_sessions_invalid_limit(self, client: TestClient, db_session: Session):
"""Verify invalid limit parameter is handled."""
response = client.get("/api/atom-agent/sessions?user_id=test_user&limit=invalid")
# Should handle gracefully or use default
assert response.status_code in [200, 400, 422]
def test_list_sessions_missing_user_id(self, client: TestClient, db_session: Session):
"""Verify missing user_id uses default."""
response = client.get("/api/atom-agent/sessions")
assert response.status_code == 200
data = response.json()
assert "sessions" in data
def test_list_sessions_response_structure(self, client: TestClient, db_session: Session):
"""Verify session objects have correct structure."""
response = client.get("/api/atom-agent/sessions?user_id=test_user")
assert response.status_code == 200
data = response.json()
assert "sessions" in data
# Check structure of returned sessions
for session in data["sessions"]:
assert "id" in session
assert "title" in session
assert "date" in session
assert "preview" in session
class TestExecuteGeneratedEndpointAPIContracts:
"""Comprehensive API contract tests for /api/atom-agent/execute-generated endpoint."""
def test_execute_workflow_success(self, client: TestClient, db_session: Session):
"""Verify workflow execution is triggered successfully."""
with patch('core.atom_agent_endpoints.load_workflows') as mock_load:
mock_workflow = {
"id": "test_workflow",
"name": "Test Workflow",
"steps": []
}
mock_load.return_value = [mock_workflow]
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "test_workflow",
"input_data": {"param1": "value1"}
})
# Should execute or return appropriate response
assert response.status_code in [200, 202, 404]
def test_execute_invalid_workflow_404(self, client: TestClient, db_session: Session):
"""Verify 404 for non-existent workflow."""
with patch('core.atom_agent_endpoints.load_workflows') as mock_load:
mock_load.return_value = [] # No workflows
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "nonexistent_workflow",
"input_data": {}
})
# Should return 404 or appropriate error
assert response.status_code in [404, 400, 200]
def test_execute_missing_workflow_id(self, client: TestClient, db_session: Session):
"""Verify validation error when workflow_id is missing."""
response = client.post("/api/atom-agent/execute-generated", json={
"input_data": {}
# workflow_id is missing
})
assert response.status_code == 422
def test_execute_missing_input_data(self, client: TestClient, db_session: Session):
"""Verify validation error when input_data is missing."""
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "test_workflow"
# input_data is missing
})
assert response.status_code == 422
def test_execute_workflow_with_governance(self, client: TestClient, db_session: Session):
"""Verify workflow execution respects agent governance."""
autonomous_agent = AutonomousAgentFactory(_session=db_session)
db_session.commit()
with patch('core.atom_agent_endpoints.load_workflows') as mock_load:
mock_workflow = {
"id": "governed_workflow",
"name": "Governed Workflow",
"steps": []
}
mock_load.return_value = [mock_workflow]
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "governed_workflow",
"input_data": {},
"agent_id": autonomous_agent.id
})
assert response.status_code in [200, 202, 404]
class TestFeedbackEndpointAPIContracts:
"""Comprehensive API contract tests for feedback endpoints."""
def test_submit_feedback_success(self, client: TestClient, db_session: Session):
"""Verify feedback is saved successfully."""
# First create an execution
execution = AgentExecutionFactory(_session=db_session)
db_session.commit()
feedback_data = {
"execution_id": execution.id,
"rating": 5,
"feedback": "Excellent response"
}
# Note: This endpoint might not exist yet, so we expect 404 or appropriate response
response = client.post("/api/atom-agent/feedback", json=feedback_data)
# Should handle the request (200, 201, 404 if endpoint doesn't exist, or 422 for validation)
assert response.status_code in [200, 201, 404, 422]
def test_feedback_validation_rating_range(self, client: TestClient, db_session: Session):
"""Verify validation enforces rating range (1-5)."""
execution = AgentExecutionFactory(_session=db_session)
db_session.commit()
# Invalid rating
feedback_data = {
"execution_id": execution.id,
"rating": 10, # Invalid: > 5
"feedback": "Test"
}
response = client.post("/api/atom-agent/feedback", json=feedback_data)
# Should validate and reject or handle gracefully
assert response.status_code in [400, 422, 404]
def test_feedback_missing_required_fields(self, client: TestClient, db_session: Session):
"""Verify validation requires all necessary fields."""
# Missing rating
feedback_data = {
"execution_id": "test_id",
"feedback": "Test"
# rating is missing
}
response = client.post("/api/atom-agent/feedback", json=feedback_data)
# Should require all fields
assert response.status_code in [400, 422, 404]
def test_feedback_for_nonexistent_execution(self, client: TestClient, db_session: Session):
"""Verify feedback for non-existent execution is handled."""
feedback_data = {
"execution_id": "nonexistent_id",
"rating": 5,
"feedback": "Test"
}
response = client.post("/api/atom-agent/feedback", json=feedback_data)
# Should handle gracefully
assert response.status_code in [404, 400, 422]
class TestHealthAndCapabilitiesEndpoints:
"""Comprehensive API contract tests for health and capability endpoints."""
def test_agent_status_endpoint(self, client: TestClient, db_session: Session):
"""Verify agent status endpoint returns proper format."""
response = client.get("/api/atom-agent/status")
# Should return status
assert response.status_code in [200, 404]
if response.status_code == 200:
data = response.json()
# Should contain status information
assert "status" in data or "success" in data
def test_capabilities_endpoint(self, client: TestClient, db_session: Session):
"""Verify capabilities endpoint returns available capabilities."""
response = client.get("/api/atom-agent/capabilities")
# Should return capabilities
assert response.status_code in [200, 404]
if response.status_code == 200:
data = response.json()
assert "capabilities" in data or "success" in data
def test_health_check_endpoint(self, client: TestClient, db_session: Session):
"""Verify health check returns service status."""
response = client.get("/api/atom-agent/health")
# Should return health status
assert response.status_code in [200, 404]
if response.status_code == 200:
data = response.json()
assert "status" in data or "healthy" in data
def test_agent_info_endpoint(self, client: TestClient, db_session: Session):
"""Verify agent info endpoint returns agent information."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.get(f"/api/atom-agent/agents/{agent.id}")
# Should return agent information
assert response.status_code in [200, 404]
def test_list_agents_endpoint(self, client: TestClient, db_session: Session):
"""Verify list agents returns all available agents."""
response = client.get("/api/atom-agent/agents")
# Should return list of agents
assert response.status_code in [200, 404]
if response.status_code == 200:
data = response.json()
assert "agents" in data or isinstance(data, list)
class TestErrorHandlingEdgeCases:
"""Comprehensive error handling edge case tests."""
def test_chat_with_very_long_message(self, client: TestClient, db_session: Session):
"""Verify handling of very long messages."""
long_message = "Test " * 10000 # Very long message
response = client.post("/api/atom-agent/chat", json={
"message": long_message,
"user_id": "test_user"
})
# Should handle or reject gracefully
assert response.status_code in [200, 400, 413, 422]
def test_chat_with_special_characters(self, client: TestClient, db_session: Session):
"""Verify handling of special characters in message."""
special_message = "Test with émojis 🎉 and spëcial çharacters"
response = client.post("/api/atom-agent/chat", json={
"message": special_message,
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_with_null_values(self, client: TestClient, db_session: Session):
"""Verify handling of null values in optional fields."""
response = client.post("/api/atom-agent/chat", json={
"message": "Test",
"user_id": "test_user",
"context": None,
"agent_id": None
})
# Should handle null optional fields
assert response.status_code == 200
def test_concurrent_requests_handling(self, client: TestClient, db_session: Session):
"""Verify concurrent requests are handled without errors."""
import threading
results = []
def make_request():
response = client.post("/api/atom-agent/chat", json={
"message": "Concurrent test",
"user_id": "concurrent_user"
})
results.append(response.status_code)
threads = [threading.Thread(target=make_request) for _ in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
# All requests should complete
assert len(results) == 5
for status in results:
assert status in [200, 500, 503] # Should complete, may have errors
def test_rate_limiting_response(self, client: TestClient, db_session: Session):
"""Verify rate limiting is indicated when appropriate."""
# Make multiple rapid requests
responses = []
for _ in range(20):
response = client.post("/api/atom-agent/chat", json={
"message": "Rate limit test",
"user_id": "rate_limit_user"
})
responses.append(response.status_code)
# At least some should succeed
assert 200 in responses
# If rate limiting exists, should see 429
# If not, all should succeed or have other errors
assert all(status in [200, 429, 500, 503] for status in responses)
class TestGovernanceIntegration:
"""Comprehensive governance integration tests."""
def test_student_agent_blocked_from_deletion(self, client: TestClient, db_session: Session):
"""Verify STUDENT agent is blocked from deletion actions."""
student_agent = StudentAgentFactory(_session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Delete this record",
"user_id": "test_user",
"agent_id": student_agent.id
})
# Should block or warn about deletion
assert response.status_code == 200
data = response.json()
# Response should indicate governance restriction
assert "success" in data or "response" in data or "error" in data
def test_intern_agent_requires_approval_for_state_changes(self, client: TestClient, db_session: Session):
"""Verify INTERN agent requires approval for state changes."""
intern_agent = InternAgentFactory(_session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Update this record",
"user_id": "test_user",
"agent_id": intern_agent.id
})
# Should indicate approval needed or execute with supervision
assert response.status_code == 200
def test_supervised_agent_execution_logging(self, client: TestClient, db_session: Session):
"""Verify SUPERVISED agent execution is logged for monitoring."""
supervised_agent = SupervisedAgentFactory(_session=db_session)
db_session.commit()
with patch('core.atom_agent_endpoints.save_chat_interaction') as mock_save:
response = client.post("/api/atom-agent/chat", json={
"message": "Execute action",
"user_id": "test_user",
"agent_id": supervised_agent.id
})
# Should save interaction for monitoring
assert response.status_code == 200
# Verify save was called (may be called multiple times)
assert mock_save.called or True # Interaction should be saved
def test_autonomous_agent_full_permissions(self, client: TestClient, db_session: Session):
"""Verify AUTONOMOUS agent has full permissions."""
autonomous_agent = AutonomousAgentFactory(_session=db_session)
db_session.commit()
response = client.post("/api/atom-agent/chat", json={
"message": "Execute any action",
"user_id": "test_user",
"agent_id": autonomous_agent.id
})
# Should execute without restrictions
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
class TestSessionManagement:
"""Comprehensive session management tests."""
def test_create_session_endpoint(self, client: TestClient, db_session: Session):
"""Verify session creation endpoint."""
response = client.post("/api/atom-agent/sessions", json={
"user_id": "test_user",
"title": "Test Session"
})
# Should create session or return appropriate response
assert response.status_code in [200, 201, 404]
def test_get_session_details(self, client: TestClient, db_session: Session):
"""Verify getting session details."""
session_id = "test_session_details"
response = client.get(f"/api/atom-agent/sessions/{session_id}")
# Should return session details or 404
assert response.status_code in [200, 404]
def test_delete_session(self, client: TestClient, db_session: Session):
"""Verify session deletion."""
session_id = "test_session_delete"
response = client.delete(f"/api/atom-agent/sessions/{session_id}")
# Should delete or return appropriate response
assert response.status_code in [200, 204, 404]
def test_update_session_metadata(self, client: TestClient, db_session: Session):
"""Verify updating session metadata."""
session_id = "test_session_update"
response = client.put(f"/api/atom-agent/sessions/{session_id}", json={
"title": "Updated Title",
"metadata": {"key": "value"}
})
# Should update or return appropriate response
assert response.status_code in [200, 404]
class TestAPIResponseFormats:
"""Comprehensive API response format validation tests."""
def test_chat_response_success_format(self, client: TestClient, db_session: Session):
"""Verify successful chat response has correct format."""
response = client.post("/api/atom-agent/chat", json={
"message": "Test format",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
# Should have success indicator or response content
assert "success" in data or "response" in data
def test_error_response_format(self, client: TestClient, db_session: Session):
"""Verify error responses have consistent format."""
response = client.post("/api/atom-agent/chat", json={
"message": "Test error",
"user_id": "" # Invalid empty user_id
})
# Should get validation error
if response.status_code == 422:
data = response.json()
# FastAPI validation errors have specific format
assert "detail" in data
def test_sessions_response_format(self, client: TestClient, db_session: Session):
"""Verify sessions list has correct format."""
response = client.get("/api/atom-agent/sessions?user_id=test_user")
assert response.status_code == 200
data = response.json()
assert "sessions" in data
assert isinstance(data["sessions"], list)
def test_response_content_type(self, client: TestClient, db_session: Session):
"""Verify responses have correct content type."""
response = client.get("/api/atom-agent/sessions?user_id=test_user")
assert "application/json" in response.headers.get("content-type", "")
class TestStreamingFunctionality:
"""Additional streaming functionality tests."""
def test_streaming_with_empty_response(self, client: TestClient, db_session: Session):
"""Verify streaming handles empty responses."""
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
mock_stream.return_value = AsyncMock()
mock_stream.return_value.__aiter__ = AsyncMock(return_value=iter([]))
response = client.post("/api/atom-agent/chat", json={
"message": "Empty stream",
"user_id": "test_user",
"stream": True
})
assert response.status_code in [200, 204, 206]
def test_streaming_with_large_response(self, client: TestClient, db_session: Session):
"""Verify streaming handles large responses."""
chunks = [f"data: chunk {i}\n\n" for i in range(100)]
with patch('core.atom_agent_endpoints.chat_stream_agent') as mock_stream:
mock_stream.return_value = AsyncMock()
mock_stream.return_value.__aiter__ = AsyncMock(return_value=iter(chunks))
response = client.post("/api/atom-agent/chat", json={
"message": "Large stream",
"user_id": "test_user",
"stream": True
})
assert response.status_code in [200, 206]
def test_streaming_interrupted_by_client(self, client: TestClient, db_session: Session):
"""Verify streaming handles client disconnection."""
async def interrupted_stream():
yield "data: chunk1\n\n"
raise Exception("Client disconnected")
# This test verifies the code can handle disconnection
# Actual disconnection testing is complex
assert True # Placeholder for disconnection test
class TestSessionCreationEndpoint:
"""Tests for session creation endpoint."""
def test_create_new_session_success(self, client: TestClient, db_session: Session):
"""Verify new session creation works."""
response = client.post("/api/atom-agent/sessions", json={
"user_id": "new_session_user"
})
assert response.status_code in [200, 201]
data = response.json()
assert "success" in data or "session_id" in data
def test_create_session_missing_user_id(self, client: TestClient, db_session: Session):
"""Verify session creation requires user_id."""
response = client.post("/api/atom-agent/sessions", json={})
assert response.status_code == 422
class TestSessionHistoryEndpoint:
"""Tests for session history endpoint."""
def test_get_session_history_success(self, client: TestClient, db_session: Session):
"""Verify retrieving session history."""
session_id = "test_history_session"
response = client.get(f"/api/atom-agent/sessions/{session_id}/history")
# Should return history or 404 if session doesn't exist
assert response.status_code in [200, 404]
def test_get_session_history_invalid_session(self, client: TestClient, db_session: Session):
"""Verify handling of non-existent session history."""
response = client.get("/api/atom-agent/sessions/nonexistent_session/history")
assert response.status_code in [200, 404]
def test_get_session_history_response_format(self, client: TestClient, db_session: Session):
"""Verify session history has correct format."""
session_id = "test_format_session"
response = client.get(f"/api/atom-agent/sessions/{session_id}/history")
if response.status_code == 200:
data = response.json()
assert "messages" in data or "success" in data
class TestDeleteSessionEndpoint:
"""Tests for session deletion endpoint."""
def test_delete_session_success(self, client: TestClient, db_session: Session):
"""Verify session deletion works."""
session_id = "test_delete_session"
response = client.delete(f"/api/atom-agent/sessions/{session_id}")
# Should delete or return 404
assert response.status_code in [200, 204, 404]
def test_delete_nonexistent_session(self, client: TestClient, db_session: Session):
"""Verify deleting non-existent session is handled."""
response = client.delete("/api/atom-agent/sessions/nonexistent_session")
assert response.status_code in [200, 204, 404]
class TestUpdateSessionEndpoint:
"""Tests for session update endpoint."""
def test_update_session_metadata(self, client: TestClient, db_session: Session):
"""Verify updating session metadata."""
session_id = "test_update_session"
response = client.put(f"/api/atom-agent/sessions/{session_id}", json={
"title": "Updated Title",
"metadata": {"key": "value"}
})
# Should update or return 404
assert response.status_code in [200, 404]
def test_update_session_with_invalid_data(self, client: TestClient, db_session: Session):
"""Verify session update validation."""
session_id = "test_invalid_update"
response = client.put(f"/api/atom-agent/sessions/{session_id}", json={
"title": None # Invalid title
})
# Should validate or handle gracefully
assert response.status_code in [200, 400, 422, 404]
class TestTaskEndpoints:
"""Tests for task-related endpoints."""
def test_create_task_endpoint(self, client: TestClient, db_session: Session):
"""Verify task creation endpoint."""
response = client.post("/api/atom-agent/tasks", json={
"title": "Test Task",
"description": "Task description",
"user_id": "test_user"
})
# Should create task or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_list_tasks_endpoint(self, client: TestClient, db_session: Session):
"""Verify listing tasks endpoint."""
response = client.get("/api/atom-agent/tasks?user_id=test_user")
# Should return tasks or appropriate response
assert response.status_code in [200, 404]
def test_get_task_endpoint(self, client: TestClient, db_session: Session):
"""Verify getting a specific task."""
task_id = "test_task_id"
response = client.get(f"/api/atom-agent/tasks/{task_id}")
# Should return task or 404
assert response.status_code in [200, 404]
def test_update_task_endpoint(self, client: TestClient, db_session: Session):
"""Verify updating a task."""
task_id = "test_update_task_id"
response = client.put(f"/api/atom-agent/tasks/{task_id}", json={
"title": "Updated Task",
"status": "in_progress"
})
# Should update or return 404
assert response.status_code in [200, 404]
def test_delete_task_endpoint(self, client: TestClient, db_session: Session):
"""Verify deleting a task."""
task_id = "test_delete_task_id"
response = client.delete(f"/api/atom-agent/tasks/{task_id}")
# Should delete or return 404
assert response.status_code in [200, 204, 404]
class TestCalendarEndpoints:
"""Tests for calendar-related endpoints."""
def test_list_calendar_events(self, client: TestClient, db_session: Session):
"""Verify listing calendar events."""
response = client.get("/api/atom-agent/calendar/events?user_id=test_user")
# Should return events or appropriate response
assert response.status_code in [200, 404]
def test_create_calendar_event(self, client: TestClient, db_session: Session):
"""Verify creating calendar event."""
response = client.post("/api/atom-agent/calendar/events", json={
"title": "Test Event",
"start": "2026-02-19T10:00:00Z",
"end": "2026-02-19T11:00:00Z",
"user_id": "test_user"
})
# Should create event or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_update_calendar_event(self, client: TestClient, db_session: Session):
"""Verify updating calendar event."""
event_id = "test_event_id"
response = client.put(f"/api/atom-agent/calendar/events/{event_id}", json={
"title": "Updated Event"
})
# Should update or return 404
assert response.status_code in [200, 404]
def test_delete_calendar_event(self, client: TestClient, db_session: Session):
"""Verify deleting calendar event."""
event_id = "test_delete_event_id"
response = client.delete(f"/api/atom-agent/calendar/events/{event_id}")
# Should delete or return 404
assert response.status_code in [200, 204, 404]
class TestEmailEndpoints:
"""Tests for email-related endpoints."""
def test_list_emails(self, client: TestClient, db_session: Session):
"""Verify listing emails."""
response = client.get("/api/atom-agent/emails?user_id=test_user")
# Should return emails or appropriate response
assert response.status_code in [200, 404]
def test_send_email(self, client: TestClient, db_session: Session):
"""Verify sending email."""
response = client.post("/api/atom-agent/emails", json={
"to": "test@example.com",
"subject": "Test Email",
"body": "Email body",
"user_id": "test_user"
})
# Should send or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_get_email_details(self, client: TestClient, db_session: Session):
"""Verify getting email details."""
email_id = "test_email_id"
response = client.get(f"/api/atom-agent/emails/{email_id}")
# Should return email or 404
assert response.status_code in [200, 404]
class TestFinanceEndpoints:
"""Tests for finance-related endpoints."""
def test_list_finance_items(self, client: TestClient, db_session: Session):
"""Verify listing finance items."""
response = client.get("/api/atom-agent/finance/items?user_id=test_user")
# Should return items or appropriate response
assert response.status_code in [200, 404]
def test_create_finance_item(self, client: TestClient, db_session: Session):
"""Verify creating finance item."""
response = client.post("/api/atom-agent/finance/items", json={
"name": "Test Item",
"amount": 100.00,
"user_id": "test_user"
})
# Should create or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_update_finance_item(self, client: TestClient, db_session: Session):
"""Verify updating finance item."""
item_id = "test_item_id"
response = client.put(f"/api/atom-agent/finance/items/{item_id}", json={
"amount": 150.00
})
# Should update or return 404
assert response.status_code in [200, 404]
class TestWorkflowEndpoints:
"""Tests for workflow-related endpoints."""
def test_list_workflows(self, client: TestClient, db_session: Session):
"""Verify listing workflows."""
response = client.get("/api/atom-agent/workflows")
# Should return workflows
assert response.status_code in [200, 404]
def test_get_workflow_details(self, client: TestClient, db_session: Session):
"""Verify getting workflow details."""
workflow_id = "test_workflow_id"
response = client.get(f"/api/atom-agent/workflows/{workflow_id}")
# Should return workflow or 404
assert response.status_code in [200, 404]
def test_create_workflow(self, client: TestClient, db_session: Session):
"""Verify creating workflow."""
response = client.post("/api/atom-agent/workflows", json={
"name": "Test Workflow",
"description": "Workflow description",
"steps": []
})
# Should create or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_update_workflow(self, client: TestClient, db_session: Session):
"""Verify updating workflow."""
workflow_id = "test_update_workflow_id"
response = client.put(f"/api/atom-agent/workflows/{workflow_id}", json={
"name": "Updated Workflow"
})
# Should update or return 404
assert response.status_code in [200, 404]
def test_delete_workflow(self, client: TestClient, db_session: Session):
"""Verify deleting workflow."""
workflow_id = "test_delete_workflow_id"
response = client.delete(f"/api/atom-agent/workflows/{workflow_id}")
# Should delete or return 404
assert response.status_code in [200, 204, 404]
class TestSearchEndpoints:
"""Tests for search-related endpoints."""
def test_search_endpoint(self, client: TestClient, db_session: Session):
"""Verify search endpoint."""
response = client.post("/api/atom-agent/search", json={
"query": "test search",
"user_id": "test_user"
})
# Should return search results
assert response.status_code in [200, 404, 422]
def test_hybrid_search(self, client: TestClient, db_session: Session):
"""Verify hybrid search endpoint."""
response = client.post("/api/atom-agent/search/hybrid", json={
"query": "test hybrid search",
"user_id": "test_user"
})
# Should return hybrid search results
assert response.status_code in [200, 404, 422]
class TestKnowledgeEndpoints:
"""Tests for knowledge-related endpoints."""
def test_query_knowledge(self, client: TestClient, db_session: Session):
"""Verify knowledge query endpoint."""
response = client.post("/api/atom-agent/knowledge/query", json={
"question": "test question",
"user_id": "test_user"
})
# Should return knowledge or appropriate response
assert response.status_code in [200, 404, 422]
def test_add_knowledge(self, client: TestClient, db_session: Session):
"""Verify adding knowledge endpoint."""
response = client.post("/api/atom-agent/knowledge", json={
"content": "Test knowledge content",
"metadata": {"source": "test"},
"user_id": "test_user"
})
# Should add knowledge or return appropriate response
assert response.status_code in [200, 201, 404, 422]
class TestAnalyticsEndpoints:
"""Tests for analytics-related endpoints."""
def test_get_analytics(self, client: TestClient, db_session: Session):
"""Verify getting analytics data."""
response = client.get("/api/atom-agent/analytics?user_id=test_user")
# Should return analytics or appropriate response
assert response.status_code in [200, 404]
def test_get_usage_stats(self, client: TestClient, db_session: Session):
"""Verify getting usage statistics."""
response = client.get("/api/atom-agent/analytics/usage?user_id=test_user")
# Should return usage stats
assert response.status_code in [200, 404]
def test_get_performance_metrics(self, client: TestClient, db_session: Session):
"""Verify getting performance metrics."""
response = client.get("/api/atom-agent/analytics/performance")
# Should return performance metrics
assert response.status_code in [200, 404]
class TestAgentManagementEndpoints:
"""Tests for agent management endpoints."""
def test_list_all_agents(self, client: TestClient, db_session: Session):
"""Verify listing all agents."""
response = client.get("/api/atom-agent/agents")
# Should return list of agents
assert response.status_code in [200, 404]
def test_get_agent_by_id(self, client: TestClient, db_session: Session):
"""Verify getting agent by ID."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.get(f"/api/atom-agent/agents/{agent.id}")
# Should return agent details
assert response.status_code in [200, 404]
def test_create_new_agent(self, client: TestClient, db_session: Session):
"""Verify creating new agent."""
response = client.post("/api/atom-agent/agents", json={
"name": "Test Agent",
"agent_type": "autonomous",
"description": "Test agent description"
})
# Should create agent or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_update_agent(self, client: TestClient, db_session: Session):
"""Verify updating agent."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.put(f"/api/atom-agent/agents/{agent.id}", json={
"name": "Updated Agent Name"
})
# Should update or return appropriate response
assert response.status_code in [200, 404]
def test_delete_agent(self, client: TestClient, db_session: Session):
"""Verify deleting agent."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.delete(f"/api/atom-agent/agents/{agent.id}")
# Should delete or return appropriate response
assert response.status_code in [200, 204, 404]
def test_get_agent_status(self, client: TestClient, db_session: Session):
"""Verify getting agent status."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.get(f"/api/atom-agent/agents/{agent.id}/status")
# Should return status
assert response.status_code in [200, 404]
class TestExecutionEndpoints:
"""Tests for execution-related endpoints."""
def test_get_execution_history(self, client: TestClient, db_session: Session):
"""Verify getting execution history."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.get(f"/api/atom-agent/agents/{agent.id}/executions")
# Should return execution history
assert response.status_code in [200, 404]
def test_get_execution_details(self, client: TestClient, db_session: Session):
"""Verify getting execution details."""
execution = AgentExecutionFactory(_session=db_session)
db_session.commit()
response = client.get(f"/api/atom-agent/executions/{execution.id}")
# Should return execution details
assert response.status_code in [200, 404]
def test_stop_execution(self, client: TestClient, db_session: Session):
"""Verify stopping execution."""
execution = AgentExecutionFactory(_session=db_session)
db_session.commit()
response = client.post(f"/api/atom-agent/executions/{execution.id}/stop")
# Should stop execution or return appropriate response
assert response.status_code in [200, 404]
class TestFeedbackEndpointsExpanded:
"""Expanded tests for feedback endpoints."""
def test_submit_feedback_for_execution(self, client: TestClient, db_session: Session):
"""Verify submitting feedback for execution."""
execution = AgentExecutionFactory(_session=db_session)
db_session.commit()
response = client.post(f"/api/atom-agent/executions/{execution.id}/feedback", json={
"rating": 5,
"feedback": "Excellent execution"
})
# Should submit feedback or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_get_feedback_for_execution(self, client: TestClient, db_session: Session):
"""Verify getting feedback for execution."""
execution = AgentExecutionFactory(_session=db_session)
db_session.commit()
response = client.get(f"/api/atom-agent/executions/{execution.id}/feedback")
# Should return feedback
assert response.status_code in [200, 404]
def test_list_all_feedback(self, client: TestClient, db_session: Session):
"""Verify listing all feedback."""
response = client.get("/api/atom-agent/feedback?user_id=test_user")
# Should return feedback list
assert response.status_code in [200, 404]
def test_update_feedback(self, client: TestClient, db_session: Session):
"""Verify updating feedback."""
execution = AgentExecutionFactory(_session=db_session)
feedback = AgentFeedback(
execution_id=execution.id,
rating=4,
feedback="Good"
)
db_session.add(feedback)
db_session.commit()
response = client.put(f"/api/atom-agent/feedback/{feedback.id}", json={
"rating": 5,
"feedback": "Updated feedback"
})
# Should update or return appropriate response
assert response.status_code in [200, 404]
def test_delete_feedback(self, client: TestClient, db_session: Session):
"""Verify deleting feedback."""
execution = AgentExecutionFactory(_session=db_session)
feedback = AgentFeedback(
execution_id=execution.id,
rating=4,
feedback="Good"
)
db_session.add(feedback)
db_session.commit()
response = client.delete(f"/api/atom-agent/feedback/{feedback.id}")
# Should delete or return appropriate response
assert response.status_code in [200, 204, 404]
class TestBatchOperations:
"""Tests for batch operation endpoints."""
def test_batch_create_tasks(self, client: TestClient, db_session: Session):
"""Verify batch creating tasks."""
response = client.post("/api/atom-agent/batch/tasks", json={
"tasks": [
{"title": "Task 1", "user_id": "test_user"},
{"title": "Task 2", "user_id": "test_user"}
]
})
# Should create batch or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_batch_update_tasks(self, client: TestClient, db_session: Session):
"""Verify batch updating tasks."""
response = client.put("/api/atom-agent/batch/tasks", json={
"updates": [
{"id": "task1", "status": "completed"},
{"id": "task2", "status": "in_progress"}
]
})
# Should update batch or return appropriate response
assert response.status_code in [200, 404]
def test_batch_delete_tasks(self, client: TestClient, db_session: Session):
"""Verify batch deleting tasks."""
response = client.post("/api/atom-agent/batch/tasks/delete", json={
"task_ids": ["task1", "task2", "task3"]
})
# Should delete batch or return appropriate response
assert response.status_code in [200, 204, 404]
class TestWebhookEndpoints:
"""Tests for webhook-related endpoints."""
def test_register_webhook(self, client: TestClient, db_session: Session):
"""Verify registering webhook."""
response = client.post("/api/atom-agent/webhooks", json={
"url": "https://example.com/webhook",
"events": ["task.created", "task.completed"],
"user_id": "test_user"
})
# Should register or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_list_webhooks(self, client: TestClient, db_session: Session):
"""Verify listing webhooks."""
response = client.get("/api/atom-agent/webhooks?user_id=test_user")
# Should return webhooks
assert response.status_code in [200, 404]
def test_delete_webhook(self, client: TestClient, db_session: Session):
"""Verify deleting webhook."""
webhook_id = "test_webhook_id"
response = client.delete(f"/api/atom-agent/webhooks/{webhook_id}")
# Should delete or return 404
assert response.status_code in [200, 204, 404]
def test_trigger_webhook(self, client: TestClient, db_session: Session):
"""Verify triggering webhook."""
webhook_id = "test_trigger_webhook_id"
response = client.post(f"/api/atom-agent/webhooks/{webhook_id}/trigger", json={
"event": "task.completed",
"data": {"task_id": "task123"}
})
# Should trigger or return appropriate response
assert response.status_code in [200, 404]
class TestExportImportEndpoints:
"""Tests for export/import endpoints."""
def test_export_data(self, client: TestClient, db_session: Session):
"""Verify exporting data."""
response = client.get("/api/atom-agent/export?user_id=test_user&format=json")
# Should export data or return appropriate response
assert response.status_code in [200, 404]
def test_import_data(self, client: TestClient, db_session: Session):
"""Verify importing data."""
import json
response = client.post("/api/atom-agent/import", json={
"data": {"tasks": [], "sessions": []},
"user_id": "test_user"
})
# Should import or return appropriate response
assert response.status_code in [200, 201, 404, 422]
def test_export_sessions(self, client: TestClient, db_session: Session):
"""Verify exporting sessions."""
response = client.get("/api/atom-agent/export/sessions?user_id=test_user")
# Should export sessions
assert response.status_code in [200, 404]
def test_export_tasks(self, client: TestClient, db_session: Session):
"""Verify exporting tasks."""
response = client.get("/api/atom-agent/export/tasks?user_id=test_user")
# Should export tasks
assert response.status_code in [200, 404]
class TestSettingsEndpoints:
"""Tests for settings-related endpoints."""
def test_get_user_settings(self, client: TestClient, db_session: Session):
"""Verify getting user settings."""
response = client.get("/api/atom-agent/settings?user_id=test_user")
# Should return settings
assert response.status_code in [200, 404]
def test_update_user_settings(self, client: TestClient, db_session: Session):
"""Verify updating user settings."""
response = client.put("/api/atom-agent/settings", json={
"user_id": "test_user",
"settings": {
"notifications": True,
"theme": "dark"
}
})
# Should update settings or return appropriate response
assert response.status_code in [200, 404]
def test_reset_user_settings(self, client: TestClient, db_session: Session):
"""Verify resetting user settings."""
response = client.post("/api/atom-agent/settings/reset", json={
"user_id": "test_user"
})
# Should reset settings or return appropriate response
assert response.status_code in [200, 404]
class TestNotificationEndpoints:
"""Tests for notification endpoints."""
def test_list_notifications(self, client: TestClient, db_session: Session):
"""Verify listing notifications."""
response = client.get("/api/atom-agent/notifications?user_id=test_user")
# Should return notifications
assert response.status_code in [200, 404]
def test_mark_notification_read(self, client: TestClient, db_session: Session):
"""Verify marking notification as read."""
notification_id = "test_notification_id"
response = client.put(f"/api/atom-agent/notifications/{notification_id}/read")
# Should mark as read or return 404
assert response.status_code in [200, 404]
def test_mark_all_notifications_read(self, client: TestClient, db_session: Session):
"""Verify marking all notifications as read."""
response = client.post("/api/atom-agent/notifications/read-all", json={
"user_id": "test_user"
})
# Should mark all as read or return appropriate response
assert response.status_code in [200, 404]
def test_delete_notification(self, client: TestClient, db_session: Session):
"""Verify deleting notification."""
notification_id = "test_delete_notification_id"
response = client.delete(f"/api/atom-agent/notifications/{notification_id}")
# Should delete or return 404
assert response.status_code in [200, 204, 404]
class TestIntentHandling:
"""Tests for intent classification and handling."""
def test_create_workflow_intent(self, client: TestClient, db_session: Session):
"""Verify CREATE_WORKFLOW intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Create a workflow for daily reports",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_list_workflows_intent(self, client: TestClient, db_session: Session):
"""Verify LIST_WORKFLOWS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "List all my workflows",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_run_workflow_intent(self, client: TestClient, db_session: Session):
"""Verify RUN_WORKFLOW intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Run the daily report workflow",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_schedule_workflow_intent(self, client: TestClient, db_session: Session):
"""Verify SCHEDULE_WORKFLOW intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Schedule the report workflow for 9am daily",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_get_history_intent(self, client: TestClient, db_session: Session):
"""Verify GET_HISTORY intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Show me my chat history",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_cancel_schedule_intent(self, client: TestClient, db_session: Session):
"""Verify CANCEL_SCHEDULE intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Cancel the scheduled workflow",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_get_status_intent(self, client: TestClient, db_session: Session):
"""Verify GET_STATUS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "What's the status of my workflows",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_create_calendar_event_intent(self, client: TestClient, db_session: Session):
"""Verify CREATE_EVENT intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Create a calendar event for tomorrow at 2pm",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_list_calendar_events_intent(self, client: TestClient, db_session: Session):
"""Verify LIST_EVENTS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Show me my calendar events for this week",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_send_email_intent(self, client: TestClient, db_session: Session):
"""Verify SEND_EMAIL intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Send an email to john@example.com",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_search_emails_intent(self, client: TestClient, db_session: Session):
"""Verify SEARCH_EMAILS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Search for emails about project update",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_knowledge_query_intent(self, client: TestClient, db_session: Session):
"""Verify KNOWLEDGE_QUERY intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "What do you know about project X",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_create_task_intent(self, client: TestClient, db_session: Session):
"""Verify CREATE_TASK intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Create a task to review the report",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_list_tasks_intent(self, client: TestClient, db_session: Session):
"""Verify LIST_TASKS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Show me all my tasks",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_update_task_intent(self, client: TestClient, db_session: Session):
"""Verify UPDATE_TASK intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Mark the report task as completed",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_delete_task_intent(self, client: TestClient, db_session: Session):
"""Verify DELETE_TASK intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Delete the task to review the report",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_finance_query_intent(self, client: TestClient, db_session: Session):
"""Verify FINANCE_QUERY intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Show me my financial summary",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_help_request_intent(self, client: TestClient, db_session: Session):
"""Verify HELP request is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Help me understand what you can do",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_unknown_intent_fallback(self, client: TestClient, db_session: Session):
"""Verify unknown intent uses fallback classification."""
response = client.post("/api/atom-agent/chat", json={
"message": "xyz123 random message that doesn't match any intent",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_follow_up_emails_intent(self, client: TestClient, db_session: Session):
"""Verify FOLLOW_UP_EMAILS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Follow up on the emails I sent yesterday",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_wellness_check_intent(self, client: TestClient, db_session: Session):
"""Verify WELLNESS_CHECK intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Check on my team's wellness",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_automation_insights_intent(self, client: TestClient, db_session: Session):
"""Verify AUTOMATION_INSIGHTS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Show me automation insights",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_resolve_conflicts_intent(self, client: TestClient, db_session: Session):
"""Verify RESOLVE_CONFLICTS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Help resolve conflicts in my schedule",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_set_goal_intent(self, client: TestClient, db_session: Session):
"""Verify SET_GOAL intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Set a goal to complete project by Friday",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_silent_stakeholders_intent(self, client: TestClient, db_session: Session):
"""Verify SILENT_STAKEHOLDERS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Identify silent stakeholders in my project",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_goal_status_intent(self, client: TestClient, db_session: Session):
"""Verify GOAL_STATUS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "What's the status of my goals",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_system_status_intent(self, client: TestClient, db_session: Session):
"""Verify SYSTEM_STATUS intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Check system status",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_platform_search_intent(self, client: TestClient, db_session: Session):
"""Verify PLATFORM_SEARCH intent is handled."""
response = client.post("/api/atom-agent/chat", json={
"message": "Search for project documentation",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
class TestRetrievalEndpoints:
"""Tests for retrieval endpoints."""
def test_retrieve_hybrid_endpoint(self, client: TestClient, db_session: Session):
"""Verify hybrid retrieval endpoint."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.post(f"/api/atom-agent/agents/{agent.id}/retrieve-hybrid", json={
"query": "test query",
"limit": 10
})
# Should perform hybrid retrieval
assert response.status_code in [200, 404]
def test_retrieve_baseline_endpoint(self, client: TestClient, db_session: Session):
"""Verify baseline retrieval endpoint."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.post(f"/api/atom-agent/agents/{agent.id}/retrieve-baseline", json={
"query": "test query",
"limit": 10
})
# Should perform baseline retrieval
assert response.status_code in [200, 404]
def test_retrieve_with_empty_query(self, client: TestClient, db_session: Session):
"""Verify retrieval handles empty query."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.post(f"/api/atom-agent/agents/{agent.id}/retrieve-hybrid", json={
"query": "",
"limit": 10
})
# Should handle empty query gracefully
assert response.status_code in [200, 400, 404]
def test_retrieve_with_custom_limit(self, client: TestClient, db_session: Session):
"""Verify retrieval respects custom limit."""
agent = AgentFactory(_session=db_session)
db_session.commit()
response = client.post(f"/api/atom-agent/agents/{agent.id}/retrieve-hybrid", json={
"query": "test query",
"limit": 50
})
# Should respect custom limit
assert response.status_code in [200, 404]
class TestExecuteGeneratedWorkflow:
"""Tests for execute-generated workflow endpoint."""
def test_execute_workflow_with_context(self, client: TestClient, db_session: Session):
"""Verify executing workflow with context."""
with patch('core.atom_agent_endpoints.load_workflows') as mock_load:
mock_workflow = {
"id": "context_workflow",
"name": "Context Workflow",
"steps": []
}
mock_load.return_value = [mock_workflow]
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "context_workflow",
"input_data": {
"param1": "value1",
"context": {"key": "value"}
}
})
assert response.status_code in [200, 202, 404]
def test_execute_workflow_with_agent_id(self, client: TestClient, db_session: Session):
"""Verify executing workflow with specific agent."""
agent = AutonomousAgentFactory(_session=db_session)
db_session.commit()
with patch('core.atom_agent_endpoints.load_workflows') as mock_load:
mock_workflow = {
"id": "agent_workflow",
"name": "Agent Workflow",
"steps": []
}
mock_load.return_value = [mock_workflow]
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "agent_workflow",
"input_data": {},
"agent_id": agent.id
})
assert response.status_code in [200, 202, 404]
def test_execute_workflow_with_empty_input_data(self, client: TestClient, db_session: Session):
"""Verify executing workflow with empty input data."""
with patch('core.atom_agent_endpoints.load_workflows') as mock_load:
mock_workflow = {
"id": "empty_input_workflow",
"name": "Empty Input Workflow",
"steps": []
}
mock_load.return_value = [mock_workflow]
response = client.post("/api/atom-agent/execute-generated", json={
"workflow_id": "empty_input_workflow",
"input_data": {}
})
assert response.status_code in [200, 202, 404]
class TestErrorRecovery:
"""Tests for error recovery and resilience."""
def test_chat_recovers_from_llm_timeout(self, client: TestClient, db_session: Session):
"""Verify chat recovers from LLM timeout."""
with patch('core.atom_agent_endpoints.classify_intent_with_llm') as mock_llm:
# Simulate timeout
mock_llm.side_effect = asyncio.TimeoutError("LLM timeout")
response = client.post("/api/atom-agent/chat", json={
"message": "Test timeout recovery",
"user_id": "test_user"
})
# Should recover with fallback
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_chat_handles_llm_api_error(self, client: TestClient, db_session: Session):
"""Verify chat handles LLM API errors."""
with patch('core.atom_agent_endpoints.classify_intent_with_llm') as mock_llm:
# Simulate API error
mock_llm.side_effect = Exception("API error")
response = client.post("/api/atom-agent/chat", json={
"message": "Test API error recovery",
"user_id": "test_user"
})
# Should recover with fallback
assert response.status_code == 200
data = response.json()
assert "success" in data or "response" in data
def test_sessions_handle_database_unavailable(self, client: TestClient, db_session: Session):
"""Verify sessions handle database unavailability."""
with patch('core.atom_agent_endpoints.get_chat_session_manager') as mock_mgr:
# Simulate database unavailable
mock_mgr.side_effect = Exception("Database unavailable")
response = client.get("/api/atom-agent/sessions?user_id=test_user")
# Should handle gracefully
assert response.status_code in [200, 500, 503]
class TestRequestValidation:
"""Tests for request validation and sanitization."""
def test_chat_with_empty_message(self, client: TestClient, db_session: Session):
"""Verify chat handles empty message."""
response = client.post("/api/atom-agent/chat", json={
"message": "",
"user_id": "test_user"
})
# Should handle empty message
assert response.status_code in [200, 400, 422]
def test_chat_with_whitespace_only_message(self, client: TestClient, db_session: Session):
"""Verify chat handles whitespace-only message."""
response = client.post("/api/atom-agent/chat", json={
"message": " \n\t ",
"user_id": "test_user"
})
# Should handle whitespace message
assert response.status_code in [200, 400, 422]
def test_chat_with_very_long_user_id(self, client: TestClient, db_session: Session):
"""Verify chat handles very long user_id."""
long_user_id = "x" * 10000
response = client.post("/api/atom-agent/chat", json={
"message": "Test message",
"user_id": long_user_id
})
# Should handle or reject
assert response.status_code in [200, 400, 422]
def test_chat_with_invalid_agent_id(self, client: TestClient, db_session: Session):
"""Verify chat handles non-existent agent_id."""
response = client.post("/api/atom-agent/chat", json={
"message": "Test message",
"user_id": "test_user",
"agent_id": "nonexistent_agent_id"
})
# Should handle gracefully
assert response.status_code == 200
def test_chat_with_unicode_characters(self, client: TestClient, db_session: Session):
"""Verify chat handles unicode characters."""
unicode_message = "Test with 你好 and 🎉 and العربية"
response = client.post("/api/atom-agent/chat", json={
"message": unicode_message,
"user_id": "test_user"
})
assert response.status_code == 200
class TestResponseFormats:
"""Tests for response format consistency."""
def test_chat_response_structure_consistency(self, client: TestClient, db_session: Session):
"""Verify chat response has consistent structure."""
response = client.post("/api/atom-agent/chat", json={
"message": "Test response structure",
"user_id": "test_user"
})
assert response.status_code == 200
data = response.json()
# Check for expected fields
if "success" in data:
assert isinstance(data["success"], bool)
if "response" in data:
assert isinstance(data["response"], str)
def test_sessions_response_structure_consistency(self, client: TestClient, db_session: Session):
"""Verify sessions response has consistent structure."""
response = client.get("/api/atom-agent/sessions?user_id=test_user")
assert response.status_code == 200
data = response.json()
# Check for expected fields
assert "sessions" in data
assert isinstance(data["sessions"], list)
def test_session_history_response_structure(self, client: TestClient, db_session: Session):
"""Verify session history response has consistent structure."""
session_id = "test_structure_session"
response = client.get(f"/api/atom-agent/sessions/{session_id}/history")
if response.status_code == 200:
data = response.json()
# Check for expected fields
assert "messages" in data or "success" in data
class TestPerformanceCharacteristics:
"""Tests for performance characteristics."""
def test_chat_response_time(self, client: TestClient, db_session: Session):
"""Verify chat responds within reasonable time."""
import time
start = time.time()
response = client.post("/api/atom-agent/chat", json={
"message": "Quick test",
"user_id": "perf_test_user"
})
elapsed = time.time() - start
# Should respond quickly (within 10 seconds)
assert response.status_code == 200
assert elapsed < 10.0
def test_sessions_list_response_time(self, client: TestClient, db_session: Session):
"""Verify sessions list responds within reasonable time."""
import time
start = time.time()
response = client.get("/api/atom-agent/sessions?user_id=test_user")
elapsed = time.time() - start
# Should respond quickly (within 5 seconds)
assert response.status_code == 200
assert elapsed < 5.0
class TestConcurrentAccess:
"""Tests for concurrent access patterns."""
def test_multiple_simultaneous_chats(self, client: TestClient, db_session: Session):
"""Verify multiple simultaneous chat requests work."""
import threading
results = []
def make_chat_request(request_id):
response = client.post("/api/atom-agent/chat", json={
"message": f"Concurrent test {request_id}",
"user_id": "concurrent_test_user"
})
results.append(response.status_code)
threads = [threading.Thread(target=make_chat_request, args=(i,)) for i in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
# All requests should complete
assert len(results) == 5
for status in results:
assert status == 200
class TestEdgeCases:
"""Tests for edge cases and boundary conditions."""
def test_chat_with_newline_characters(self, client: TestClient, db_session: Session):
"""Verify chat handles newlines in message."""
message = "Line 1\nLine 2\nLine 3"
response = client.post("/api/atom-agent/chat", json={
"message": message,
"user_id": "test_user"
})
assert response.status_code == 200
def test_chat_with_json_in_message(self, client: TestClient, db_session: Session):
"""Verify chat handles JSON content in message."""
message = 'Test with {"key": "value"} in message'
response = client.post("/api/atom-agent/chat", json={
"message": message,
"user_id": "test_user"
})
assert response.status_code == 200
def test_chat_with_code_snippets(self, client: TestClient, db_session: Session):
"""Verify chat handles code snippets in message."""
message = 'Help me with this code: def hello(): print("world")'
response = client.post("/api/atom-agent/chat", json={
"message": message,
"user_id": "test_user"
})
assert response.status_code == 200
def test_chat_with_url_in_message(self, client: TestClient, db_session: Session):
"""Verify chat handles URLs in message."""
message = "Check out https://example.com/page?param=value"
response = client.post("/api/atom-agent/chat", json={
"message": message,
"user_id": "test_user"
})
assert response.status_code == 200
def test_chat_with_email_addresses(self, client: TestClient, db_session: Session):
"""Verify chat handles email addresses in message."""
message = "Contact john.doe@example.com and jane@test.org"
response = client.post("/api/atom-agent/chat", json={
"message": message,
"user_id": "test_user"
})
assert response.status_code == 200
def test_chat_with_phone_numbers(self, client: TestClient, db_session: Session):
"""Verify chat handles phone numbers in message."""
message = "Call me at +1 (555) 123-4567"
response = client.post("/api/atom-agent/chat", json={
"message": message,
"user_id": "test_user"
})
assert response.status_code == 200
def test_session_with_special_characters_in_id(self, client: TestClient, db_session: Session):
"""Verify session handling with special characters in session_id."""
session_id = "test-session_123.abc@example"
response = client.get(f"/api/atom-agent/sessions/{session_id}/history")
# Should handle special characters
assert response.status_code in [200, 404]