334 lines
12 KiB
Python
334 lines
12 KiB
Python
"""Tests for analysis sessions endpoints."""
|
|
|
|
import pytest
|
|
from unittest.mock import AsyncMock
|
|
import httpx
|
|
from app.models.analysis import SessionResponse, SessionList, SessionCreate
|
|
|
|
|
|
class TestAnalysisEndpoints:
|
|
"""Tests for /api/v1/analysis/sessions endpoints."""
|
|
|
|
def test_create_session_success(self, client, mock_db_client):
|
|
"""Test creating a new analysis session."""
|
|
mock_session = SessionResponse(
|
|
session_id="session-123",
|
|
user_id="test-user-123",
|
|
environment="ift",
|
|
api_mode="bench",
|
|
request=[],
|
|
response={},
|
|
annotations={},
|
|
created_at="2024-01-01T00:00:00Z",
|
|
updated_at="2024-01-01T00:00:00Z"
|
|
)
|
|
mock_db_client.save_session = AsyncMock(return_value=mock_session)
|
|
|
|
session_data = {
|
|
"environment": "ift",
|
|
"api_mode": "bench",
|
|
"request": [],
|
|
"response": {"answers": []},
|
|
"annotations": {}
|
|
}
|
|
|
|
response = client.post("/api/v1/analysis/sessions", json=session_data)
|
|
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
|
|
assert data["session_id"] == "session-123"
|
|
assert data["environment"] == "ift"
|
|
assert data["api_mode"] == "bench"
|
|
|
|
mock_db_client.save_session.assert_called_once()
|
|
|
|
def test_create_session_invalid_data(self, client, mock_db_client):
|
|
"""Test creating session with invalid data."""
|
|
error_response = httpx.Response(400, json={"detail": "Invalid format"})
|
|
mock_db_client.save_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Bad request", request=None, response=error_response)
|
|
)
|
|
|
|
session_data = {
|
|
"environment": "invalid",
|
|
"api_mode": "bench",
|
|
"request": [],
|
|
"response": {},
|
|
"annotations": {}
|
|
}
|
|
|
|
response = client.post("/api/v1/analysis/sessions", json=session_data)
|
|
|
|
assert response.status_code in [400, 422]
|
|
|
|
def test_get_sessions_success(self, client, mock_db_client):
|
|
"""Test getting list of sessions."""
|
|
from app.models.analysis import SessionListItem
|
|
mock_sessions = SessionList(
|
|
sessions=[
|
|
SessionListItem(
|
|
session_id="session-1",
|
|
environment="ift",
|
|
created_at="2024-01-01T00:00:00Z"
|
|
),
|
|
SessionListItem(
|
|
session_id="session-2",
|
|
environment="psi",
|
|
created_at="2024-01-02T00:00:00Z"
|
|
)
|
|
],
|
|
total=2
|
|
)
|
|
mock_db_client.get_sessions = AsyncMock(return_value=mock_sessions)
|
|
|
|
response = client.get("/api/v1/analysis/sessions?limit=50&offset=0")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
assert data["total"] == 2
|
|
assert len(data["sessions"]) == 2
|
|
assert data["sessions"][0]["session_id"] == "session-1"
|
|
assert data["sessions"][1]["session_id"] == "session-2"
|
|
|
|
mock_db_client.get_sessions.assert_called_once_with(
|
|
"test-user-123", None, 50, 0
|
|
)
|
|
|
|
def test_get_sessions_with_filter(self, client, mock_db_client):
|
|
"""Test getting sessions with environment filter."""
|
|
mock_sessions = SessionList(sessions=[], total=0)
|
|
mock_db_client.get_sessions = AsyncMock(return_value=mock_sessions)
|
|
|
|
response = client.get("/api/v1/analysis/sessions?environment=ift&limit=10&offset=5")
|
|
|
|
assert response.status_code == 200
|
|
|
|
mock_db_client.get_sessions.assert_called_once_with(
|
|
"test-user-123", "ift", 10, 5
|
|
)
|
|
|
|
def test_get_sessions_pagination(self, client, mock_db_client):
|
|
"""Test sessions pagination limits."""
|
|
mock_sessions = SessionList(sessions=[], total=0)
|
|
mock_db_client.get_sessions = AsyncMock(return_value=mock_sessions)
|
|
|
|
|
|
response = client.get("/api/v1/analysis/sessions")
|
|
assert response.status_code == 200
|
|
mock_db_client.get_sessions.assert_called_with(
|
|
"test-user-123", None, 50, 0
|
|
)
|
|
|
|
|
|
response = client.get("/api/v1/analysis/sessions?limit=250")
|
|
assert response.status_code == 422
|
|
|
|
def test_get_session_by_id_success(self, client, mock_db_client):
|
|
"""Test getting specific session by ID."""
|
|
mock_session = SessionResponse(
|
|
session_id="session-123",
|
|
user_id="test-user-123",
|
|
environment="ift",
|
|
api_mode="bench",
|
|
request=[{"body": "Q1", "with_docs": True}],
|
|
response={"answers": ["A1"]},
|
|
annotations={"note": "test"},
|
|
created_at="2024-01-01T00:00:00Z",
|
|
updated_at="2024-01-01T00:00:00Z"
|
|
)
|
|
mock_db_client.get_session = AsyncMock(return_value=mock_session)
|
|
|
|
response = client.get("/api/v1/analysis/sessions/session-123")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
|
|
assert data["session_id"] == "session-123"
|
|
assert data["annotations"]["note"] == "test"
|
|
|
|
mock_db_client.get_session.assert_called_once_with("test-user-123", "session-123")
|
|
|
|
def test_get_session_not_found(self, client, mock_db_client):
|
|
"""Test getting non-existent session."""
|
|
error_response = httpx.Response(404, json={"detail": "Not found"})
|
|
mock_db_client.get_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Not found", request=None, response=error_response)
|
|
)
|
|
|
|
response = client.get("/api/v1/analysis/sessions/nonexistent")
|
|
|
|
assert response.status_code == 404
|
|
|
|
def test_delete_session_success(self, client, mock_db_client):
|
|
"""Test deleting a session."""
|
|
mock_db_client.delete_session = AsyncMock(return_value=None)
|
|
|
|
response = client.delete("/api/v1/analysis/sessions/session-123")
|
|
|
|
assert response.status_code == 204
|
|
assert response.content == b""
|
|
|
|
mock_db_client.delete_session.assert_called_once_with("test-user-123", "session-123")
|
|
|
|
def test_delete_session_not_found(self, client, mock_db_client):
|
|
"""Test deleting non-existent session."""
|
|
error_response = httpx.Response(404, json={"detail": "Not found"})
|
|
mock_db_client.delete_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Not found", request=None, response=error_response)
|
|
)
|
|
|
|
response = client.delete("/api/v1/analysis/sessions/nonexistent")
|
|
|
|
assert response.status_code == 404
|
|
|
|
def test_analysis_endpoints_require_auth(self, unauthenticated_client):
|
|
"""Test that all analysis endpoints require authentication."""
|
|
|
|
response = unauthenticated_client.post("/api/v1/analysis/sessions", json={})
|
|
assert response.status_code == 401
|
|
|
|
|
|
response = unauthenticated_client.get("/api/v1/analysis/sessions")
|
|
assert response.status_code == 401
|
|
|
|
|
|
response = unauthenticated_client.get("/api/v1/analysis/sessions/test")
|
|
assert response.status_code == 401
|
|
|
|
|
|
response = unauthenticated_client.delete("/api/v1/analysis/sessions/test")
|
|
assert response.status_code == 401
|
|
|
|
def test_create_session_user_not_found(self, client, mock_db_client):
|
|
"""Test creating session when user not found in DB API."""
|
|
error_response = httpx.Response(404, json={"detail": "User not found"})
|
|
mock_db_client.save_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Not found", request=None, response=error_response)
|
|
)
|
|
|
|
session_data = {
|
|
"environment": "ift",
|
|
"api_mode": "bench",
|
|
"request": [],
|
|
"response": {},
|
|
"annotations": {}
|
|
}
|
|
|
|
response = client.post("/api/v1/analysis/sessions", json=session_data)
|
|
|
|
assert response.status_code == 404
|
|
assert "user not found" in response.json()["detail"].lower()
|
|
|
|
def test_create_session_db_api_error(self, client, mock_db_client):
|
|
"""Test creating session when DB API returns 502."""
|
|
error_response = httpx.Response(503, json={"detail": "Service unavailable"})
|
|
mock_db_client.save_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Service error", request=None, response=error_response)
|
|
)
|
|
|
|
session_data = {
|
|
"environment": "ift",
|
|
"api_mode": "bench",
|
|
"request": [],
|
|
"response": {},
|
|
"annotations": {}
|
|
}
|
|
|
|
response = client.post("/api/v1/analysis/sessions", json=session_data)
|
|
|
|
assert response.status_code == 502
|
|
|
|
def test_create_session_unexpected_error(self, client, mock_db_client):
|
|
"""Test creating session with unexpected error."""
|
|
mock_db_client.save_session = AsyncMock(
|
|
side_effect=Exception("Unexpected database error")
|
|
)
|
|
|
|
session_data = {
|
|
"environment": "ift",
|
|
"api_mode": "bench",
|
|
"request": [],
|
|
"response": {},
|
|
"annotations": {}
|
|
}
|
|
|
|
response = client.post("/api/v1/analysis/sessions", json=session_data)
|
|
|
|
assert response.status_code == 500
|
|
|
|
def test_get_sessions_user_not_found(self, client, mock_db_client):
|
|
"""Test getting sessions when user not found."""
|
|
error_response = httpx.Response(404, json={"detail": "User not found"})
|
|
mock_db_client.get_sessions = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Not found", request=None, response=error_response)
|
|
)
|
|
|
|
response = client.get("/api/v1/analysis/sessions")
|
|
|
|
assert response.status_code == 404
|
|
|
|
def test_get_sessions_db_api_error(self, client, mock_db_client):
|
|
"""Test getting sessions when DB API fails."""
|
|
error_response = httpx.Response(503, json={"detail": "Service error"})
|
|
mock_db_client.get_sessions = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Service error", request=None, response=error_response)
|
|
)
|
|
|
|
response = client.get("/api/v1/analysis/sessions")
|
|
|
|
assert response.status_code == 502
|
|
|
|
def test_get_sessions_unexpected_error(self, client, mock_db_client):
|
|
"""Test getting sessions with unexpected error."""
|
|
mock_db_client.get_sessions = AsyncMock(
|
|
side_effect=Exception("Database connection lost")
|
|
)
|
|
|
|
response = client.get("/api/v1/analysis/sessions")
|
|
|
|
assert response.status_code == 500
|
|
|
|
def test_get_session_by_id_db_api_error(self, client, mock_db_client):
|
|
"""Test getting session when DB API returns 502."""
|
|
error_response = httpx.Response(500, json={"error": "Server error"})
|
|
mock_db_client.get_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Server error", request=None, response=error_response)
|
|
)
|
|
|
|
response = client.get("/api/v1/analysis/sessions/session-123")
|
|
|
|
assert response.status_code == 502
|
|
assert "failed to retrieve session" in response.json()["detail"].lower()
|
|
|
|
def test_get_session_by_id_unexpected_error(self, client, mock_db_client):
|
|
"""Test getting session with unexpected error."""
|
|
mock_db_client.get_session = AsyncMock(side_effect=Exception("Database crash"))
|
|
|
|
response = client.get("/api/v1/analysis/sessions/session-123")
|
|
|
|
assert response.status_code == 500
|
|
assert "internal server error" in response.json()["detail"].lower()
|
|
|
|
def test_delete_session_db_api_error(self, client, mock_db_client):
|
|
"""Test deleting session when DB API returns 502."""
|
|
error_response = httpx.Response(500, json={"error": "Server error"})
|
|
mock_db_client.delete_session = AsyncMock(
|
|
side_effect=httpx.HTTPStatusError("Server error", request=None, response=error_response)
|
|
)
|
|
|
|
response = client.delete("/api/v1/analysis/sessions/session-123")
|
|
|
|
assert response.status_code == 502
|
|
assert "failed to delete session" in response.json()["detail"].lower()
|
|
|
|
def test_delete_session_unexpected_error(self, client, mock_db_client):
|
|
"""Test deleting session with unexpected error."""
|
|
mock_db_client.delete_session = AsyncMock(side_effect=Exception("Database crash"))
|
|
|
|
response = client.delete("/api/v1/analysis/sessions/session-123")
|
|
|
|
assert response.status_code == 500
|
|
assert "internal server error" in response.json()["detail"].lower()
|