"""PLAN 319 — 횡단배수 종류 바꿈이 맹암거 · 개거처럼 정본이 다른 종류에서도 먹음(요구 217). - 패널: 관 지점 ↔ 구조물로 바꿈 = 옛 것 지움(「없음」) → 같은 측점에 새 종류(우클릭 추가 길 `addAt`) · 그 측점 옛 조정값 버림 · 처음 종류로 되돌리면 비울 자리 기록이 빠짐 · 같은 정본끼리는 종전 그대로 - 횡단 초안 맞춤: 일반 측점 자리(grid)도 종류가 바뀌거나 빠지면 구조물만 뺀 사본(측점 남음 · 고친 값 그대로)에 새 종류 · 저장분 종류로 되돌리면 저장분 그대로 실제 TS 를 `helper_319_kind_swap.cjs` 가 Node 로 돌린다(서버 부르는 곳 흉내). """ from __future__ import annotations import json import os import subprocess import pytest HERE = os.path.dirname(__file__) ROOT = os.path.join(HERE, "..", "..") pytestmark = pytest.mark.skipif( not os.path.isdir(os.path.join(ROOT, "config", "node_modules")), reason="프론트엔드 의존성 미설치", ) @pytest.fixture(scope="module") def result() -> dict: out = subprocess.run( ["node", os.path.join(HERE, "helper_319_kind_swap.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=120, check=True, ) return json.loads(out.stdout) def _src(*parts: str) -> str: with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle: return handle.read() def test_pipe_to_underdrain_removes_pipe_and_places_at_same_station(result: dict) -> None: swap = result["pipe_to_underdrain"] assert swap["removed"] == [80] assert swap["pipeSet"] == [None] assert swap["addAt"] == [[80, "cross_underdrain"]] assert swap["reset"] == 0 and swap["live"] == 0 # 새로 놓기 폼으로 빠지지 않음 assert swap["kindreset"] == {"80.00": "pipe"} # [저장] 때 그 측점 옛 조정값 비움(318-4) assert swap["culvertopt"] == {"300.00": {"b": 2}} # 그 측점 세션 조정값만 버림 def test_back_to_first_kind_drops_reset_mark(result: dict) -> None: back = result["underdrain_back_to_pipe"] assert back["left"] == [] and back["emit"] == 1 and back["editingSet"] == [None] assert back["addAt"] == [[80, "pipe"]] assert back["kindreset"] is None def test_structure_to_pipe_kind(result: dict) -> None: swap = result["open_ditch_to_box"] assert swap["left"] == ["sign"] # 고른 개거만 빠짐 assert swap["removed"] == [] assert swap["addAt"] == [[120, "box_culvert"]] assert swap["kindreset"]["120.00"] == "open_ditch" def test_same_owner_switch_unchanged(result: dict) -> None: for case in ("pipe_to_box", "underdrain_to_open_ditch"): same = result[case] assert same["addAt"] == [] and same["removed"] == [] and same["live"] == 1 assert result["to_blank"]["reset"] == 1 and result["to_blank"]["addAt"] == [] def test_grid_station_kind_change_uses_bare_copy(result: dict) -> None: # 일반 측점 자리 = 측점이 남음 — 저장분에서 구조물만 뺀 사본에 새 종류(지형 쪽 고친 값 그대로) grid = result["grid"] assert grid["pipe_to_underdrain"] == { "count": 3, "keys": [], "structure": "맹암거", "preview": True, "fresh": False, "keep": 1, } assert grid["pipe_to_box"]["keys"] == ["box"] and grid["pipe_to_box"]["keep"] == 1 assert grid["underdrain_to_pipe"]["keys"] == ["culvert"] assert grid["underdrain_to_pipe"]["structure"] == "파형강관 D800" assert grid["underdrain_to_pipe"]["keep"] == 1 def test_grid_station_emptied_keeps_station_without_facility(result: dict) -> None: assert result["grid"]["pipe_deleted"] == { "count": 3, "keys": [], "structure": None, "preview": True, "fresh": False, "keep": 1, } def test_grid_station_back_to_saved_kind_restores_saved(result: dict) -> None: back = result["grid"]["pipe_back"] assert back["keys"] == ["culvert"] and not back["preview"] and back["keep"] == 1 def test_panel_wires_add_at() -> None: panel = _src("B05_Profile", "B05_Profile_UI_Structures_Panel.ts") assert "addAt: (at, typeId) => api.addAt(at, typeId)" in panel assert "return api;" in panel assert len(panel.splitlines()) <= 700