"""The HTTP surface, exercised with no network and no credentials.""" from __future__ import annotations import pytest from fastapi.testclient import TestClient from server import catalog from server.main import app @pytest.fixture(autouse=True) def no_credentials(monkeypatch): for var in ("HF_TOKEN", "HUGGING_FACE_HUB_TOKEN", "SPACE_ID", "ASE_ALLOW_SPACE_CREDITS"): monkeypatch.delenv(var, raising=False) # The suite must never pick up the developer's real key.txt. monkeypatch.setenv("ASE_KEY_FILE", "/nonexistent/ase-glm-test-key") @pytest.fixture def client(): return TestClient(app) def test_health(client): assert client.get("/api/health").json()["ok"] is True def test_config_lists_the_models_and_the_billing_mode(client): body = client.get("/api/config").json() ids = [m["id"] for m in body["models"]] assert "zai-org/GLM-5.3" in ids assert body["defaultModel"] == catalog.DEFAULT_MODEL assert body["auth"]["billsViewer"] is False assert "token" not in body["auth"] def test_every_catalog_model_is_well_formed(): for m in catalog.MODELS: j = m.to_json() assert "/" in j["id"], "an id must be owner/name to route" assert j["label"] and j["vendor"] assert j["providers"], f"{j['id']} has no route" assert j["contextTokens"] is None or j["contextTokens"] > 0 def sse_events(response) -> list[tuple[str, str]]: out, name, data = [], "message", [] for line in response.text.split("\n"): if line.startswith("event:"): name = line[6:].strip() elif line.startswith("data:"): data.append(line[5:].lstrip(" ")) elif not line.strip() and data: out.append((name, "\n".join(data))) name, data = "message", [] if data: out.append((name, "\n".join(data))) return out def test_a_missing_credential_is_reported_in_the_stream_not_as_a_4xx(client): # The client renders errors into the transcript. A 4xx would show as a # transport failure somewhere the reader is not looking. r = client.post("/api/chat", json={ "model": "zai-org/GLM-5.3", "messages": [{"role": "user", "content": "hi"}], }) assert r.status_code == 200 events = sse_events(r) assert events[0][0] == "error" assert "credential" in events[0][1].lower() def test_an_unknown_model_is_refused_before_any_upstream_call(client): r = client.post("/api/chat", json={ "model": "../../etc/passwd", "messages": [{"role": "user", "content": "hi"}], }) assert sse_events(r)[0][0] == "error" assert "Unknown model" in sse_events(r)[0][1] @pytest.mark.parametrize("body", [ {"model": "zai-org/GLM-5.3"}, {"model": "zai-org/GLM-5.3", "messages": []}, {"model": "zai-org/GLM-5.3", "messages": "not a list"}, ]) def test_a_request_with_no_messages_is_refused(client, body): assert sse_events(client.post("/api/chat", json=body))[0][0] == "error" def test_model_insight_rejects_a_model_not_in_the_catalog(client): r = client.get("/api/model", params={"id": "evil/model"}) assert r.status_code == 400 def test_an_unknown_api_path_is_a_404_not_the_index_page(client): # The SPA catch-all matches anything the declared routes did not. If it # answers an /api path, a typo'd endpoint returns 200 full of HTML and the # client reports a JSON parse error a long way from the cause. r = client.get("/api/does-not-exist") assert r.status_code == 404 assert "