- 새 파일 B05_Profile_UI_RouteEdit_Keys.ts(창 keydown 가로채기 · 마지막 누름 평면 안 · 고정 · 입력칸 제외 · 하한 검사) + logic/KeyNudge - 평면을 누른 뒤 방향키는 평면이 삼킴 — 종단 ▲▼ · 횡단 조정창으로 안 샘 - B06 Panel_Base lastPointerWithin 넓힘 · Pointer.ts 걸기 한 줄 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ji4nuyLVHcxrXWHTdb5nRD
81 lines
3.5 KiB
Python
81 lines
3.5 KiB
Python
"""383-2 교각점 방향키 — `logic/B05_Profile_RouteEdit_KeyNudge.ts` 를
|
|
Node(`helper_383_2_key_nudge.cjs`)로 돌려 판정(화면 축 0.1 m · Shift ×10 · 돌린 지도 · 스냅 뒤
|
|
실제 이동 · 함께 밀린 IP · 제자리 안내) + 이음(`_RouteEdit_Keys` · 끌기 걸기 한 줄 · 평면이
|
|
삼킴 → 종단 ▲▼ 비킴).
|
|
|
|
./venv/Scripts/python.exe -m pytest resources/tester/test_383_2_route_keys.py -q
|
|
"""
|
|
|
|
import json
|
|
import math
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
B05 = ROOT / "B05_Profile"
|
|
HELPER = Path(__file__).with_name("helper_383_2_key_nudge.cjs")
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def got() -> dict:
|
|
run = subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
["node", str(HELPER)], capture_output=True, text=True, encoding="utf-8", timeout=60
|
|
)
|
|
assert run.returncode == 0, run.stderr
|
|
return json.loads(run.stdout)
|
|
|
|
|
|
def _read(name: str) -> str:
|
|
return (B05 / name).read_text(encoding="utf-8")
|
|
|
|
|
|
def test_화면_축_0_1m_Shift_10배(got) -> None:
|
|
plain = got["plain"]
|
|
assert plain["ArrowUp"] == pytest.approx([0, 0.1]) # 화면 위 = 도면 북쪽(뒤집힌 y)
|
|
assert plain["ArrowDown"] == pytest.approx([0, -0.1])
|
|
assert plain["ArrowLeft"] == pytest.approx([-0.1, 0])
|
|
assert plain["ArrowRight"] == pytest.approx([0.1, 0])
|
|
assert got["shift"]["ArrowRight"] == pytest.approx([1.0, 0])
|
|
assert got["arrows"] == [True, True, True, True, False]
|
|
|
|
|
|
def test_돌린_지도도_화면_위(got) -> None:
|
|
up = got["rotated"]["ArrowUp"]
|
|
turn = math.radians(30)
|
|
assert math.hypot(*up) == pytest.approx(0.1)
|
|
assert up == pytest.approx([-0.1 * math.sin(turn), 0.1 * math.cos(turn)])
|
|
|
|
|
|
def test_스냅_뒤_실제_이동_함께_밀린_IP(got) -> None:
|
|
assert got["snapped"]["movedM"] == pytest.approx(0.8)
|
|
assert got["snapped"]["pushed"] == 1
|
|
assert got["stayed"]["movedM"] == pytest.approx(0.02) and got["stayed"]["pushed"] == 0
|
|
assert got["merged"]["movedM"] == pytest.approx(0.4) and got["merged"]["pushed"] == 0
|
|
messages = got["messages"]
|
|
assert "실제 이동 0.8 m" in messages["snapped"] and "함께 밀린 IP 1곳" in messages["snapped"]
|
|
assert "같은 측점 — 스냅 끄고 미세 조정" in messages["stayed"]
|
|
assert "0.3 m 옮겼습니다" in messages["free"]
|
|
|
|
|
|
def test_이음_끌기_걸기_한_줄_창_가로채기() -> None:
|
|
pointer = _read("B05_Profile_UI_RouteEdit_Pointer.ts")
|
|
assert pointer.count("bindRouteEditKeys(") == 1
|
|
keys = _read("B05_Profile_UI_RouteEdit_Keys.ts")
|
|
assert 'window.addEventListener("keydown", onKeyDown, true)' in keys # 앞서 받음(capture)
|
|
assert 'lastPointerWithin(".b05-routeedit")' in keys
|
|
assert "event.preventDefault();\n event.stopPropagation();" in keys
|
|
assert "state.apexLock[index] === true" in keys # 고정 IP 는 안 옮김
|
|
assert "shortfallCrossed(" in keys # 하한 검사 = 끌기와 같음
|
|
assert "params.commit();" in keys # 뗄 때 한 걸음(스냅이면 그때 맞춤)
|
|
# 종단 ▲▼ 는 앞선 preventDefault 를 보고 비킴
|
|
tools = _read("B05_Profile_UI_Profile_Panel_Tools.ts")
|
|
assert "if (event.defaultPrevented) return;" in tools
|
|
base = (ROOT / "B06_Section/B06_Section_UI_Cross_Panel_Base.ts").read_text(encoding="utf-8")
|
|
assert "export function lastPointerWithin(selector: string)" in base
|
|
|
|
|
|
def test_RouteEdit_본문_줄_안_늘림() -> None:
|
|
assert len(_read("B05_Profile_UI_RouteEdit.ts").splitlines()) <= 700
|