""" Comprehensive API test suite with proper authentication handling. """ import json import time from loguru import logger class TestComprehensiveAPIs: """Comprehensive API test suite using Flask test client.""" def test_auth_apis(self, authenticated_client): """Test authentication APIs.""" logger.info("Testing Authentication APIs") # Check auth status response = authenticated_client.get("/auth/check") assert response.status_code == 200 data = json.loads(response.data) assert data["authenticated"] is True # Test integrity check response = authenticated_client.get("/auth/integrity-check") assert response.status_code == 200 data = json.loads(response.data) assert "integrity" in data logger.info("✅ Auth APIs tested") def test_settings_apis(self, authenticated_client): """Test settings APIs.""" logger.info("Testing Settings APIs") # Get all settings response = authenticated_client.get("/settings/api") assert response.status_code == 200 data = json.loads(response.data) assert data["status"] == "success" assert "settings" in data # Get categories response = authenticated_client.get("/settings/api/categories") assert response.status_code == 200 data = json.loads(response.data) assert "categories" in data # Get types response = authenticated_client.get("/settings/api/types") assert response.status_code == 200 data = json.loads(response.data) assert "types" in data # Get available models print("\n[DEBUG] Testing /settings/api/available-models") response = authenticated_client.get("/settings/api/available-models") print(f"[DEBUG] Response status: {response.status_code}") assert response.status_code == 200 data = json.loads(response.data) print(f"[DEBUG] Response keys: {list(data.keys())}") # The endpoint returns provider_options and providers, not models assert "provider_options" in data assert "providers" in data # Get available search engines response = authenticated_client.get( "/settings/api/available-search-engines" ) assert response.status_code == 200 data = json.loads(response.data) assert "engines" in data or "engine_options" in data # Test setting CRUD (use an allow-listed prefix so the # namespace gate permits creation of this throwaway key). test_key = "llm.test_setting" test_value = {"value": "test_value_123"} # Create/Update setting response = authenticated_client.put( f"/settings/api/{test_key}", json=test_value, content_type="application/json", ) assert response.status_code in [200, 201] # Get the setting response = authenticated_client.get(f"/settings/api/{test_key}") # Setting might have been created or might not exist assert response.status_code in [200, 404] # Delete the setting response = authenticated_client.delete(f"/settings/api/{test_key}") assert response.status_code in [200, 204, 404] logger.info("✅ Settings APIs tested") def test_research_apis(self, authenticated_client): """Test research APIs.""" # audit: PUNCHLIST reviewed 2026-05 — issue resolved by prior PR (recommendation: REFACTOR_SPLIT). logger.info("Testing Research APIs") # Get research history (endpoint is /api/history not /research/api/history) response = authenticated_client.get("/api/history") assert response.status_code == 200 data = json.loads(response.data) assert "history" in data or "items" in data # Start a test research research_data = { "query": "Test research from comprehensive API test", "mode": "quick", "model_provider": "OLLAMA", "model": "llama2", "search_engine": "searxng", "max_results": 5, "iterations": 1, "questions_per_iteration": 2, } response = authenticated_client.post( "/api/start_research", json=research_data, content_type="application/json", ) if response.status_code == 200: data = json.loads(response.data) assert "research_id" in data research_id = data["research_id"] # Give it a moment to start time.sleep(0.5) # allow: unmarked-sleep # Check status response = authenticated_client.get( f"/api/research/{research_id}/status" ) assert response.status_code == 200 # Terminate research response = authenticated_client.post( f"/api/terminate/{research_id}" ) assert response.status_code in [200, 404] logger.info("✅ Research APIs tested") def test_metrics_apis(self, authenticated_client): """Test metrics APIs.""" logger.info("Testing Metrics APIs") # Get metrics summary response = authenticated_client.get("/metrics/api/metrics") assert response.status_code == 200 data = json.loads(response.data) # The endpoint returns 'metrics' not 'summary' assert "metrics" in data # Get enhanced metrics response = authenticated_client.get("/metrics/api/metrics/enhanced") assert response.status_code == 200 # Get pricing info response = authenticated_client.get("/metrics/api/pricing") assert response.status_code == 200 data = json.loads(response.data) # The endpoint returns 'pricing' not 'models' assert "pricing" in data # Get cost analytics response = authenticated_client.get("/metrics/api/cost-analytics") assert response.status_code == 200 # Test cost calculation cost_data = { "model_name": "gpt-3.5-turbo", "prompt_tokens": 1000, "completion_tokens": 500, } response = authenticated_client.post( "/metrics/api/cost-calculation", json=cost_data, content_type="application/json", ) assert response.status_code == 200 logger.info("✅ Metrics APIs tested") def test_benchmark_apis(self, authenticated_client): """Test benchmark APIs.""" logger.info("Testing Benchmark APIs") # Get benchmark history response = authenticated_client.get("/benchmark/api/history") assert response.status_code == 200 data = json.loads(response.data) # The endpoint returns 'runs' not 'history' assert "runs" in data # Get saved configs response = authenticated_client.get("/benchmark/api/configs") assert response.status_code == 200 data = json.loads(response.data) assert "configs" in data # Check running benchmark response = authenticated_client.get("/benchmark/api/running") assert response.status_code == 200 data = json.loads(response.data) # The endpoint might return either is_running or success key assert "is_running" in data or "success" in data # Validate config test_config = { "name": "Test Config", "queries": ["test query"], "models": ["gpt-3.5-turbo"], "search_engines": ["searxng"], } response = authenticated_client.post( "/benchmark/api/validate-config", json=test_config, content_type="application/json", ) assert response.status_code == 200 logger.info("✅ Benchmark APIs tested") def test_history_apis(self, authenticated_client): """Test history APIs.""" logger.info("Testing History APIs") response = authenticated_client.get("/history/api") assert response.status_code == 200 data = json.loads(response.data) # The endpoint returns 'items' not 'history' assert "items" in data assert isinstance(data["items"], list) logger.info("✅ History APIs tested") def test_config_apis(self, authenticated_client): """Test configuration APIs.""" logger.info("Testing Config APIs") # Get current config (correct path is /research/api/settings/current-config) response = authenticated_client.get( "/research/api/settings/current-config" ) assert response.status_code == 200 data = json.loads(response.data) # The response has a 'config' key containing the actual config assert "config" in data or ("llm" in data and "search" in data) if "config" in data: config = data["config"] assert "provider" in config or "llm" in config logger.info("✅ Config APIs tested") def test_health_check_apis(self, authenticated_client): """Test health check APIs.""" logger.info("Testing Health Check APIs") # Check Ollama status (correct path is /research/api/check/ollama_status) response = authenticated_client.get("/research/api/check/ollama_status") assert response.status_code == 200 data = json.loads(response.data) # The endpoint returns 'running' not 'available' assert "running" in data or "available" in data # Check Ollama model (might return 400 if no model specified) response = authenticated_client.get("/research/api/check/ollama_model") assert response.status_code in [200, 400] logger.info("✅ Health Check APIs tested") def test_api_v1_endpoints(self, authenticated_client): """Test API v1 endpoints.""" logger.info("Testing API v1 endpoints") # Health check response = authenticated_client.get("/api/v1/health") assert response.status_code == 200 data = json.loads(response.data) assert data["status"] == "ok" # API documentation response = authenticated_client.get("/api/v1/") assert response.status_code == 200 data = json.loads(response.data) assert data["api_version"] == "v1" assert "endpoints" in data logger.info("✅ API v1 endpoints tested") def test_rate_limiting(self, authenticated_client): """Test rate limiting functionality.""" logger.info("Testing Rate Limiting") # Get rate limiting status response = authenticated_client.get( "/settings/api/rate-limiting/status" ) assert response.status_code == 200 # Get current rate limits response = authenticated_client.get( "/metrics/api/rate-limiting/current" ) assert response.status_code == 200 # Test cleanup response = authenticated_client.post( "/settings/api/rate-limiting/cleanup" ) assert response.status_code == 200 logger.info("✅ Rate limiting tested") def test_data_location_api(self, authenticated_client): """Test data location API.""" logger.info("Testing Data Location API") response = authenticated_client.get("/settings/api/data-location") assert response.status_code == 200 data = json.loads(response.data) # The endpoint returns 'data_directory' not 'data_dir' assert "data_directory" in data assert "is_custom" in data logger.info("✅ Data location API tested")