Files
Aislo/resources/tester/test_b08_library_share.py
T
eomsangdonandClaude Opus 5 0bb14ce2b3 feat(b08): 라이브러리 공유 — [동료에게 보내기] 같은 회사 동료의 「받음」 단으로 복사(개인 단을 안 덮음 · 보낸 사람 기록 · 출처 공사명 그대로) · 받음 단 항목도 가져오기·복제 가능 · 회사 밖·나에게·내 것 아닌 항목은 막음(브레인 판정 ①)
화면: 복제로 만든 개인 항목 선택 → 동료 목록 받음 → 확인창 「받는 쪽 목록에 받음으로 뜸 · 그 사람 것은 안 덮음」 · 공용 storage 라 취소(동료 폴더 안 생김 확인) · 개인 항목 지워 되돌림 · 쓰기는 임시 storage 시험

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
2026-09-14 18:25:22 +09:00

109 lines
4.6 KiB
Python

"""라이브러리 공유 — 같은 회사 동료에게 내 항목을 복사해 보냄 (PLAN 4장 · 2026-09-14 브레인 판정 ①).
⚠ 받는 쪽이 모르게 들어가지 않음 — 받은 항목은 그 사람 개인 단을 덮지 않고 **「받음」 단**에 따로 섬
(개인 단은 종류당 하나라 그대로 넣으면 동료가 고친 내 것이 조용히 덮임). 받은 뒤 가져오기·복제는 받는 사람 몫.
⚠ 같은 회사 안만 · 출처 공사명은 그대로(같은 회사라 그 공사를 앎 · 판정 ③).
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
import B08_Quantity.B08_Quantity_Engine_StructureLibrary as library_module # noqa: E402
import B08_Quantity.B08_Quantity_Router_StmateLibrary as router_module # noqa: E402
from B08_Quantity.B08_Quantity_Engine_StructureTemplate import load_template # noqa: E402
from common_util.common_util_auth import verify_session # noqa: E402
LIB = "/api/projects/33333333-3333-3333-3333-333333333333/quantity/structure-sheets/library"
MINE = "AX-ST-0000aaaa"
@pytest.fixture()
def client(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> TestClient:
monkeypatch.setattr(library_module, "STORAGE_BASE_DIR", str(tmp_path / "storage"))
item = {
**load_template("masonry_wet"),
"code": MINE,
"library_tier": "personal",
"name": "내 돌쌓기",
"origin": {"project": "봉화 임도"},
}
folder = tmp_path / "storage" / "7" / "42" / "library"
folder.mkdir(parents=True)
(folder / f"{MINE}.json").write_text(json.dumps(item), encoding="utf-8")
# 받는 사람(43)도 같은 종류 내 것이 있음 — 덮이면 안 됨
theirs = tmp_path / "storage" / "7" / "43" / "library"
theirs.mkdir(parents=True)
(theirs / "AX-ST-0000bbbb.json").write_text(
json.dumps({**item, "code": "AX-ST-0000bbbb", "name": "동료 것"}), encoding="utf-8"
)
async def members(company_id: int) -> list[dict]:
assert company_id == 7
return [
{"id": 42, "name": "나", "email": "me@x"},
{"id": 43, "name": "동료", "email": "you@x"},
]
monkeypatch.setattr(router_module, "_company_members", members)
app = FastAPI()
app.include_router(router_module.router)
app.dependency_overrides[verify_session] = lambda: {"company_id": 7, "user_id": 42}
return TestClient(app)
def test_동료_목록은_같은_회사에서_나를_뺀다(client: TestClient) -> None:
body = client.get(f"{LIB}/colleagues").json()
assert body["colleagues"] == [{"id": 43, "name": "동료"}]
def test_보내면_받는_쪽_받음_단에_서고_그_사람_개인_단은_안_덮인다(
client: TestClient, tmp_path: Path
) -> None:
sent = client.put(
f"{LIB}/share", json={"type_id": "masonry_wet", "code": MINE, "to_user_id": 43}
)
assert sent.status_code == 200, sent.text
received = tmp_path / "storage" / "7" / "43" / "library_received" / f"{MINE}.json"
saved = json.loads(received.read_text(encoding="utf-8"))
assert saved["library_tier"] == "received"
assert saved["received_from"]["name"] == "나" and saved["origin"]["project"] == "봉화 임도"
theirs = tmp_path / "storage" / "7" / "43" / "library" / "AX-ST-0000bbbb.json"
assert json.loads(theirs.read_text(encoding="utf-8"))["name"] == "동료 것"
dirs = library_module.tier_dirs(7, 43)
listed = library_module.list_items(dirs, "masonry_wet")
assert [i["tier"] for i in listed][:2] == ["personal", "received"]
def test_회사_밖이나_내_것_아닌_항목은_못_보낸다(client: TestClient) -> None:
stranger = client.put(
f"{LIB}/share", json={"type_id": "masonry_wet", "code": MINE, "to_user_id": 99}
)
assert stranger.status_code == 404
missing = client.put(
f"{LIB}/share", json={"type_id": "masonry_wet", "code": "AX-ST-0000cccc", "to_user_id": 43}
)
assert missing.status_code == 404
myself = client.put(
f"{LIB}/share", json={"type_id": "masonry_wet", "code": MINE, "to_user_id": 42}
)
assert myself.status_code == 400
def test_화면에_보내기_단추와_받음_표시() -> None:
ui = (ROOT / "B08_Quantity" / "B08_Quantity_UI_StructureSheet_Library.ts").read_text(
encoding="utf-8"
)
assert "/share" in ui and "/colleagues" in ui and "동료에게 보내기" in ui
assert 'received: "받음"' in ui