Files
Aislo/resources/tester/test_815_2_alias_column.py
T
eomsangdonandClaude Opus 5.5 4549e28fa5 feat(815-2): M01 요소 표 「별칭」 한 열 · 마스터 기계 별칭 다섯 옮김
- 인력 · 기계 · 재료 자재 · 유가전력 표에 비고 앞 「별칭」 열 — 눌러 고침 · 콤마로 여러 개 · 빈 글이면 칸 없음
- 저장 길 = 그대로 `/api/m01/save`(서버가 앞뒤 빈칸 뗌 · 빈 글 = 칸 지움 · 그 줄만 다시 씀)
- check_master — 요소 줄 열 한 벌 밖 덧칸 `별칭` 허용(빈 글 · 글 아님은 흠)
- 마스터 기계 별칭 다섯(맞춤.json) → 기계 줄 15 개 `별칭` · 옛 마스터 장부 파일 걷음
- M01 로직 1,513 셈 지문 전후 같음
- 새 시험 test_815_2_alias_column.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:20:09 +09:00

105 lines
4.1 KiB
Python

"""PLAN 815-2 — M01 요소 「별칭」 한 열(요구 764 · 765).
① 별칭 칸 저장 = 그 줄만 바뀜 · 앞뒤 빈칸 뗌 · 빈 글이면 칸 없음(임시 사본 폴더만)
② M01 길은 시스템 관리자만(아니면 403)
③ 마스터 기계 별칭 다섯 → 기계 줄 `별칭` · 옛 장부 파일 걷음
"""
from __future__ import annotations
import json
import shutil
from pathlib import Path
import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
from common_util import common_util_auth as auth
from M01_MasterData import M01_MasterData_Router as router_module
from M01_MasterData import M01_MasterData_Store as store
ROOT = Path(__file__).resolve().parents[2]
REAL = store.FOLDER
MACHINE = "기계.json"
KEY = "EQ000001"
FIVE = {
"EQ000192": "아스팔트페이버(피니셔)",
"EQ000193": "아스팔트페이버(피니셔)",
**{f"EQ000{n}": "디젤 엔진" for n in range(497, 508)},
"EQ000400": "워터제트",
"EQ000425": "버킷준설기",
"EQ000248": "바이브레이트 봉상후렉시블",
}
@pytest.fixture
def copy(tmp_path: Path, monkeypatch) -> Path:
for path in REAL.glob("*.json"):
if not path.name.startswith("_") or path.name == store.mk.BOOK.name:
shutil.copy(path, tmp_path / path.name)
monkeypatch.setattr(store, "FOLDER", tmp_path)
return tmp_path
def _app(role: str = "SYSTEM_ADMIN") -> TestClient:
app = FastAPI()
app.dependency_overrides[auth.verify_session] = lambda: {
"user_id": 1,
"name": "시험",
"role": role,
"company_id": 1,
}
deps = [Depends(auth.verify_session), Depends(auth.require_system_admin)]
app.include_router(router_module.router, dependencies=deps)
return TestClient(app)
def _save_alias(client: TestClient, text: str) -> None:
one = client.get("/api/m01/rows", params={"file": MACHINE, "q": KEY}).json()
row = next(r for r in one["rows"] if r["키"] == KEY)
part = {
"file": MACHINE,
"version": one["version"],
"changes": [{"op": "edit", "key": KEY, "row": {**row, "별칭": text}}],
}
res = client.post("/api/m01/save", json={"files": [part]})
assert res.status_code == 200, res.text
def _around(text: str) -> tuple[str, str, str]:
"""(그 줄 앞 글, 그 줄 글, 뒤 글)."""
start = text.rfind("{", 0, text.index(f'"키": "{KEY}"'))
_, end = json.JSONDecoder().raw_decode(text, start)
return text[:start], text[start:end], text[end:]
def test_별칭_저장_그_줄만_빈칸이면_칸_없음(copy: Path) -> None:
client = _app()
before = (copy / MACHINE).read_bytes()
_save_alias(client, " 시험별칭A, 시험별칭B ")
after = (copy / MACHINE).read_bytes().decode("utf-8")
row = next(r for r in json.loads(after)["줄"] if r["키"] == KEY)
assert row["별칭"] == "시험별칭A, 시험별칭B" # 글 그대로 · 앞뒤 빈칸만 뗌
old, new = _around(before.decode("utf-8")), _around(after)
assert old[0] == new[0] and old[2] == new[2] # 그 줄 밖 글 · 서식 그대로
assert json.loads(new[1]) == {**json.loads(old[1]), "별칭": "시험별칭A, 시험별칭B"}
_save_alias(client, " ")
last = _around((copy / MACHINE).read_bytes().decode("utf-8"))
assert last[0] == old[0] and last[2] == old[2]
assert json.loads(last[1]) == json.loads(old[1]) # 빈 글 = 칸 없음 = 처음 값
def test_M01_길은_시스템_관리자만() -> None:
for role in ("USER", "COMPANY_ADMIN"):
res = _app(role).post("/api/m01/save", json={"files": []})
assert res.status_code == 403
main = (ROOT / "main.py").read_text(encoding="utf-8")
assert "include_router(m01_master_data_router, dependencies=system_admin_only)" in main
def test_마스터_기계_별칭_다섯_옮김_장부_걷음() -> None:
rows = {r["키"]: r for r in json.loads((REAL / MACHINE).read_text(encoding="utf-8"))["줄"]}
assert {k: r.get("별칭") for k, r in rows.items() if r.get("별칭")} == FIVE
assert not (ROOT / "resources" / "master_template" / "실무자료" / "맞춤.json").exists()