Files
Aislo/resources/tester/test_302_3_print_quantity.py
T

190 lines
8.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""302-3 인쇄 미리보기 「수량산출」 — B08 탭 표를 화면 없이 PrintSheet 로 모음.
견본 = 검증_sub8 서버 GET 응답(구조물 집계표만 손 견본 · `fixtures/b08_302_3_print_quantity.json`).
`helper_302_3_print_quantity.mjs` 가 화면 코드를 node 로 묶어 같은 응답 · 같은 캐시로
모으기(`collectQuantitySheets`) 와 B08 화면이 부르는 표 짜기를 나란히 냄 → 쪽 차례 · 이름 · 열 머리 · 줄 대조.
"""
from __future__ import annotations
import base64
import copy
import json
import shutil
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
HELPER = Path(__file__).with_name("helper_302_3_print_quantity.mjs")
FIXTURE = json.loads(
(Path(__file__).with_name("fixtures") / "b08_302_3_print_quantity.json").read_text("utf-8")
)
PNG = b"\x89PNG\r\n\x1a\n302-3"
B08 = ROOT / "B08_Quantity"
def _run(responses: dict, drafts: list | None = None, screen: bool = True) -> dict:
if shutil.which("node") is None:
pytest.skip("node 가 없음")
job = {
"project": "p302",
"responses": responses,
"image_b64": base64.b64encode(PNG).decode(),
"drafts": drafts or [],
"screen": screen,
}
out = subprocess.run(
["node", str(HELPER), str(ROOT)],
input=json.dumps(job, ensure_ascii=False),
cwd=ROOT,
capture_output=True,
text=True,
encoding="utf-8",
timeout=300,
check=True,
)
return json.loads(out.stdout.strip().splitlines()[-1])
def _responses() -> dict:
data = copy.deepcopy(FIXTURE)
routes = data["/quantity/milestone"]["data"]["routes"]
# 경로 그림 둘 — 사용자 그림 · 서버 캡처(auto) 꼴
data["/quantity/milestone"]["images"] = {
routes[0]["id"]: "a.png",
routes[2]["id"]: "auto/b.png",
}
return data
@pytest.fixture(scope="module")
def base() -> dict:
return _run(_responses())
def _same(sheet: dict, screen: dict) -> None:
for key in ("heads", "rows", "total", "mergeSame", "frozen"):
assert sheet[key] == screen[key], (sheet["id"], key)
def test_쪽_차례_이름(base):
stations = FIXTURE["/quantity/hydro"]["stations"]
names = [s["name"] for s in base["sheets"]]
head = ["구조물 집계표", "총괄자재수량집계표", "콘크리트소요자재집계표", "자재수량집계표"]
assert names[:4] == head
assert names[4:8] == base["screen"]["earthworkNames"] == [
"토공집계표", "토적표", "평균운반거리", "종방향 무대운반거리"
] # fmt: skip
hydro = names[8:-1]
assert len(hydro) == len(stations) == 11 # 배수지점 측점마다 한 장
assert all(n.startswith("수리집수면적표 ") for n in hydro)
kinds = [n for n, st in zip(hydro, stations) if st["kind"]]
assert kinds and all(n.endswith(" 세월교") for n in kinds)
assert names[-1] == "거리이정표"
assert len({s["id"] for s in base["sheets"]}) == len(names)
def test_표_짜기_B08_화면과_같음(base):
sheets = {s["id"]: s for s in base["sheets"]}
screen = base["screen"]
_same(sheets["summary"], screen["summary"])
for sid in ("material:material", "material:concrete", "material:quantity",
"earthwork:summary", "earthwork:sheet"): # fmt: skip
_same(sheets[sid], screen[sid])
# 운반 = 화면 표 + 아래 평균운반거리 줄(번호 칸 글)
for sid in ("earthwork:haul", "earthwork:free"):
want = screen[sid]
assert sheets[sid]["heads"] == want["heads"] and sheets[sid]["total"] == want["total"]
assert sheets[sid]["rows"] == want["rows"] + [{"no": a} for a in want["averages"]]
assert "평균운반거리" in want["averages"][0]
_same(sheets["milestone"], {**screen["milestone"]})
def test_견본_수치(base):
sheets = {s["id"]: s for s in base["sheets"]}
summary = sheets["summary"]
assert summary["heads"] == ["측점", "관 공›Φ800m/m›관매설›m", "관 공›Φ800m/m›커플링›ea"]
assert len(summary["rows"]) == 2 and summary["total"]["pipe:len|800"] == 20.5
sheet = sheets["earthwork:sheet"]
assert (
len(sheet["heads"]) == 35 and len(sheet["rows"]) == 8
) # 견본 32칸 + 측점 · 거리 · 보정량계
assert (
sheet["orientation"] == "landscape"
and sheets["earthwork:summary"]["orientation"] == "portrait"
)
assert sheets["material:concrete"]["rows"] and len(sheets["material:concrete"]["rows"]) == 5
hydro = next(s for s in base["sheets"] if s["id"].startswith("hydro:"))
assert hydro["heads"] == ["구분", "항목", "값"]
value = {r["item"]: r["value"] for r in hydro["rows"]}
calc = FIXTURE["/quantity/hydro/calc"]
assert value["Q : 홍수량 (㎥/s)"] == f"{calc['flow']:.2f}"
assert value["Qd : 설계 홍수량 (㎥/s) = Q × 2.0"] == f"{calc['design_flow']:.2f}"
assert value["R24 : 확률강우량 (mm/day)"] == f"{calc['r24_mm']:.1f}"
# 서버 계산 = 화면과 같은 입력(기본 < 장 기본 < 연결 < 저장 < 초안)
assert base["posts"] == base["screen"]["hydroInputs"]
def test_거리이정표_지도_그림(base):
milestone = base["sheets"][-1]
routes = FIXTURE["/quantity/milestone"]["data"]["routes"]
assert len(milestone["images"]) == 2
for image, route in zip(milestone["images"], (routes[0], routes[2])):
head, body = image["src"].split(",", 1)
assert head == "data:image/png;base64" and base64.b64decode(body) == PNG
assert image["caption"] == (route["name"].strip() or route["rows"][0]["item"])
def test_캐시_값이면_화면에_보이는_그_값():
responses = _responses()
stations = responses["/quantity/hydro"]["stations"]
key = f"{stations[0]['chainage_m']:.3f}"
milestone = copy.deepcopy(responses["/quantity/milestone"]["data"])
milestone["routes"][0]["name"] = "가나상회"
got = _run(responses, [["b08-hydro", {key: {"area_km2": 0.5}}], ["b08-milestone", milestone]])
assert got["posts"][0]["area_km2"] == 0.5 == got["screen"]["hydroInputs"][0]["area_km2"]
hydro = next(s for s in got["sheets"] if s["id"] == f"hydro:{key}")
assert any(r["value"].startswith("0.5 (") for r in hydro["rows"])
sheet = got["sheets"][-1]
assert any(r.get("company") == "가나상회" for r in sheet["rows"])
_same(sheet, got["screen"]["milestone"])
def test_영역_하나_실패_까닭_한_장():
responses = _responses()
del responses["/quantity/earthwork"]
got = _run(responses, screen=False)
earth = [s for s in got["sheets"] if s["id"].startswith("earthwork")]
assert len(earth) == 1 and earth[0]["name"] == "토공"
assert earth[0]["rows"][0]["note"].startswith("불러오지 못했습니다")
assert got["sheets"][0]["name"] == "구조물 집계표" and got["sheets"][-1]["name"] == "거리이정표"
def test_B08_화면이_같은_함수를_씀():
read = lambda name: (B08 / f"B08_Quantity_{name}.ts").read_text("utf-8") # noqa: E731
assert "summaryTable(view)" in read("UI_Summary") and "loadSummary(projectId)" in read(
"UI_Summary"
)
material = read("UI_Material")
assert "materialOptions(built)" in material and "loadMaterials(projectId)" in material
assert "earthworkSheetOptions(table, interval)" in read("UI_Earthwork")
sheets = read("UI_Earthwork_Sheets")
assert "earthworkSummaryOptions(table)" in sheets and "haulOptions(groups, caption)" in sheets
assert "hydroInputs(sheet, station, drafts)" in read("UI_Hydro")
assert "milestoneTable(data, siteInfo()" in read("UI_Milestone")
# 표 짜기 파일은 화면 없음
for name in (
"Summary_Table",
"Material_Tables",
"Earthwork_Tables",
"Hydro_Table",
"Milestone_Table",
):
text = read(name)
assert "document." not in text and "createDataTable" not in text, name
assert len(text.splitlines()) <= 700
printer = (ROOT / "B09_Estimation/draft/B09_Draft_Print_Quantity.ts").read_text("utf-8")
assert 'from "./B09_Draft_Print_Types"' in printer and "createDataTable" not in printer