"""
Service Integration Tests
Tests for API, AI, and visualization microservices.
Verifies service health, endpoints, and inter-service communication.
"""
import pytest
import json
from typing import Dict, Any
class TestMainAPIService:
"""Tests for main API service with C tools integration."""
def test_api_health_check(self, api_client):
"""Test main API health check endpoint."""
response = api_client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] in ["healthy", "ok"]
assert "tools" in data or "message" in data
def test_api_root_endpoint(self, api_client):
"""Test main API root endpoint."""
response = api_client.get("/")
assert response.status_code == 200
data = response.json()
assert data["name"] == "Tikker API"
assert "version" in data
assert "endpoints" in data
def test_get_daily_stats(self, api_client):
"""Test daily statistics endpoint."""
response = api_client.get("/api/stats/daily")
assert response.status_code in [200, 503]
if response.status_code == 200:
data = response.json()
assert "presses" in data or "status" in data
def test_get_top_words(self, api_client):
"""Test top words endpoint."""
response = api_client.get("/api/words/top?limit=10")
assert response.status_code in [200, 503]
if response.status_code == 200:
data = response.json()
assert isinstance(data, list) or isinstance(data, dict)
def test_decode_file_endpoint(self, api_client):
"""Test file decoding endpoint."""
payload = {
"input_file": "test_input.txt",
"output_file": "test_output.txt",
"verbose": False
}
response = api_client.post("/api/decode", json=payload)
assert response.status_code in [200, 400, 404, 503]
def test_api_health_timeout(self, api_client):
"""Test API health endpoint response time."""
import time
start = time.time()
response = api_client.get("/health")
elapsed = time.time() - start
assert elapsed < 5.0
assert response.status_code == 200
class TestAIService:
"""Tests for AI microservice."""
def test_ai_health_check(self, ai_client):
"""Test AI service health check."""
response = ai_client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"
assert "ai_available" in data
def test_ai_root_endpoint(self, ai_client):
"""Test AI service root endpoint."""
response = ai_client.get("/")
assert response.status_code == 200
data = response.json()
assert data["name"] == "Tikker AI Service"
assert "endpoints" in data
def test_ai_analyze_endpoint(self, ai_client):
"""Test AI text analysis endpoint."""
payload = {
"text": "This is a test message for analysis",
"analysis_type": "general"
}
response = ai_client.post("/analyze", json=payload)
assert response.status_code in [200, 503]
def test_ai_analyze_activity(self, ai_client):
"""Test AI activity analysis."""
payload = {
"text": "typing keyboard input keystroke logs",
"analysis_type": "activity"
}
response = ai_client.post("/analyze", json=payload)
assert response.status_code in [200, 503]
def test_ai_empty_text_validation(self, ai_client):
"""Test AI service rejects empty text."""
payload = {
"text": "",
"analysis_type": "general"
}
response = ai_client.post("/analyze", json=payload)
if response.status_code == 503:
pass
else:
assert response.status_code == 400
class TestVizService:
"""Tests for visualization microservice."""
def test_viz_health_check(self, viz_client):
"""Test visualization service health check."""
response = viz_client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"
assert "viz_available" in data
def test_viz_root_endpoint(self, viz_client):
"""Test visualization service root endpoint."""
response = viz_client.get("/")
assert response.status_code == 200
data = response.json()
assert data["name"] == "Tikker Visualization Service"
assert "supported_charts" in data
def test_viz_bar_chart(self, viz_client):
"""Test bar chart generation."""
payload = {
"title": "Test Bar Chart",
"data": {"A": 10, "B": 20, "C": 15},
"chart_type": "bar",
"width": 10,
"height": 6
}
response = viz_client.post("/chart", json=payload)
assert response.status_code in [200, 503]
if response.status_code == 200:
data = response.json()
assert data["status"] == "success"
assert data["chart_type"] == "bar"
assert "image_base64" in data
def test_viz_line_chart(self, viz_client):
"""Test line chart generation."""
payload = {
"title": "Test Line Chart",
"data": {"Jan": 100, "Feb": 120, "Mar": 140},
"chart_type": "line"
}
response = viz_client.post("/chart", json=payload)
assert response.status_code in [200, 503]
def test_viz_pie_chart(self, viz_client):
"""Test pie chart generation."""
payload = {
"title": "Test Pie Chart",
"data": {"Category1": 30, "Category2": 40, "Category3": 30},
"chart_type": "pie"
}
response = viz_client.post("/chart", json=payload)
assert response.status_code in [200, 503]
def test_viz_chart_download(self, viz_client):
"""Test chart download endpoint."""
payload = {
"title": "Download Test",
"data": {"X": 50, "Y": 75},
"chart_type": "bar"
}
response = viz_client.post("/chart/download", json=payload)
assert response.status_code in [200, 503]
def test_viz_invalid_chart_type(self, viz_client):
"""Test invalid chart type handling."""
payload = {
"title": "Invalid Chart",
"data": {"A": 10},
"chart_type": "invalid"
}
response = viz_client.post("/chart", json=payload)
if response.status_code == 503:
pass
else:
assert response.status_code == 400
class TestServiceIntegration:
"""Tests for service-to-service communication."""
def test_all_services_healthy(self, api_client, ai_client, viz_client):
"""Test all services report healthy status."""
api_response = api_client.get("/health")
ai_response = ai_client.get("/health")
viz_response = viz_client.get("/health")
assert api_response.status_code == 200
assert ai_response.status_code == 200
assert viz_response.status_code == 200
def test_api_to_ai_communication(self, api_client, ai_client):
"""Test API can communicate with AI service."""
api_health = api_client.get("/health")
ai_health = ai_client.get("/health")
assert api_health.status_code == 200
assert ai_health.status_code == 200
def test_api_to_viz_communication(self, api_client, viz_client):
"""Test API can communicate with visualization service."""
api_health = api_client.get("/health")
viz_health = viz_client.get("/health")
assert api_health.status_code == 200
assert viz_health.status_code == 200
def test_concurrent_service_requests(self, api_client, ai_client, viz_client):
"""Test multiple concurrent requests to different services."""
responses = {
"api": api_client.get("/health"),
"ai": ai_client.get("/health"),
"viz": viz_client.get("/health")
}
for service, response in responses.items():
assert response.status_code == 200, f"{service} service failed"
class TestErrorHandling:
"""Tests for error handling and edge cases."""
def test_api_invalid_endpoint(self, api_client):
"""Test API handles invalid endpoints."""
response = api_client.get("/api/invalid")
assert response.status_code == 404
def test_ai_invalid_endpoint(self, ai_client):
"""Test AI service handles invalid endpoints."""
response = ai_client.get("/invalid")
assert response.status_code == 404
def test_viz_invalid_endpoint(self, viz_client):
"""Test visualization service handles invalid endpoints."""
response = viz_client.get("/invalid")
assert response.status_code == 404
def test_api_malformed_json(self, api_client):
"""Test API handles malformed JSON."""
response = api_client.post(
"/api/decode",
content="invalid json",
headers={"Content-Type": "application/json"}
)
assert response.status_code in [400, 422]
def test_ai_malformed_json(self, ai_client):
"""Test AI service handles malformed JSON."""
response = ai_client.post(
"/analyze",
content="invalid json",
headers={"Content-Type": "application/json"}
)
assert response.status_code in [400, 422]
@pytest.fixture
def api_client():
"""Create API test client."""
from fastapi.testclient import TestClient
try:
from api_c_integration import app
return TestClient(app)
except:
return None
@pytest.fixture
def ai_client():
"""Create AI service test client."""
from fastapi.testclient import TestClient
try:
from ai_service import app
return TestClient(app)
except:
return None
@pytest.fixture
def viz_client():
"""Create visualization service test client."""
from fastapi.testclient import TestClient
try:
from viz_service import app
return TestClient(app)
except:
return None