Files
daily-paper/tests/test_pages.py
T
Rain-Bus f7f1a4c0cb refactor: split monolithic phase tests into per-module test files
- rename test_admin_phase4.py -> test_admin.py, test_search.py -> test_searcher.py
- split test_phase5.py into test_cleaner, test_embedder, test_image_extractor, test_pages
- move schema tests from test_summarizer.py into dedicated test_schemas.py
- add sample_papers_range and sample_papers_with_summary fixtures in conftest
- update .gitignore to exclude all of data/
2026-06-06 00:34:30 +08:00

225 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""页面路由测试 — detail、trends、compare、graceful degradation。"""
from __future__ import annotations
from datetime import date
from unittest.mock import patch as upatch
import pytest
from app.config import settings
# ═══════════════════════════════════════════════════════════════════════
# Detail 页 & 相似论文
# ═══════════════════════════════════════════════════════════════════════
class TestDetailPage:
"""论文详情页测试。"""
def test_detail_page_renders(self, client, sample_papers_with_summary):
"""详情页正常渲染。"""
resp = client.get("/paper/2401.20001")
assert resp.status_code == 200
assert "测试论文" in resp.text or "Test Paper" in resp.text
def test_detail_page_not_found(self, client):
"""不存在的论文返回 404。"""
resp = client.get("/paper/nonexistent.99999")
assert resp.status_code == 404
# ═══════════════════════════════════════════════════════════════════════
# Similar API(详情页内联)
# ═══════════════════════════════════════════════════════════════════════
class TestDetailSimilarPapers:
"""详情页相似论文模块测试(CHROMA 关闭时的降级行为)。"""
def test_detail_page_renders_with_similar(self, client, sample_papers_with_summary):
"""详情页正常渲染(含相似论文模块)。"""
resp = client.get("/paper/2401.20001")
assert resp.status_code == 200
assert "测试论文" in resp.text or "Test Paper" in resp.text
def test_detail_page_not_found_similar(self, client):
"""不存在的论文返回 404。"""
resp = client.get("/paper/nonexistent.99999")
assert resp.status_code == 404
# ═══════════════════════════════════════════════════════════════════════
# Trends Dashboard
# ═══════════════════════════════════════════════════════════════════════
class TestTrendsDashboard:
"""趋势看板测试。"""
def test_trends_page_renders(self, client, sample_papers_with_summary):
"""趋势看板页面正常渲染。"""
resp = client.get("/trends")
assert resp.status_code == 200
assert "趋势看板" in resp.text
assert "chart" in resp.text.lower() or "Chart" in resp.text
def test_trends_api_returns_data(self, client, sample_papers_with_summary):
"""趋势 API 返回正确数据结构。"""
resp = client.get("/api/stats/trends")
assert resp.status_code == 200
data = resp.json()
assert "daily_counts" in data
assert "top_tags" in data
assert "upvotes_dist" in data
assert "summary_completion" in data
assert isinstance(data["daily_counts"], list)
assert isinstance(data["top_tags"], list)
assert isinstance(data["upvotes_dist"], list)
assert isinstance(data["summary_completion"], list)
def test_trends_api_daily_counts(self, client, sample_papers_with_summary):
"""每日论文数量数据正确。"""
# 使用测试数据的日期范围
with upatch("app.services.trends.date") as mock_date:
mock_date.today.return_value = date(2024, 1, 20)
mock_date.side_effect = lambda *a, **kw: date(*a, **kw)
resp = client.get("/api/stats/trends")
data = resp.json()
assert len(data["daily_counts"]) == 5
for item in data["daily_counts"]:
assert "date" in item
assert "count" in item
assert item["count"] == 1
def test_trends_api_top_tags(self, client, sample_papers_with_summary):
"""热门标签数据正确。"""
resp = client.get("/api/stats/trends")
data = resp.json()
tags = {t["tag"]: t["count"] for t in data["top_tags"]}
assert "NLP" in tags
assert tags["NLP"] == 5 # 所有论文都有 NLP
def test_trends_api_summary_completion(self, client, sample_papers_with_summary):
"""总结完成率数据正确。"""
resp = client.get("/api/stats/trends")
data = resp.json()
statuses = {s["status"]: s["count"] for s in data["summary_completion"]}
assert "done" in statuses
assert statuses["done"] == 4 # 4 篇已完成
def test_trends_empty_db(self, client):
"""无数据时不崩溃。"""
resp = client.get("/api/stats/trends")
assert resp.status_code == 200
data = resp.json()
assert data["daily_counts"] == []
assert data["top_tags"] == []
# ═══════════════════════════════════════════════════════════════════════
# Compare Page
# ═══════════════════════════════════════════════════════════════════════
class TestComparePage:
"""论文对比页测试。"""
def test_compare_page_no_ids(self, client):
"""无 ID 时显示输入表单。"""
resp = client.get("/compare")
assert resp.status_code == 200
assert "对比" in resp.text
def test_compare_page_with_ids(self, client, sample_papers_with_summary):
"""对比多篇论文正常渲染。"""
resp = client.get("/compare?ids=2401.20001,2401.20002")
assert resp.status_code == 200
assert "2401.20001" in resp.text
assert "2401.20002" in resp.text
# 应包含对比字段
assert "一句话摘要" in resp.text
assert "研究问题" in resp.text
def test_compare_page_max_5(self, client, sample_papers_with_summary):
"""最多 5 篇。"""
ids = "2401.20001,2401.20002,2401.20003,2401.20004,2401.20005"
resp = client.get(f"/compare?ids={ids}")
assert resp.status_code == 200
def test_compare_page_over_5_truncates(self, client, sample_papers_with_summary):
"""超过 5 篇截断。"""
ids = "2401.20001,2401.20002,2401.20003,2401.20004,2401.20005,2401.20006"
resp = client.get(f"/compare?ids={ids}")
assert resp.status_code == 200
def test_compare_page_invalid_ids(self, client):
"""无效 ID 时显示空结果。"""
resp = client.get("/compare?ids=nonexistent.99999")
assert resp.status_code == 200
def test_compare_page_shows_no_summary_placeholder(self, client, sample_papers_with_summary):
"""无总结的论文显示占位文本。"""
# 2401.20005 没有 summarystatus=pending
resp = client.get("/compare?ids=2401.20005")
assert resp.status_code == 200
assert "暂无总结" in resp.text
# ═══════════════════════════════════════════════════════════════════════
# Nav Bar
# ═══════════════════════════════════════════════════════════════════════
class TestNavBar:
"""导航栏测试。"""
def test_nav_includes_trends_link(self, client):
"""导航栏应包含趋势链接。"""
resp = client.get("/search")
assert resp.status_code == 200
assert "/trends" in resp.text
def test_nav_includes_compare_implicitly(self, client):
"""compare 页面可访问。"""
resp = client.get("/compare")
assert resp.status_code == 200
# ═══════════════════════════════════════════════════════════════════════
# Graceful DegradationCHROMA_ENABLED=false
# ═══════════════════════════════════════════════════════════════════════
class TestGracefulDegradation:
"""CHROMA_ENABLED=false 时优雅降级测试。"""
def test_search_works_without_chroma(self, client, monkeypatch, sample_papers_with_summary):
"""CHROMA 关闭时 FTS5 搜索正常工作。"""
monkeypatch.setattr(settings, "CHROMA_ENABLED", False)
resp = client.get("/search?q=Test")
assert resp.status_code == 200
assert "Test Paper" in resp.text or "测试论文" in resp.text
def test_detail_works_without_chroma(self, client, monkeypatch, sample_papers_with_summary):
"""CHROMA 关闭时详情页正常工作。"""
monkeypatch.setattr(settings, "CHROMA_ENABLED", False)
resp = client.get("/paper/2401.20001")
assert resp.status_code == 200
def test_trends_works_without_chroma(self, client, monkeypatch, sample_papers_with_summary):
"""CHROMA 关闭时趋势看板正常工作。"""
monkeypatch.setattr(settings, "CHROMA_ENABLED", False)
resp = client.get("/trends")
assert resp.status_code == 200
def test_compare_works_without_chroma(self, client, monkeypatch, sample_papers_with_summary):
"""CHROMA 关闭时对比页正常工作。"""
monkeypatch.setattr(settings, "CHROMA_ENABLED", False)
resp = client.get("/compare?ids=2401.20001,2401.20002")
assert resp.status_code == 200