Files
sovereign_ai/SovereignAI-Starter/tests/test_api_contract.py
T

96 lines
3.6 KiB
Python

import os
import tempfile
import unittest
from uuid import UUID
from unittest.mock import patch
from fastapi import HTTPException
# Importing the API initializes its SQLite schema. Keep this test process isolated
# from the real local conversation database.
_TEST_DATA_DIR = tempfile.TemporaryDirectory(prefix="sovereignai-api-tests-")
os.environ["SOVEREIGNAI_DATA_DIR"] = _TEST_DATA_DIR.name
from app.main import app
from tests.api_client import authenticated_client
class ApiErrorContractTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.client = authenticated_client(app)
def test_health_response_has_correlation_id(self) -> None:
response = self.client.get("/health")
self.assertEqual(response.status_code, 200)
UUID(response.headers["x-request-id"])
self.assertEqual(response.json()["status"], "ok")
def test_not_found_uses_normalized_error_contract(self) -> None:
response = self.client.get("/no-such-route")
self.assertEqual(response.status_code, 404)
self.assertEqual(response.json()["error"]["code"], "not_found")
self.assertEqual(response.json()["request_id"], response.headers["x-request-id"])
def test_validation_error_is_normalized_and_does_not_echo_input(self) -> None:
sentinel = "sensitive-validation-input"
response = self.client.post(
"/v1/chat/completions", json={"messages": sentinel}
)
self.assertEqual(response.status_code, 422)
payload = response.json()
self.assertEqual(payload["error"]["code"], "invalid_request")
self.assertEqual(payload["request_id"], response.headers["x-request-id"])
self.assertNotIn(sentinel, response.text)
self.assertNotIn("input", payload["detail"][0])
def test_upstream_timeout_uses_gateway_timeout_contract(self) -> None:
with patch(
"app.main.get_completion",
side_effect=HTTPException(
status_code=504, detail="انتهت مهلة انتظار خادم النموذج المحلي."
),
):
response = self.client.post(
"/v1/chat/completions",
json={"messages": [{"role": "user", "content": "مرحبا"}]},
)
self.assertEqual(response.status_code, 504)
self.assertEqual(response.json()["error"]["code"], "upstream_timeout")
self.assertEqual(response.json()["request_id"], response.headers["x-request-id"])
def test_model_list_exposes_verified_capabilities(self) -> None:
class MetadataProvider:
name = "test"
default_model = "vision-test"
base_url = "http://local"
async def list_models(self):
return ["vision-test", "unknown-test"]
async def describe_models(self, model_names):
return {
"vision-test": {
"verified": True,
"capabilities": ["completion", "vision"],
},
"unknown-test": {"verified": False, "capabilities": []},
}
with patch("app.main.get_model_provider", return_value=MetadataProvider()):
response = self.client.get("/v1/models")
self.assertEqual(response.status_code, 200)
models = {item["id"]: item for item in response.json()["data"]}
self.assertEqual(models["vision-test"]["capabilities"], ["completion", "vision"])
self.assertTrue(models["vision-test"]["capabilities_verified"])
self.assertFalse(models["unknown-test"]["capabilities_verified"])
if __name__ == "__main__":
unittest.main()