Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BVPp2o6Mh2FZJr72yW3ofZ
97 lines
4.2 KiB
Python
97 lines
4.2 KiB
Python
"""M02 항목 목록(PLAN 39-5) — 칸 · 찾기 · 쪽(TS · `helper_m02_item_list.cjs`) ·
|
|
서버 목록 칸(임시 storage).
|
|
|
|
① 종류마다 칸(도면 · 면적산출 · 일위대가 · 항목 통째) · 빈 번호 「—」 · 합계 없으면 「—」 ·
|
|
고친 날 = 날짜만 · 찾기 = 보이는 칸 AND · 쪽 30 줄 · 넘친 쪽은 끝 쪽.
|
|
② 서버 `items` — `수정일`(도면 · 면적산출 · 일위대가 파일) · `labor`(번호 · 담은 로직 수 ·
|
|
합계 = 계산값.반영합.계) · 일위대가 파일이 없으면 null · 깨진 파일 · 수 아닌 합계도 목록은 뜸.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
from resources.tester import test_m02_tree as base
|
|
from resources.tester.test_m02_tree import Tree, _as
|
|
|
|
world = base.world # 같은 임시 storage 판
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def ts() -> dict:
|
|
proc = subprocess.run(
|
|
["node", os.path.join(HERE, "helper_m02_item_list.cjs")],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def test_종류마다_칸(ts):
|
|
assert ts["heads"]["structure"] == ["도번", "이름", "폴더", "단위", "고친 날"]
|
|
assert ts["heads"]["area"] == ["면적번", "이름", "폴더", "단위", "고친 날"]
|
|
assert ts["heads"]["labor"] == [
|
|
"일위대가번",
|
|
"이름",
|
|
"폴더",
|
|
"단위",
|
|
"담은 로직 수",
|
|
"합계",
|
|
"고친 날",
|
|
]
|
|
assert "규격" not in sum(ts["heads"].values(), []) and "층" not in sum(ts["heads"].values(), [])
|
|
|
|
|
|
def test_칸_값_빈_번호_합계_날짜(ts):
|
|
s, labor = ts["cells"]["structure"], ts["cells"]["labor"]
|
|
assert s[0] == ["SD-c1", "1.2m", "기슭막이 / 메쌓기", "m", "2026-10-01"]
|
|
assert s[2][0] == "—" and s[2][2] == "" # 빈 도번 · 맨 위 항목(폴더 없음)
|
|
assert labor[0][3:] == ["m", "3", "1,234,567", "2026-10-04"] # 합계 원 단위 반올림
|
|
assert labor[1][5] == "—" and labor[2][0] == labor[2][4] == "—" # 합계 없음 · 일위대가 없음
|
|
assert ts["cells"]["item"][0][-1] == "2026-10-04" # 항목 통째 = 가장 늦게 고친 날
|
|
|
|
|
|
def test_찾기_쪽(ts):
|
|
assert ts["find"] == ["c2"] # 낱말 둘 AND(폴더 · 이름 칸)
|
|
assert ts["findLabor"] == ["c1"] # 번호 칸도 찾음
|
|
assert ts["findNone"] == {"shown": [], "page": 1, "total": 0}
|
|
assert ts["page3"] == {"page": 3, "total": 65, "n": 5}
|
|
assert ts["pageOver"] == 3 and ts["pageEmpty"] == 1
|
|
|
|
|
|
def test_서버_목록_칸_수정일_labor(world):
|
|
t = Tree(_as(world), "personal")
|
|
t.do(op="add-item", 경로=["배수"], 이름="측구", 단위="m")
|
|
t.do(op="add-item", 경로=[], 이름="옹벽", 단위="m")
|
|
root = world["storage"] / "7" / "42" / "templates"
|
|
ditch, wall = t.item(["배수", "측구"]), t.item(["옹벽"])
|
|
assert set(ditch["수정일"]) >= {"structure", "area"}
|
|
assert len(ditch["수정일"]["structure"]) == 19 # 초 단위 ISO
|
|
assert (
|
|
ditch["labor"]["로직수"] == 0 and ditch["labor"]["합계"] is None
|
|
) # 새 열 = 빈 일위대가(39-1b)
|
|
(root / "labor").mkdir(exist_ok=True)
|
|
doc = {
|
|
"일위대가번": "SU-000001",
|
|
"담은로직": [{"로직": "GF000219"}, {"로직": "GF000137"}],
|
|
"계산값": {"반영합": {"계": 12345.6}},
|
|
}
|
|
(root / "labor" / f"{ditch['열']}.json").write_text(json.dumps(doc), encoding="utf-8")
|
|
(root / "labor" / f"{wall['열']}.json").write_text("{깨짐", encoding="utf-8")
|
|
rows = {r["열"]: r for r in t.client.get(t.url).json()["items"]}
|
|
assert rows[ditch["열"]]["labor"] == {"번호": "SU-000001", "로직수": 2, "합계": 12345.6}
|
|
assert "labor" in rows[ditch["열"]]["수정일"]
|
|
assert rows[wall["열"]]["labor"] == {"번호": None, "로직수": 0, "합계": None}
|
|
doc["계산값"] = {"반영합": {"계": "글"}}
|
|
(root / "labor" / f"{ditch['열']}.json").write_text(json.dumps(doc), encoding="utf-8")
|
|
again = {r["열"]: r for r in t.client.get(t.url).json()["items"]}
|
|
assert again[ditch["열"]]["labor"]["합계"] is None
|