"""PLAN 370-2 — B06 사면 이동 멈춤 · 교차점 손잡이 · 고름 이어받기(요구 240-14). 짝: `B06_Section/logic/B06_Section_UI_Cross_Fit.ts`(`extendStop` · `toePoints`) · `B06_Section/B06_Section_UI_Cross_Design_Pick.ts`(손잡이 · 키 이어받기). 실제 TS 를 `helper_370_2_toe_stop.cjs` 가 Node 로 돌린다. """ from __future__ import annotations import json import os import subprocess import sys import pytest HERE = os.path.dirname(__file__) ROOT = os.path.join(HERE, "..", "..") if ROOT not in sys.path: sys.path.insert(0, ROOT) from config.config_system import STANDARD_CROSS_SECTION # noqa: E402 pytestmark = pytest.mark.skipif( not os.path.isdir(os.path.join(ROOT, "config", "node_modules")), reason="프론트엔드 의존성 미설치", ) @pytest.fixture(scope="module") def out(tmp_path_factory) -> dict: standard = tmp_path_factory.mktemp("std") / "standard.json" standard.write_text(json.dumps(STANDARD_CROSS_SECTION), encoding="utf-8") proc = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", os.path.join(HERE, "helper_370_2_toe_stop.cjs"), str(standard)], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_노견_끝이_원지반을_지나면_그_자리에_한_번_섬(out) -> None: stop = out["stop"] low, high = stop["crossing"] assert low < stop["value"] < high assert stop["gap"] < 2e-3 # 노견 끝 = 원지반 assert stop["noCross"] == 0.1 # 안 지나면 걸음 그대로 assert abs(stop["fromStop"] - round(stop["value"] + 0.1, 1)) < 1e-9 # 멈춘 뒤엔 다시 안 섬 assert stop["leftNoGround"] == 0.1 # 지반 없으면 그대로 def test_교차점_손잡이_쪽마다_늘_보임(out) -> None: toe = out["toe"] assert toe["count"] == len(toe["sides"]) == 2 assert toe["centerClass"] is True # 중심점 원과 같은 고르기 차례 assert toe["rightOnGround"] is True assert abs(toe["rightCx"] - toe["rightX"]) < 1e-9 def test_손잡이를_고르면_그_쪽_사면_좌우_이동(out) -> None: got = out["toePick"] assert got["active"] is True and got["panelOpen"] is True assert got["title"] == "교차점 이동 (우)" # 아래 띠 공용 칸(370-3) assert got["value"].startswith("노선에서 ") assert len(got["sent"]) == 1 and got["sent"][0]["side"] == "right" low, high = out["stop"]["crossing"] assert abs(got["sent"][0]["valueM"] - out["stop"]["value"]) < 1e-9 # ◀▶ 도 멈춤 자리 assert low < got["sent"][0]["valueM"] < high def test_절에서_성으로_넘어가도_고름_유지(out) -> None: inherit = out["inherit"] assert inherit["cutIndex"] >= 0 and inherit["before"] == inherit["cutIndex"] assert inherit["farMode"] == "left_cut" # 우 = 성토로 넘어감 assert inherit["afterIndex"] is not None assert inherit["label"] == "교차점 이동 (우)"