research-link-ai / tests /test_system_api.py
MHamdan's picture
Deploy Research-Link-AI (Docker Space, offline demo)
a753e74 verified
Raw
History Blame Contribute Delete
3 kB
"""Tests for the system/config/papers API routes."""
import json
import pytest
from fastapi.testclient import TestClient
from researchlink.api.app import app
client = TestClient(app)
@pytest.fixture
def papers_dir(tmp_path, monkeypatch):
"""Point the API at a temp papers/ root with one module."""
mod = tmp_path / "2024-x"
mod.mkdir()
(mod / "metadata.json").write_text(json.dumps({
"slug": "2024-x", "conflicts": [],
"fields": {"title": {"value": "Paper X", "status": "verified"},
"year": {"value": 2024}, "authors": {"value": ["A"]}},
}), encoding="utf-8")
(mod / "summary.md").write_text("# Summary\n", encoding="utf-8")
monkeypatch.setenv("RESEARCHLINK_OUTPUT_DIR", str(tmp_path))
from researchlink import config
config.get_settings.__globals__["_settings"] = None
yield tmp_path
config.get_settings.__globals__["_settings"] = None
def test_health():
r = client.get("/api/health")
assert r.status_code == 200 and r.json()["backend"] == "ok"
def test_config_has_no_keys():
body = client.get("/api/config").text
assert "api_key" not in body and "sk-" not in body
data = json.loads(body)
assert data["mode"] in ("offline", "anthropic", "openai", "openrouter", "ollama", "custom")
def test_llm_status_safe():
d = client.get("/api/llm/status").json()
assert "tasks" in d and "api_key" not in d
def test_papers_list(papers_dir):
d = client.get("/api/papers").json()
slugs = [p["slug"] for p in d["papers"]]
assert "2024-x" in slugs
p = next(p for p in d["papers"] if p["slug"] == "2024-x")
assert p["title"] == "Paper X"
assert p["artifacts"]["summary.md"] == "generated" # exists
assert p["artifacts"]["review.md"] == "not-generated" # missing
def test_paper_detail(papers_dir):
d = client.get("/api/papers/2024-x").json()
assert d["metadata"]["slug"] == "2024-x"
assert d["artifacts"]["summary.md"]["content"].startswith("# Summary")
assert d["artifacts"]["summary.md"]["status"] == "generated"
def test_paper_detail_missing_artifact_placeholder(papers_dir):
d = client.get("/api/papers/2024-x").json()
review = d["artifacts"]["review.md"]
assert review["status"] == "not-generated"
assert "not-generated" in review["content"] # clean placeholder, never null
assert review["exists"] is False
def test_raw_artifact_and_traversal(papers_dir):
assert client.get("/api/papers/2024-x/raw/summary.md").text.startswith("# Summary")
assert client.get("/api/papers/2024-x/raw/nope.md").status_code == 404
assert client.get("/api/papers/2024-x/raw/..%2f..%2fetc").status_code in (400, 404)
def test_paper_detail_404(papers_dir):
assert client.get("/api/papers/does-not-exist").status_code == 404
def test_paper_traversal_blocked(papers_dir):
# encoded traversal should not escape the papers root
assert client.get("/api/papers/..%2f..%2fetc").status_code in (400, 404)