Files
Aislo/resources/tester/test_250_1_b08_milestone_roads_width.py
T
eomsangdonandClaude Opus 5.5 5a249afb21 feat(b08): 거리이정표 — 카카오 지도 보기 유지 · 상자 색 · 상자 끌어 옮김 · 자동 정렬 (250-2)
- 카카오 지도 처음 한 번만 맞춤 · 고르기 · 끌기 뒤 중심 · 줌 그대로
- 공사지 강조색 · 기준점 경고색 · 거래처 성공색(테마 변수 · 밝음 · 어두움)
- 거래처 · 기준점 상자 끌어 옮김(pos 저장) · [자동 정렬]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLCk2y5xE8YGVgjbTntWsY
2026-10-11 00:13:15 +09:00

107 lines
5.0 KiB
Python

"""PLAN 250(사용자 149 · 150 · 152) — 거리이정표 도로 구분 = 선 자리 · 모달 정리 · 폭 · 지도 높이."""
import json
import re
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity.B08_Quantity_Milestone_Calc import compute_milestone, road_of # noqa: E402
IMPORTS = re.compile(r"^import[^;]*;\n", re.MULTILINE)
def _read(rel: str) -> str:
return (ROOT / rel).read_text(encoding="utf-8")
def _ts(expr: str):
src = IMPORTS.sub("", _read("B08_Quantity/B08_Quantity_Milestone_Calc.ts"))
out = subprocess.run(
["node", "--experimental-strip-types", "--no-warnings", "--input-type=module-typescript",
"-e", src + f"\nconsole.log(JSON.stringify({expr}));"],
capture_output=True, text=True, encoding="utf-8", timeout=60,
) # fmt: skip
assert out.returncode == 0, out.stderr
return json.loads(out.stdout)
def test_도로_구분_선_자리_짝():
cases = [
(r, k)
for r in (None, "2차포장", "1차포장", "포장", "비포장")
for k in ("via", "base", "direct", "mid")
]
py = [road_of(r, k) for r, k in cases]
assert py == _ts(f"{json.dumps(cases)}.map(([r, k]) => roadOf(r, k))")
assert road_of(None, "via") == "2차포장" and road_of("포장", "base") == "1차포장"
assert road_of("2차포장", "direct") == "포장" and road_of("비포장", "via") == "비포장"
def test_기준점_생기면_2차_1차_없으면_포장():
leg = lambda road, km: {"road": road, "km": km} # noqa: E731
route = {"id": "r", "name": "거창군청", "address": "", "via_base": True, "dir": None,
"legs": [leg(None, 23.8)], "rows": [{"item": "장비", "dest": "mid", "note": ""}]} # fmt: skip
data = {"site": {"mid_station_m": 800, "mid_road": "비포장"},
"base": {"enabled": True, "name": "병곡리", "address": "", "dir": None,
"legs": [leg(None, 0.6)]},
"routes": [route]} # fmt: skip
(a,) = compute_milestone(data, None)
assert (a["s2"], a["s1"], a["pv"], a["un"], a["total"]) == (23.8, 0.6, 0, 0.8, 25.2)
data["base"]["enabled"] = False
(b,) = compute_milestone(data, None)
assert (b["s2"], b["s1"], b["pv"], b["un"], b["total"]) == (0, 0, 23.8, 0.8, 24.6)
def test_모달_상자_하나_항목_하나_수정_글():
modal = _read("B08_Quantity/B08_Quantity_UI_Milestone_Modal.ts")
leg = _read("B08_Quantity/B08_Quantity_UI_Milestone_LegModal.ts")
assert '"+ 줄"' not in modal and "same.rows" not in modal
assert 'label: "고침"' not in modal + leg and modal.count('"수정"') >= 2
assert 'item.root.style.visibility = dest.root.style.visibility = k === "base"' in modal
def test_폭_전체_지도_높이_한_값():
css = _read("B08_Quantity/B08_Quantity_UI_Milestone.css")
block = css[css.index(".b08-milestone {") :]
assert "width: 100%;" in block[: block.index("}")]
assert ".b08-milestone > .ui-data-table .ui-data-table__table {\n width: 100%;" in css
assert css.count("height: 480px;") == 1 and ".b08-milestone__map {" in css
def test_153_지도_보기_유지_상자_색_끌어_옮김():
kmap = _read("B08_Quantity/B08_Quantity_UI_Milestone_KakaoMap.ts")
assert (
"let fitted = false;" in kmap and "map.panTo(" in kmap
) # 처음 한 번만 맞춤 · 그 뒤 줌 그대로
css = _read("B08_Quantity/B08_Quantity_UI_Milestone.css")
for kind, var in (
("is-site", "--color-accent"),
("is-base", "--color-warning"),
("is-route", "--color-success"),
):
block = css[css.index(f".b08-milestone__box.{kind} rect {{") :]
assert var in block[: block.index("}")], kind
ui = _read("B08_Quantity/B08_Quantity_UI_Milestone_Diagram.ts")
assert 'if (box.kind === "route" || box.kind === "base") dragBox(g, box, shift);' in ui
assert 'label: "자동 정렬"' in ui and "fresh.routes.forEach((r) => (r.pos = null));" in ui
def test_153_끌어_놓은_자리_레이아웃():
src = IMPORTS.sub("", _read("B08_Quantity/B08_Quantity_Milestone_Layout.ts"))
data = {"site": {"mid_station_m": None, "mid_road": "비포장"},
"base": {"enabled": True, "name": "기준", "address": "", "dir": "W", "legs": [], "pos": [500, -40]},
"routes": [{"id": "r", "name": "a", "address": "", "via_base": False, "dir": "N", "legs": [],
"rows": [], "pos": [-700, 300]}]} # fmt: skip
expr = f"layoutMilestone({json.dumps(data)}, {{}}, 0.5).boxes.filter((b) => b.id === 'base' || b.id === 'r').map((b) => [b.id, b.x, b.y])"
out = subprocess.run(
["node", "--experimental-strip-types", "--no-warnings", "--input-type=module-typescript",
"-e", src + f"\nconsole.log(JSON.stringify({expr}));"],
capture_output=True, text=True, encoding="utf-8", timeout=60,
) # fmt: skip
assert out.returncode == 0, out.stderr
assert sorted(json.loads(out.stdout)) == [["base", 500, -40], ["r", -700, 300]]