"""PLAN 322-3 카드 목록 흐름 일곱 — 초안 측점 맞춤(`withDraftStations`)이 측점 계획 한 벌을 따름. 놓기 · 일반 측점에 놓기(219 흠 — No.N+0 자리 새 구조물 = 이름 칩 · 관 그림) · 옮기기 · 같은 군 바꿈 · 정본 넘는 바꿈(관 → 맹암거) · 지우기 · 저장 뒤 다시 열기(빼 둔 옛 자리 돌아옴). 각 줄 = [측점, 카드 이름, 미리 뜬 사본, 관 계열 그림 열쇠]. TS 쪽 = `helper_322_3_flow.cjs`(Node). """ from __future__ import annotations import json import subprocess from pathlib import Path import pytest HERE = Path(__file__).parent ROOT = HERE.parent.parent pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules").is_dir(), reason="프론트엔드 의존성 미설치" ) @pytest.fixture(scope="module") def flows() -> dict: out = subprocess.run( ["node", str(HERE / "helper_322_3_flow.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=120, check=True, ) return json.loads(out.stdout) def _marked(rows: list) -> list: return [row for row in rows if row[1] or row[2] or row[3]] def test_place(flows: dict) -> None: assert _marked(flows["place"]) == [ [93, "옹벽", True, []], [101, "옹벽", True, []], [113, "옹벽", True, []], ] def test_place_on_general_station_gets_name_and_shape(flows: dict) -> None: # 219 흠 — 일반 측점 자리(100 · 120)에 새로 놓은 맹암거 · 관 = 그 자리 사본에 이름 칩 · 관 그림 assert _marked(flows["gridPlace"]) == [ [100, "맹암거", True, []], [120, "파형강관 D800", True, ["culvert"]], ] assert len(flows["gridPlace"]) == 11 # 측점 수 그대로(사본으로 갈음) def test_move_hides_old_and_adds_new(flows: dict) -> None: assert _marked(flows["move"]) == [[75, "파형강관 D1000", True, ["culvert"]]] assert all(row[0] != 61 for row in flows["move"]) def test_same_group_switch_renames(flows: dict) -> None: assert _marked(flows["sameGroup"]) == [ [93, "흙막이", True, []], [101, "흙막이", True, []], [113, "흙막이", True, []], ] def test_cross_owner_switch_drops_pipe_drawing(flows: dict) -> None: assert _marked(flows["crossOwner"]) == [[101, "맹암거", True, []]] def test_pick_follows_moved_pipe(flows: dict) -> None: moved, other = flows["follow"] assert (moved["chainageM"], moved["structureId"]) == (75, "pipe-s1") # 세션 id 그대로(323-5) assert (other["chainageM"], other["structureId"]) == (101, "w1") # 구조물 고름은 그대로 def test_remove_and_reopen(flows: dict) -> None: assert _marked(flows["remove"]) == [] assert [row[0] for row in flows["remove"]] == list(range(0, 201, 20)) assert _marked(flows["reopen"]) == [ [93, "옹벽", False, []], [101, "옹벽", False, []], [113, "옹벽", False, []], ] # ── 옛 소수 관(검증_sub1 견본) — B06 을 바로 열어도 B05 와 같은 정수 m 초안(요구 167 · `snapPlan`) ── SNAPPED = [85, 173, 258, 352, 440, 534, 620, 720, 804, 900, 983] def test_old_decimal_pipes_snap_like_b05(flows: dict) -> None: assert flows["snapTo"] == [SNAPPED, 0] def test_saved_integer_stations_keep_cards(flows: dict) -> None: # 서버가 정수 자리로 심은 저장분 = 계획과 같음 — 저장 카드 그대로 · 새 미리 뜬 카드 0 rows = flows["snapSavedInt"] assert [row[0] for row in _marked(rows)] == SNAPPED assert not any(row[2] for row in rows) assert len(rows) == 58 def test_saved_decimal_stations_follow_plan(flows: dict) -> None: # 소수 자리 저장분 = B05 를 먼저 연 것과 같음 — 소수 카드는 빼 두고 정수 자리(격자 자리는 사본) rows = flows["snapSavedDec"] assert [row[0] for row in _marked(rows)] == SNAPPED assert all(row[2] for row in _marked(rows)) assert all(float(row[0]).is_integer() for row in rows) assert len(rows) == 58