193 lines
8.1 KiB
Python
193 lines
8.1 KiB
Python
"""用户数据服务 + 路由测试 — 收藏、阅读状态、笔记。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from app.services.user_data import (
|
|
get_note,
|
|
save_note,
|
|
set_reading_status,
|
|
toggle_bookmark,
|
|
)
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
# 收藏服务测试
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
class TestBookmarkService:
|
|
def test_toggle_bookmark_add(self, db_session, sample_paper):
|
|
result = toggle_bookmark(db_session, "2401.12345")
|
|
assert result["bookmarked"] is True
|
|
assert result["arxiv_id"] == "2401.12345"
|
|
|
|
def test_toggle_bookmark_remove(self, db_session, sample_paper):
|
|
toggle_bookmark(db_session, "2401.12345")
|
|
result = toggle_bookmark(db_session, "2401.12345")
|
|
assert result["bookmarked"] is False
|
|
|
|
def test_toggle_bookmark_not_found(self, db_session):
|
|
result = toggle_bookmark(db_session, "nonexistent")
|
|
assert "error" in result
|
|
assert result["error"] == "not_found"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
# 阅读状态服务测试
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
class TestReadingStatusService:
|
|
def test_set_reading_status(self, db_session, sample_paper):
|
|
result = set_reading_status(db_session, "2401.12345", "read_summary")
|
|
assert result["status"] == "read_summary"
|
|
assert result["arxiv_id"] == "2401.12345"
|
|
|
|
def test_set_reading_status_invalid(self, db_session, sample_paper):
|
|
result = set_reading_status(db_session, "2401.12345", "invalid_status")
|
|
assert "error" in result
|
|
assert result["error"] == "invalid_status"
|
|
|
|
def test_update_existing_status(self, db_session, sample_paper):
|
|
set_reading_status(db_session, "2401.12345", "skimmed")
|
|
result = set_reading_status(db_session, "2401.12345", "read_full")
|
|
assert result["status"] == "read_full"
|
|
|
|
def test_set_reading_status_not_found(self, db_session):
|
|
result = set_reading_status(db_session, "nonexistent", "unread")
|
|
assert "error" in result
|
|
assert result["error"] == "not_found"
|
|
|
|
def test_all_valid_statuses(self, db_session, sample_paper):
|
|
for status in ("unread", "skimmed", "read_summary", "read_full"):
|
|
result = set_reading_status(db_session, "2401.12345", status)
|
|
assert result["status"] == status
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
# 笔记服务测试
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
class TestNoteService:
|
|
def test_save_and_get_note(self, db_session, sample_paper):
|
|
save_note(db_session, "2401.12345", "这是一条测试笔记")
|
|
result = get_note(db_session, "2401.12345")
|
|
assert result["content"] == "这是一条测试笔记"
|
|
assert result["arxiv_id"] == "2401.12345"
|
|
assert result["updated_at"] is not None
|
|
|
|
def test_update_note(self, db_session, sample_paper):
|
|
save_note(db_session, "2401.12345", "旧笔记")
|
|
save_note(db_session, "2401.12345", "新笔记")
|
|
result = get_note(db_session, "2401.12345")
|
|
assert result["content"] == "新笔记"
|
|
|
|
def test_get_note_empty(self, db_session, sample_paper):
|
|
result = get_note(db_session, "2401.12345")
|
|
assert result["content"] == ""
|
|
assert result["updated_at"] is None
|
|
|
|
def test_get_note_paper_not_found(self, db_session):
|
|
result = get_note(db_session, "nonexistent")
|
|
assert result is None
|
|
|
|
def test_save_note_paper_not_found(self, db_session):
|
|
result = save_note(db_session, "nonexistent", "内容")
|
|
assert "error" in result
|
|
assert result["error"] == "not_found"
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
# 用户数据路由 HTTP 测试
|
|
# ═══════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
class TestUserDataRoutes:
|
|
"""HTTP 级别的用户数据 API 测试。"""
|
|
|
|
def test_bookmark_toggle_api(self, client, sample_paper):
|
|
"""POST /api/bookmark/{arxiv_id} 切换收藏。"""
|
|
resp = client.post("/api/bookmark/2401.12345")
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["bookmarked"] is True
|
|
|
|
# 再次切换 → 取消
|
|
resp2 = client.post("/api/bookmark/2401.12345")
|
|
assert resp2.status_code == 200
|
|
data2 = resp2.json()
|
|
assert data2["bookmarked"] is False
|
|
|
|
def test_bookmark_htmx_returns_html(self, client, sample_paper):
|
|
"""HTMX 请求返回 HTML 片段。"""
|
|
headers = {"HX-Request": "true"}
|
|
resp = client.post("/api/bookmark/2401.12345", headers=headers)
|
|
assert resp.status_code == 200
|
|
assert "btn-bookmark" in resp.text
|
|
assert "★" in resp.text
|
|
|
|
def test_bookmark_not_found(self, client):
|
|
"""收藏不存在的论文返回 404。"""
|
|
resp = client.post("/api/bookmark/nonexistent")
|
|
assert resp.status_code == 404
|
|
|
|
def test_reading_status_api(self, client, sample_paper):
|
|
"""POST /api/reading-status/{arxiv_id} 更新状态。"""
|
|
resp = client.post(
|
|
"/api/reading-status/2401.12345",
|
|
json={"status": "read_summary"},
|
|
)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["status"] == "read_summary"
|
|
|
|
def test_reading_status_invalid(self, client, sample_paper):
|
|
"""无效状态返回 422。"""
|
|
resp = client.post(
|
|
"/api/reading-status/2401.12345",
|
|
json={"status": "invalid"},
|
|
)
|
|
assert resp.status_code == 422
|
|
|
|
def test_reading_status_not_found(self, client):
|
|
"""不存在的论文返回 404。"""
|
|
resp = client.post(
|
|
"/api/reading-status/nonexistent",
|
|
json={"status": "unread"},
|
|
)
|
|
assert resp.status_code == 404
|
|
|
|
def test_note_get_api(self, client, sample_paper):
|
|
"""GET /api/note/{arxiv_id} 返回笔记。"""
|
|
resp = client.get("/api/note/2401.12345")
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["content"] == ""
|
|
|
|
def test_note_save_api(self, client, sample_paper):
|
|
"""POST /api/note/{arxiv_id} 保存笔记。"""
|
|
resp = client.post(
|
|
"/api/note/2401.12345",
|
|
json={"content": "Markdown **笔记**"},
|
|
)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["content"] == "Markdown **笔记**"
|
|
assert data["updated_at"] is not None
|
|
|
|
# 读取确认
|
|
resp2 = client.get("/api/note/2401.12345")
|
|
assert resp2.json()["content"] == "Markdown **笔记**"
|
|
|
|
def test_note_not_found(self, client):
|
|
"""不存在的论文返回 404。"""
|
|
resp = client.get("/api/note/nonexistent")
|
|
assert resp.status_code == 404
|
|
|
|
resp2 = client.post(
|
|
"/api/note/nonexistent",
|
|
json={"content": "test"},
|
|
)
|
|
assert resp2.status_code == 404
|