"""139-6 · 151-3 고른 설계선 사면 이동 패널 — 고른 조각 쪽만 0.1 m 걸음 · 노폭 안쪽 금지(0 에서 멈춤). 화면 TS(`_Cross_Design_Pick`)를 흉내 DOM 으로 돌린 값(`helper_139_6_line_shift.cjs`). """ import json import subprocess from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] HELPER = Path(__file__).parent / "helper_139_6_line_shift.cjs" pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules").is_dir(), reason="프론트엔드 의존성 미설치" ) @pytest.fixture(scope="module") def out() -> dict: done = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", str(HELPER)], cwd=str(ROOT), capture_output=True, text=True, encoding="utf-8" ) assert done.returncode == 0, done.stderr return json.loads(done.stdout) def test_화면_방향대로_그_쪽만_단추와_방향키(out: dict) -> None: first, back, right = out["log"] assert first == {"left": 0.2, "right": 0} # 좌 사면 · ◀ 단추 + ← 키 = 좌 바깥 0.2 assert back == {"left": 0, "right": 0} # → 키 · ▶ · → 키 = 0 에서 멈춤(노폭 안쪽 금지) assert right == {"left": 0, "right": 0.1} # 우 사면 · ← = 안쪽 0 · ▶ = 바깥 0.1 def test_공용_칸_값에_이동_표기(out: dict) -> None: """370-3 — 치수 · 이동은 아래 띠 공용 칸 값 한 줄(옛 우측 위 치수 · 패널 읽기 줄).""" assert "이동 +0.1m" in out["text"] and "노견 +" not in out["text"] assert out["text"].startswith("길이 ") and "\n" not in out["text"] assert out["titleLeft"] == "사면 이동 (좌)" def test_단추는_공용_칸_재설정(out: dict) -> None: assert out["slots"] == ["◀", "↺", "▶"] assert out["afterReset"] == {"left": 0, "right": 0} assert out["picks"] == [] # 칸 누름은 고름으로 안 번짐 assert out["hiddenAtStart"] is True and out["hiddenAfter"] is True assert out["afterHidden"] == {"left": 0, "right": 0} def test_페이지가_같은_창구로_세션_재계산() -> None: sync = (ROOT / "B06_Section" / "B06_Section_UI_Page_Design_Sync.ts").read_text(encoding="utf-8") assert ( "writeShoulderExtend(projectId, currentRouteId, chainageM, shift.side, shift.valueM)" in sync ) persist = (ROOT / "B06_Section" / "B06_Section_UI_Page_Persist.ts").read_text(encoding="utf-8") assert "patch.shoulder_extend_left_m = sides.left" in persist