"""458 노선 바뀜 — B06 갈아끼움 + 지금 현황으로 다시 얹기 · 주인 측점 거리 상한 · 시종점 밖. 못박는 것 - 시점 당김(재현 A 꼴): 관 · 세월교 그림 = 제 측점 하나씩(따라간 누가거리) · 격자를 떠난 관 측점 `grid` 지움. - 가게 초안 없는 채(저장분 현황) 얹어도 옛 자리 세월교가 이웃 일반 측점에 안 붙음(상한 0.51 m · 측점 없음). - 시점 밖으로 밀린 관(재현 D 꼴) = 시점 측점에 안 얹고 「노선 밖」. - 카드 번호 안 겹침 — 격자 자리(80 m)를 떠난 옹벽 끝 측점은 새 번호(그 자리 새 일반 측점과 따로) · 초안 사본 표시(`preview`)는 안 들고 감. Node 헬퍼 `helper_458_swap_attach.cjs` 가 진짜 모듈(따라감 · 측점 · 갈아끼움 · 형상 얹기)을 부름. """ import json import subprocess from pathlib import Path import pytest HERE = Path(__file__).resolve().parent ROOT = HERE.parents[1] pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules").is_dir(), reason="프론트엔드 의존성 미설치" ) @pytest.fixture(scope="module") def out() -> dict: proc = subprocess.run( ["node", str(HERE / "helper_458_swap_attach.cjs")], cwd=ROOT, capture_output=True, text=True, encoding="utf-8", timeout=120, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def _shaped(sections: list[dict]) -> dict[float, dict]: return {s["chainage_m"]: s["shapes"] for s in sections if s["shapes"]} def test_시설마다_제_측점_하나(out): shift = out["shift"] assert shift["pipes"] == [["p1", 47], ["p2", 157]] assert _shaped(shift["now"]) == {47: {"culvert": 47}, 157: {"ford": 157}} assert shift["misses"] == {"outside": [], "far": []} def test_격자_떠난_시설_측점_grid_지움(out): by_at = {s["chainage_m"]: s for s in out["shift"]["now"]} assert by_at[47]["kind"] == "irregular" and by_at[47]["grid"] is False def test_저장분_현황이어도_이웃에_안_붙음(out): shift = out["shift"] assert shift["staleMisses"]["far"] == [150] assert all("ford" not in shapes for shapes in _shaped(shift["stale"]).values()) def test_시점_밖_관은_안_얹고_노선_밖(out): outside = out["outside"] assert ["p1", 0] in outside["pipes"] assert outside["misses"] == {"outside": [0], "far": []} assert _shaped(outside["now"]) == {100: {"ford": 100}} assert {s["chainage_m"]: s["grid"] for s in outside["now"]}[20] is True # 격자 자리 옹벽 측점 def test_카드_번호_안_겹침_떠난_끝_측점은_새_번호(out): ids = dict(out["shift"]["ids"]) assert len(set(ids.values())) == len(ids) assert ids[87] == "station_000000087000" # 옹벽 끝 80 → 87 assert ids[80] == "station_000000080000" # 그 자리 새 일반 측점 assert ids[47] == "station_000000047000" # 관도 격자 40 을 떠남 assert ids[40] == "station_000000040000" assert ids[157] == "station_000000150000" # 옛 자리가 빈 세월교 측점 = 옛 번호 그대로 def test_초안_사본_표시_안_들고_감(out): assert out["shift"]["preview"] == 0 and out["outside"]["preview"] == 0