brief-rags-bench/tests/test_analysis.py

334 lines
13 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] # 422 for validation error
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)
# Test default values
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
)
# Test max limit (200)
response = client.get("/api/v1/analysis/sessions?limit=250")
assert response.status_code == 422 # Validation error, exceeds max
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."""
# POST /sessions
response = unauthenticated_client.post("/api/v1/analysis/sessions", json={})
assert response.status_code == 401 # HTTPBearer returns 401
# GET /sessions
response = unauthenticated_client.get("/api/v1/analysis/sessions")
assert response.status_code == 401
# GET /sessions/{id}
response = unauthenticated_client.get("/api/v1/analysis/sessions/test")
assert response.status_code == 401
# DELETE /sessions/{id}
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()