"""
Main Application Tests
Run with: pytest tests/test_main.py -v
"""
import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock
from pathlib import Path
# Import the app instance from main
from main import app
@pytest.fixture
def client():
"""
Test client fixture that handles the lifespan (startup/shutdown)
'with' statement triggers the @asynccontextmanager lifespan in main.py
"""
with TestClient(app) as c:
yield c
def test_root_endpoint(client):
"""Test the root GET endpoint for status and version"""
response = client.get("/")
assert response.status_code == 200
data = response.json()
assert data["name"] == "AegisAI"
assert data["status"] == "operational"
assert "version" in data
def test_docs_accessible(client):
"""Test that API documentation is available"""
response = client.get("/docs")
assert response.status_code == 200
@patch("main.db_service")
@patch("main.settings")
def test_lifespan_startup_shutdown(mock_settings, mock_db_service):
"""
Test the startup and shutdown logic specifically.
- Startup: Creates evidence directory.
- Shutdown: Cleans up old incidents.
"""
# Setup mocks
mock_settings.EVIDENCE_DIR = MagicMock(spec=Path)
mock_settings.MAX_EVIDENCE_AGE_DAYS = 30
mock_db_service.cleanup_old_incidents.return_value = 5
# Trigger lifespan by using the context manager
with TestClient(app):
# Startup checks
mock_settings.EVIDENCE_DIR.mkdir.assert_called_once_with(
exist_ok=True, parents=True
)
# Shutdown checks (after 'with' block ends)
mock_db_service.cleanup_old_incidents.assert_called_once_with(30)
def test_cors_headers(client):
"""Test that CORS middleware is active"""
response = client.options(
"/",
headers={
"Origin": "http://localhost:3000",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "X-Requested-With",
},
)
# If the origin is allowed in settings, this should be 200
assert response.status_code == 200
assert "access-control-allow-origin" in response.headers