dotb_ai-platform/tests/test_database_error_mapping.py
hungtran24 6577bb74be refactor: simplify scoring service, AI profile revisions and test suite
Phase 2 and 3 of the platform rework.

- Neutral request/response contract: external_id, metadata, X-AI-Key,
  run_id in the response; client-specific fields removed.
- AI profile is a revision table: saving creates an inactive revision,
  activation is separate, try-run does not store a run. One
  chat-completions gateway serves AIHub and OpenAI-compatible profiles.
- Add between and in rule operators.
- Contracts moved to contracts/lead-scoring/ with a score-response fixture.
- Admin Web updated for revisions, runs and the neutral fixture.
- Consolidate tests; remove rewrite_architect.md and the stale handoff doc;
  rewrite spec, CONTEXT and ARCHITECTURE for the current design.

Not verified: live AIHub/OpenAI behavior, Omni/EMS integration.
2026-10-09 08:23:21 +07:00

48 lines
1.6 KiB
Python

from types import SimpleNamespace
import pytest
from fastapi.testclient import TestClient
from sqlalchemy.exc import OperationalError
from ai_platform.bootstrap.app import create_app
from ai_platform.bootstrap.wiring import get_app_credential_use_cases, get_scoring_use_cases
from ai_platform.infrastructure.config.settings import Settings
@pytest.mark.parametrize("boundary", ["auth", "scoring"])
@pytest.mark.parametrize(
"error",
[
OperationalError(
"private-sql", {"credential": "private-key"}, Exception("private-storage-error")
),
ConnectionRefusedError("private-storage-error"),
],
)
def test_database_unavailability_returns_safe_503(canonical_request, boundary, error):
app = create_app(Settings())
async def authenticate(_raw):
return "omni-local"
async def credential_cases():
if boundary == "auth":
raise error
return SimpleNamespace(authenticate=authenticate)
async def scoring_cases():
raise error
app.dependency_overrides[get_app_credential_use_cases] = credential_cases
app.dependency_overrides[get_scoring_use_cases] = scoring_cases
# Dependencies are isolated; this test makes no DB connections or startup mutations.
client = TestClient(app)
headers = {
"Authorization": "Bearer private-key",
"Idempotency-Key": "f81c7c4e-a92a-4b19-8d7a-3a5c08eb4e6e",
}
response = client.post("/v1/lead-scoring/score", headers=headers, json=canonical_request)
assert response.status_code == 503
assert response.json() == {"detail": "Database unavailable"}
assert "private" not in response.text