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 "手动搜索" in response.text assert "renderMarkdownReport" in response.text assert "自动记录" not in response.text assert "采集今日情报" not in response.text def test_manual_agent_run_endpoint_starts_background_job(monkeypatch) -> None: # 手动搜索入口复用调度任务,方便验证每轮候选和入库数量。 monkeypatch.setenv("SIGNALSCOUT_ENV", "test") get_settings.cache_clear() started = [] 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) def fake_run_scheduled_job(settings): started.append(settings.env) def override_get_db(): # 手动搜索测试只验证接口调度行为,运行中状态查询使用内存库。 db = TestingSessionLocal() try: yield db finally: db.close() monkeypatch.setattr("app.api.routes.run_scheduled_job", fake_run_scheduled_job) app = create_app() app.dependency_overrides[get_db] = override_get_db with TestClient(app) as client: response = client.post("/agent/runs/daily") get_settings.cache_clear() assert response.status_code == 200 assert response.json()["status"] == "started" assert started == ["test"] 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"]