"""模型网关 endpoint 覆盖 API 测试(api-spec §4.4,DB 优先于 .env/yaml)。""" from collections.abc import AsyncGenerator import pytest from httpx import ASGITransport, AsyncClient from app.main import app @pytest.fixture async def client() -> AsyncGenerator[AsyncClient, None]: transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as http_client: yield http_client def _first_endpoint(gateway: dict) -> tuple[str, str]: model = gateway["models"][0] return model["name"], model["endpoints"][0]["name"] @pytest.mark.asyncio async def test_list_models_has_endpoint_override_fields(client: AsyncClient) -> None: resp = await client.get("/api/v1/settings/models") assert resp.status_code == 200 ep = resp.json()["models"][0]["endpoints"][0] assert "priority" in ep assert "is_overridden" in ep assert "has_url_override" in ep assert "has_key_override" in ep assert ep["is_overridden"] is False @pytest.mark.asyncio async def test_patch_endpoint_status_override(client: AsyncClient) -> None: gateway = (await client.get("/api/v1/settings/models")).json() model, endpoint = _first_endpoint(gateway) resp = await client.patch( f"/api/v1/settings/models/{model}/endpoints/{endpoint}", json={"status": "inactive"}, ) assert resp.status_code == 200 body = resp.json() assert body["is_overridden"] is True assert body["status"] == "inactive" # GET 反映覆盖 gateway2 = (await client.get("/api/v1/settings/models")).json() eps = [m for m in gateway2["models"] if m["name"] == model][0]["endpoints"] ep = [e for e in eps if e["name"] == endpoint][0] assert ep["is_overridden"] is True assert ep["status"] == "inactive" @pytest.mark.asyncio async def test_patch_endpoint_key_override_redacted(client: AsyncClient) -> None: gateway = (await client.get("/api/v1/settings/models")).json() model, endpoint = _first_endpoint(gateway) resp = await client.patch( f"/api/v1/settings/models/{model}/endpoints/{endpoint}", json={"api_key": "sk-test-secret-value"}, ) assert resp.status_code == 200 assert resp.json()["has_key_override"] is True # 脱敏:响应体不含 api_key 原值 assert "sk-test-secret-value" not in resp.text @pytest.mark.asyncio async def test_patch_endpoint_not_found(client: AsyncClient) -> None: resp = await client.patch( "/api/v1/settings/models/no_such_model/endpoints/primary", json={"status": "inactive"}, ) assert resp.status_code == 404