feat(M02): 원문 다운로드 — 제목 행 단추 · pdf 통째 길(책 이름만) · 원문 읽기 M02 대리 길(85-4)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
This commit is contained in:
2026-10-08 12:09:49 +09:00
co-authored by Claude Opus 5.5
parent 084b52001e
commit eaeff398dc
4 changed files with 121 additions and 7 deletions
+50
View File
@@ -104,3 +104,53 @@ def test_item_all_marked() -> None:
total += 1
missing += not any(f.get("item") for f in make.source(src)["found"])
assert total >= 30 and missing == 0, (total, missing)
def _m02_client(role: str = "USER") -> TestClient:
from common_util.common_util_auth import verify_session
from M02_MasterTemplete import M02_MasterTemplete_Router_Combos as combos
app = FastAPI()
app.include_router(combos.router)
app.dependency_overrides[verify_session] = lambda: {"user_id": 42, "role": role}
return TestClient(app)
def test_m02_원문_대리_길과_pdf() -> None:
"""85-4 — 일반 사용자도 원문(M01 길과 같은 몸) · pdf 통째(책 이름만 · 그 밖 400 · 한글 파일명)."""
from M02_MasterTemplete import M02_MasterTemplete_Router_Combos as combos
client = _m02_client()
got = client.get("/api/m02/logic-lib/source", params={"src": "산림품셈 3-1"})
assert got.status_code == 200 and got.json() == make.source("산림품셈 3-1")
for book in ("건설", "산림"):
res = client.get("/api/m02/logic-lib/source-pdf", params={"book": book})
assert res.status_code == 200 and res.headers["content-type"] == "application/pdf"
assert (
len(res.content) == combos.SOURCE_PDF[book].stat().st_size
and res.content[:4] == b"%PDF"
)
assert "filename*=utf-8''" in res.headers["content-disposition"]
again = client.get(
"/api/m02/logic-lib/source-pdf",
params={"book": book},
headers={"if-none-match": res.headers["etag"]},
)
assert again.status_code == 304
for bad in ("../../main.py", "건설품셈", ""):
assert client.get("/api/m02/logic-lib/source-pdf", params={"book": bad}).status_code == 400
def test_원문_패널_길_주입() -> None:
"""85-4 — M01 은 옛 길 그대로(기본값) · M02 일위대가 상세는 M02 길 + pdf."""
from pathlib import Path
root = Path(__file__).resolve().parents[2]
src = (root / "M01_MasterData/M01_MasterData_UI_LogicLab_Source.ts").read_text(encoding="utf-8")
assert 'opts.path ?? "/m01/logic/source"' in src
side = (root / "M01_MasterData/M01_MasterData_UI_LogicLab_Side.ts").read_text(encoding="utf-8")
assert "createSourceView()" in side
labor = (root / "M02_MasterTemplete/M02_MasterTemplete_Labor_Detail.ts").read_text(
encoding="utf-8"
)
assert 'path: "/m02/logic-lib/source"' in labor and 'pdf: "/m02/logic-lib/source-pdf"' in labor