Files
signalscout-backend/tests/test_api_health.py
T
2026-07-08 23:39:41 +08:00

126 lines
4.8 KiB
Python

from datetime import datetime
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool
from app.core.config import get_settings
from app.db.models import AgentRun, Base, Signal
from app.db.session import get_db
from app.main import create_app
def test_health_endpoint_returns_app_identity(monkeypatch) -> None:
# 健康检查只暴露服务身份,不触发Agent运行或数据库写入。
monkeypatch.setenv("SIGNALSCOUT_ENV", "test")
get_settings.cache_clear()
with TestClient(create_app()) as client:
response = client.get("/health")
get_settings.cache_clear()
assert response.status_code == 200
assert response.json()["status"] == "ok"
assert response.json()["app"] == "SignalScout"
def test_home_page_returns_dashboard_shell(monkeypatch) -> None:
# 根路径应该展示业务工作台,而不是返回接口404。
monkeypatch.setenv("SIGNALSCOUT_ENV", "test")
get_settings.cache_clear()
with TestClient(create_app()) as client:
response = client.get("/")
get_settings.cache_clear()
assert response.status_code == 200
assert "SignalScout" in response.text
assert "今日 AI 信号" in response.text
assert "renderMarkdownReport" in response.text
assert "自动记录" not in response.text
assert "采集今日情报" not in response.text
def test_manual_agent_run_endpoint_is_not_exposed(monkeypatch) -> None:
# Agent只通过后台调度器自动运行,HTTP API不提供手动启动入口。
monkeypatch.setenv("SIGNALSCOUT_ENV", "test")
get_settings.cache_clear()
with TestClient(create_app()) as client:
response = client.post("/agent/runs/daily")
stream_response = client.post("/agent/runs/daily/stream")
get_settings.cache_clear()
assert response.status_code == 404
assert stream_response.status_code == 404
def test_dashboard_returns_news_and_github_signals_separately(monkeypatch) -> None:
# 仪表盘接口直接返回分组后的业务数据,前端不再用标题或来源名自行猜测分类。
monkeypatch.setenv("SIGNALSCOUT_ENV", "test")
get_settings.cache_clear()
engine = create_engine(
"sqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
future=True,
)
TestingSessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)
Base.metadata.create_all(engine)
with TestingSessionLocal() as session:
run = AgentRun(status="completed", started_at=datetime(2026, 7, 8, 8, 0), request_payload={})
session.add(run)
session.flush()
session.add_all(
[
Signal(
run_id=run.id,
source_type="news",
topic="AI 新闻",
title="New model release",
summary="模型发布动态。",
source_url="https://example.com/news",
source_url_hash="news-hash",
source_name="Example News",
published_at=datetime(2026, 7, 8, 9, 0),
importance=4,
entities=["Example"],
),
Signal(
run_id=run.id,
source_type="github",
topic="GitHub 热门项目",
title="example/agent-kit",
summary="开源项目动态。",
source_url="https://github.com/example/agent-kit",
source_url_hash="github-hash",
source_name="GitHub",
published_at=datetime(2026, 7, 8, 10, 0),
importance=5,
entities=["example/agent-kit"],
),
]
)
session.commit()
def override_get_db():
# 测试依赖把接口请求限制在内存库里,避免触碰开发数据库。
db = TestingSessionLocal()
try:
yield db
finally:
db.close()
app = create_app()
app.dependency_overrides[get_db] = override_get_db
with TestClient(app) as client:
dashboard_response = client.get("/dashboard")
github_response = client.get("/signals", params={"source_type": "github"})
get_settings.cache_clear()
dashboard = dashboard_response.json()
assert dashboard_response.status_code == 200
assert [item["source_type"] for item in dashboard["news_signals"]] == ["news"]
assert [item["source_type"] for item in dashboard["github_signals"]] == ["github"]
assert github_response.status_code == 200
assert [item["title"] for item in github_response.json()] == ["example/agent-kit"]