Files
Aislo/resources/tester/test_118_pipe_pick.py
T
eomsangdonandClaude Opus 5.5 a6e7a14217 refactor(b06): 구조물 패널 선택 배선 떼기 — wireStructureSelection 새 파일(152-1)
- B06_Section_UI_Page_Structures_Panel.ts 699 → 540줄 · 동작 그대로
- 선택 배선 = B06_Section_UI_Page_Structures_Selection.ts
- 문자열 시험 3개 새 파일 읽기로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3mdb91125mPoC6tpsQx4P
2026-10-09 19:01:18 +09:00

117 lines
4.6 KiB
Python

"""PLAN 118-1 — B06 배관 횡단도 관 고름 → 관 두 겹 강조 · 좌측 「관」 상자 강조 · 조정창 없음.
짝: `B06_Section/B06_Section_UI_Cross_Culvert.ts`(관 판정면 · 강조) · `_Cross_Structure_Panel.ts`(show "pipe") ·
`_Adjust_Dock.ts`(side "pipe") · `_Page_Structures_Panel.ts`(`keyOf`) · `_Page_Structure_Pick.ts`(3D pipe 키).
실제 TS 를 `helper_118_pipe_pick.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 out() -> dict:
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", os.path.join(HERE, "helper_118_pipe_pick.cjs")],
capture_output=True,
text=True,
encoding="utf-8",
timeout=60,
)
assert proc.returncode == 0, proc.stderr
return json.loads(proc.stdout)
def _src(rel: str) -> str:
with open(os.path.join(ROOT, rel), encoding="utf-8") as f:
return f.read()
def test_관을_누르면_관을_고름(out) -> None:
overlay = out["overlay"]
assert overlay["firstPicked"] == ["pipe"]
assert overlay["stopped"] is True # 카드 고름으로 안 번짐
assert overlay["hitMatchesOuter"] is True # 판정면 = 외경
def test_관_판정면은_벽_아래(out) -> None:
"""겹친 자리는 벽이 이김 — 관 판정면이 벽 · 집수정 판정면보다 먼저 얹힘."""
order = out["overlay"]["hitOrder"]
assert order[0] == "pipe"
assert order.count("pipe") == 1 and len(order) > 1
def test_관_고름은_관_두_겹만_강조(out) -> None:
overlay = out["overlay"]
assert overlay["pipeCount"] == 2
assert overlay["onPipe"]["pipes"] == [True, True]
assert not any(overlay["onPipe"]["walls"])
# 벽을 고르면 관 강조는 꺼짐 — 동시 강조 없음
assert not any(overlay["onOutlet"]["pipes"]) and any(overlay["onOutlet"]["walls"])
assert not any(overlay["onNone"]["pipes"] + overlay["onNone"]["walls"])
def test_관을_숨긴_카드엔_관_판정면_없음(out) -> None:
"""링크 · 독립 흙막이 · 세월교 · 박스 측점(hidden_pipe) — 관은 세월교 오버레이 몫."""
assert out["hiddenPipe"]["pipes"] == 0
assert "pipe" not in out["hiddenPipe"]["picked"]
def test_관_강조는_주인_측점_카드만(out) -> None:
stands = out["stands"]
assert stands["self"] is True
assert stands["neighbour"] is False
assert stands["outletNeighbour"] is True # 벽 연동은 그대로
def test_3D_관_고름이_B06_으로_이어짐(out) -> None:
assert out["pick"]["pipe"] == [["revet", "pipe"]]
assert out["pick"]["basin"] == []
assert out["pick"]["fordPipe"] == [] # 세월교 측점 = 세월교 창 몫
def test_관은_조정창_없음(out) -> None:
panel = out["panel"]
assert panel["outlet"] == {"hidden": False, "side": "outlet"}
assert panel["pipe"] == {"hidden": True, "side": "pipe", "touched": []}
assert panel["none"] == {"hidden": True, "side": ""}
def test_좌측_관_상자_강조_스크롤() -> None:
dock = _src("B06_Section/B06_Section_UI_Adjust_Dock.ts")
assert 'if (side === "body" || side === "pipe") {' in dock
assert "'fieldset[data-spec-container=\"pipe\"]'" in dock
assert 'body.classList.add("is-active");' in dock
assert 'if (scroll) body.scrollIntoView({ block: "nearest" });' in dock
# 관 상자 칸을 고치면 관을 고름 — 횡단에서 누른 것과 같은 길
page = _src("B06_Section/B06_Section_UI_Page_Structures_Selection.ts")
assert 'if (id === "inlet" || id === "outlet" || id === "pipe") return id;' in page
css = _src("B06_Section/B06_Section_UI_Style_Cross_Areas.css")
assert ".b06-chart__culvert-pipe.is-active {" in css
def test_벽_본체_동시_고름_금지_그대로() -> None:
"""107-1 — 관도 같은 고름 저장소라 세월교 · 박스 고름과 함께 서지 않음."""
station = _src("B06_Section/B06_Section_UI_Page_Station_Controls.ts")
assert "let revetSelection: { at: string; key: RevetPick } | null = null;" in station
assert (
"if (key && ford.control.selectedFor(chainageM)) ford.control.select(chainageM, null);"
in station
)
view = _src("B06_Section/B06_Section_UI_Cross_View.ts")
assert "const toggleRevet = (key: RevetPick): void => {" in view
assert "if (activeRevet !== null) toggleRevet(activeRevet);" in view