# -*- coding: utf-8 -*- """231-1 노면공 범위 고름 — 측점만 남은 고름은 노면공 범위 강조를 켜지 않음(조사 AD 1안 + 같은 구멍). 까닭: B06 폼 다시 세움(`load()` — B05↔B06 오감 · 새로 고침)이 측점만 남은 고름을 거름 없이 `selectAt` 으로 열어 「그 측점을 덮는 첫 구조물」= 노면공이 열리고 범위 강조 · 고름 기록까지 노면공으로 바뀜. B05 3D 부재 고름(`wireStructurePick`)도 거름 없이 노면공 id 를 고름 한 칸에 적었음. 고침: 측점 고름이 여는 모든 길에 `coversAtStation`(노면공 뺌 · 152-5) 한 벌 · 노면공은 목록 · 알약 · 형상 누름(id)만. 곁: 측점 고름이 연 폼은 카드를 구조물 기준 카드로 옮기지 않음 · 넘김 카드 = 찾는 거리 안 가장 가까운 카드. 진짜 TS 를 `helper_231_1_pave_reload.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="프론트엔드 의존성 미설치", ) def _read(*parts: str) -> str: with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle: return handle.read() @pytest.fixture(scope="module") def out() -> dict: proc = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", os.path.join(HERE, "helper_231_1_pave_reload.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) CARD_120 = {"form": None, "paveLayer": None, "span": None, "card": 120, "sid": None} PAVE = {"form": "pave", "paveLayer": "pave", "span": "pave", "card": None, "sid": "pave"} def test_범위_안_카드_고름_오감해도_노면공_안_켬_폼_그대로(out) -> None: assert out["cardBefore"] == CARD_120 assert out["cardAfter"] == CARD_120 assert out["cardAfter2"] == CARD_120 # 두 번 오가도 def test_같은_카드_목록_고름_뒤_오감도_노면공_안_켬(out) -> None: assert out["signPick"]["form"] == "sign" after = out["signAfter"] assert after["form"] == "sign" # 목록 고름도 기록 — 오감 뒤 그 폼(231-2) assert after["paveLayer"] is None assert after["span"] != "pave" assert after["card"] is None # 측점 없는 표지 = 카드 안 고름 · 스크롤만(요구 178) def test_목록_노면공은_오감해도_범위_강조_그대로(out) -> None: assert out["paveBefore"] == PAVE assert out["paveAfter"] == PAVE def test_옹벽_범위_안_카드는_그_카드_그대로(out) -> None: wall = {"form": "wall", "paveLayer": None, "span": None, "card": 120, "sid": None} assert out["wallCard"] == wall # 기준 카드 100 으로 안 옮김 assert out["wallAfter"] == wall # 오감 뒤도 · 범위 테두리 없음(137-4) # 목록 고름은 그대로 기준 카드 · 범위 테두리 · id 기록 assert out["wallList"] == { "form": "wall", "paveLayer": None, "span": "wall", "card": 100, "sid": "wall", } def test_관_넘김은_가장_가까운_카드(out) -> None: assert out["pipeHandoff"]["card"] == 80.17 # 이웃 측점 80 아님 assert out["pipeHandoff"]["form"] == "pipe-80.17" def test_B05_3D_고름은_노면공_id_를_안_적음(out) -> None: assert out["pick3dWall"] == {"sid": "wall", "form": "wall"} # 범위 안 옹벽 = 옹벽 assert out["pick3dBare"] == {"sid": None, "form": None} # 노면공만 덮음 = 안 엶 after = out["pick3dAfter"] assert after["paveLayer"] is None assert after["sid"] is None assert after["form"] is None def test_배선() -> None: panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts") assert "section.selectAt({ chainageM: picked, structureId }, coverable);" in panel assert "if (!openingAtStation) deps.focusChainage(focusOf(structure), revealOnly);" in panel assert "deps.markStructure?.(id, !openingAtStation);" in panel cross = _read("A00_Common", "design", "design_view_cross.ts") assert ( "markStructure: (structureId, span) => sectionView.selectMark(structureId, span)," in cross ) pick = _read("B05_Profile", "B05_Profile_UI_Structure_Pick_Session.ts") assert "structures.resolveAt(selection, coverable)" in pick assert "structures.selectAt({ ...selection, structureId }, coverable)" in pick profile = _read("A00_Common", "design", "design_view_profile.ts") at = profile.index("wireStructurePick(") assert "coversAtStation(bridge.typeGroup(entry.type_id))" in profile[at : at + 300] handoff = _read("B06_Section", "B06_Section_UI_Page_Structure_Pick.ts") assert "nearestWithin(sections, handoff.at, (section) => section.chainage_m)" in handoff