# -*- coding: utf-8 -*- """PLAN 188-1 — 종단(B05) ↔ 횡단(B06) 오갈 때 마지막 고름 하나만 이김. 원인: 종단 측점선 · 3D 띠 · 표에서 고른 일반 측점은 고름 한 칸(`structure-pick`)에 안 적혀 (`syncIrregularSelection` 이 일반 측점이면 바로 끝남) 옛 배관 고름이 남아 횡단이 배관 카드로 감. 횡단 → 종단은 관 · 구조물이 없는 자리면 그래프 측점선을 풀어 버림(`selectGraphAt` = null). 실제 TS 를 `helper_188_1_last_pick.cjs` 가 Node 로 돌린다. """ from __future__ import annotations import json import os import subprocess import pytest HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.abspath(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 out() -> dict: proc = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", os.path.join(HERE, "helper_188_1_last_pick.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def _read(*parts: str) -> str: with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle: return handle.read() def test_배관_다음_일반_측점이면_횡단은_일반_측점(out) -> None: assert out["pipeThenStation"] == "s20" assert out["pillThenStation"] == "s20" # 알약으로 고른 배관도 def test_일반_측점_다음_배관이면_횡단은_배관(out) -> None: assert out["stationThenPipe"] == "irregular:p1" def test_구조물을_끼워도_마지막_고름이_이김(out) -> None: assert out["structureThenStation"] == "s100" assert out["stationThenStructure"] == "s60" # 옹벽 = 시작 측점 카드 assert out["structureThenPipe"] == "irregular:p1" def test_고름을_풀면_비우고_모르는_측점은_안_건드림(out) -> None: assert out["released"] is None assert out["unknownKeeps"] == 20 def test_횡단_일반_측점은_종단_측점선과_3D_띠로(out) -> None: station = out["b06Station"] assert station["graph"] == {"station": "s40", "mark": None} assert station["marker"] == "s40" assert station["pick"] == {"chainageM": 40, "structureId": None} def test_횡단_배관은_종단_배관_측점선_측점선_없는_관은_알약(out) -> None: assert out["b06Pipe"]["graph"]["station"] == "irregular:p1" assert out["b06BarePipe"]["graph"] == {"station": None, "mark": "pipe-50.00"} def test_횡단_구조물은_종단에서_그_구조물을_열고_측점선_없이_고름_한_칸을_안_덮음(out) -> None: structure = out["b06Structure"] assert structure["opened"] == ["wall"] # 구조물 고름 = 종단 측점선 · 3D 띠 없음(189-1 · 여러 측점이라 한 측점 기준 없음) assert structure["graph"] == {"station": None, "mark": None} assert structure["marker"] is None # 되살리며 3D 띠 리스너가 되불러도(동기화 중) 구조물 id · 부재키가 남음 assert structure["pick"] == {"chainageM": 60, "structureId": "wall", "partKey": "own"} def test_종단_횡단을_오가도_마지막_고름(out) -> None: assert out["roundTrip"] == ["s20", "s80", "irregular:p1", "s0"] def test_그래프_표적_차례(out) -> None: target = out["graphTarget"] assert target["byId"] == {"stationId": "s20"} assert target["bare"] == {"pipeChainageM": 50} assert target["station"] == {"stationId": "s100"} assert target["far"] == {"stationId": None} assert target["none"] == {"stationId": None} def test_종단_보기_배선() -> None: page = _read("A00_Common", "design", "design_view_profile.ts") assert "regularChainage:" in page assert "remember: (chainageM) => rememberPick(chainageM, null)" in page assert "graphTargetAt(id, chainageM, lastPipes ?? [], sections)" in page assert "const sections = structurePick ? [] :" in page