zotero-kb/tests/test_writing.py
2026-04-16 13:34:39 +08:00

80 lines
3.2 KiB
Python

from pathlib import Path
from zotero_kb.cards import CardBuilder
from zotero_kb.config import AppConfig
from zotero_kb.projects import ProjectService
from zotero_kb.workspace import Workspace
from zotero_kb.writing import WritingService
from zotero_kb.zotero_reader import ZoteroItemRecord
class FakeLlmClient:
def generate_card(self, source_bundle: dict[str, object]) -> dict[str, object]:
title = str(source_bundle["title"])
if "Scoped" in title:
summary = "Project-scoped retrieval improves drafting support."
claims = ["Project scoping improves citation precision."]
hints = ["Use for scoped retrieval arguments."]
else:
summary = "Broad retrieval baseline for comparison."
claims = ["Baseline retrieval may drift."]
hints = ["Use as a contrast only."]
return {
"summary": summary,
"core_claims": claims,
"methods": ["Method details."],
"evidence": ["Evidence details."],
"quotable_passages": claims,
"writing_hints": hints,
"keywords": ["retrieval", "writing"],
}
def _build_item(item_key: str, title: str) -> ZoteroItemRecord:
return ZoteroItemRecord(
item_key=item_key,
title=title,
creators=["Alice Smith"],
year="2024",
item_type="journalArticle",
abstract=title,
tags=["retrieval"],
collection_paths=[["Theory", "Drafting"]],
notes=[title],
attachment_texts=[title],
)
def test_recommend_citations_only_reads_project_items(tmp_path: Path) -> None:
config = AppConfig(workspace_dir=tmp_path / "workspace", zotero_data_dir=tmp_path / "zotero")
workspace = Workspace(config)
workspace.create_project("thesis-ch2", "Thesis Chapter 2", "openai", "gpt-5-mini")
builder = CardBuilder(config.workspace_dir, FakeLlmClient())
builder.build_or_update(_build_item("PAPER0001", "Scoped Retrieval for Drafting"))
builder.build_or_update(_build_item("PAPER0002", "Broad Retrieval Baseline"))
project_service = ProjectService(config.workspace_dir)
project_service.add_items("thesis-ch2", ["PAPER0001"])
service = WritingService(config.workspace_dir)
result = service.recommend_citations("thesis-ch2", "support scoped retrieval during drafting")
assert [item["item_key"] for item in result["results"]] == ["PAPER0001"]
def test_generate_plan_returns_structured_sections(tmp_path: Path) -> None:
config = AppConfig(workspace_dir=tmp_path / "workspace", zotero_data_dir=tmp_path / "zotero")
workspace = Workspace(config)
workspace.create_project("thesis-ch2", "Thesis Chapter 2", "openai", "gpt-5-mini")
builder = CardBuilder(config.workspace_dir, FakeLlmClient())
builder.build_or_update(_build_item("PAPER0001", "Scoped Retrieval for Drafting"))
project_service = ProjectService(config.workspace_dir)
project_service.add_items("thesis-ch2", ["PAPER0001"])
service = WritingService(config.workspace_dir)
plan = service.generate_plan("thesis-ch2", "argue that project scoping improves drafting")
assert "sections" in plan
assert plan["sections"][0]["citations"][0]["item_key"] == "PAPER0001"