Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
114 lines
5.0 KiB
Python
114 lines
5.0 KiB
Python
"""PLAN 370-2 — B06 사면 이동 멈춤 · 교차점 손잡이 · 고름 이어받기(요구 240-14).
|
|
|
|
짝: `B06_Section/logic/B06_Section_UI_Cross_Fit.ts`(`extendStop` · `toePoints` · `edgeOnGround`) ·
|
|
`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:
|
|
"""370-4 — 멈춤값(0.001 m 반올림)이 참 교차 앞이면 남은 틈 > 1e-4 · 그래도 ±5 mm 안 = 멈춤 자리."""
|
|
got = out["before"]
|
|
assert got["before"] < got["exact"] # 교차 앞
|
|
assert 0.1 < got["gapMm"] <= 5 # 옛 잣대(0.1 mm) 밖 · 새 잣대(5 mm) 안
|
|
assert abs(got["got"] - got["next"]) < 1e-9 # 0.936 → 1.036 꼴(제자리 아님)
|
|
|
|
|
|
def test_손잡이_없는_넘어감도_고름_유지(out) -> None:
|
|
"""370-5 — 바뀜 자리 손잡이를 고른 뒤 사면이 원지반과 못 만나도 같은 쪽 사면 선 · 암 칸으로 안 넘어감."""
|
|
got = out["noToe"]
|
|
assert got["toeGone"] is True
|
|
assert got["index"] is not None
|
|
assert got["zone"] == {"zone": "fill", "side": "right"}
|
|
assert got["title"] == "사면 이동 (우)"
|
|
assert got["buttons"] == ["left", "reset", "right"] # ◀↺▶ 남음
|
|
|
|
|
|
def test_교차점_손잡이는_바뀜_자리만(out) -> None:
|
|
"""414-1 — 원 = 그 쪽 노견 끝 = 원지반(±5 mm · `bare`)일 때만 · 보통 단면은 원 0."""
|
|
toe = out["toe"]
|
|
assert toe["nearSides"] == ["left", "right"] # 사면 ∩ 원지반 자리는 있어도
|
|
assert toe["nearCount"] == 0 # 보통 단면(절 · 성 정해짐) = 원 0
|
|
assert toe["count"] == len(toe["bareSides"]) == 1 and toe["bareSides"] == ["right"]
|
|
assert toe["centerClass"] is True # 중심점 원과 같은 고르기 차례
|
|
assert toe["rightOnGround"] is True
|
|
assert abs(toe["rightCx"] - toe["rightX"]) < 1e-9
|
|
|
|
|
|
def test_손잡이를_고르면_좌우로_절성토_넘김(out) -> None:
|
|
"""414-1 — 바뀜 자리 원을 고르면 ▶(바깥) = 성토 · ◀(안쪽) = 절토."""
|
|
got = out["toePick"]
|
|
assert got["active"] is True and got["panelOpen"] is True
|
|
assert got["title"] == "사면 이동 (우)" # 아래 띠 공용 칸(370-3)
|
|
assert got["value"].startswith("절·성토 없음 · 노선에서 ")
|
|
assert [c["side"] for c in got["sent"]] == ["right", "right"]
|
|
low, high = out["stop"]["crossing"]
|
|
outward, inward = (c["valueM"] for c in got["sent"])
|
|
assert outward >= high and inward <= low # 멈춤 자리에서 다시 안 섬
|
|
assert got["modes"] == ["left_cut", "both_cut"] # 우 = 성토 → 절토
|
|
|
|
|
|
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"] == "사면 이동 (우)"
|
|
|
|
|
|
def test_정확히_0_자리는_절성토_없음_사면처럼_고름(out) -> None:
|
|
"""379-1 — 멈춘 자리(노견 끝 = 원지반) 손잡이를 누르면 사면과 같은 조작."""
|
|
zero = out["zero"]
|
|
assert zero["bare"]["right"] is True and zero["nearBare"]["right"] is False
|
|
assert zero["toe"] is True and zero["radius"] == "8" # 판정 원 8 px
|
|
assert zero["title"] == "사면 이동 (우)"
|
|
assert zero["value"].startswith("절·성토 없음 · 노선에서 ")
|
|
assert zero["buttons"] == ["left", "reset", "right"] # ◀↺▶
|
|
assert zero["keys"] >= 1 # 방향키 듣개
|