"""453 B05 평면 편집 — 집기 한 판정 · 손잡이 끌기 · 막힌 걸음 놓음 · 스냅만 바꾼 초안. 못박는 것 - 433-14 ③ · 433-21 ③ 노드 가운데 6 px = 노드 · 밖 = 마커 · 노드 · 손잡이 중 가까운 것 · 맴돔 커서 같은 판정. - 433-14 ① 막힌 걸음만 하고 놓으면 미리보기 맞춤을 누르기 전 자리로(맞추지 않은 기준 13/13 → 0). - 433-14 ② 스냅 · 분석 지형만 바꾼 뒤 노선이 처음으로 돌아가도 다리 초안 있음(null 아님). - 433-21 ① 손잡이 끌기 훑기는 `test_390_5_snap_step_ops`. 짝: `helper_453_plan_pick_draft.cjs`(진짜 TS `_Input` · `_History` · `_Draft` · `StationFit`). """ import json import subprocess from pathlib import Path import pytest HERE = Path(__file__).resolve().parent B05 = HERE.parents[1] / "B05_Profile" def _read(name: str) -> str: return (B05 / name).read_text(encoding="utf-8") @pytest.fixture(scope="module") def got() -> dict: proc = subprocess.run( ["node", str(HERE / "helper_453_plan_pick_draft.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_노드_가운데만_노드_밖은_가까운_것(got) -> None: p = got["pick"] assert ( p["handleSide"] == "handle" and p["handleCenter"] == "handle" ) # 예전 = 노드 12 px 안이라 노드 assert p["coreEdge"] == "pick" and p["nodeCore"] == "pick" assert p["nodeCloser"] == "pick" and p["handleOnly"] == "handle" and p["nothing"] == "pick" assert p["handleDistance"] == 3 def test_마커_겹친_교점_가운데는_교점(got) -> None: p = got["pick"] assert p["markOnCore"] == "pick" # 예전 = 마커 먼저 assert p["markCloser"] == "mark" and p["nodeBeatsMark"] == "pick" and p["tie"] == "mark" def test_누름_맴돔_커서_한_판정() -> None: pointer = _read("B05_Profile_UI_RouteEdit_Pointer.ts") down = pointer[pointer.index('addEventListener("pointerdown"') :] down = down[: down.index('addEventListener("pointermove"')] assert "const choice = chooseAt(px, py);" in down assert "if (choice.mark && marks.press(px, py)) {" in down assert "dragHandle = choice.handle;" in down and "handleAt(px, py)" not in down move = pointer[pointer.index('addEventListener("pointermove"') :] move = move[: move.index("const endDrag")] hover = move[move.index("const measuring") :] assert "chooseAt(px, py)" in hover and "handleAt(px, py)" not in hover assert "marks.over(" not in pointer and "pressWinner(" in pointer def test_막힌_걸음만_놓으면_되돌림(got) -> None: b = got["blocked"] assert b["drags"] == 13 and b["previewMoved"] == 13 and b["leftAfterRelease"] == 0 pointer = _read("B05_Profile_UI_RouteEdit_Pointer.ts") end = pointer[pointer.index("const endDrag") :] assert end.index("if (!dragMoved && dragRaw) {") < end.index("if (dragMoved) {") def test_스냅만_바꾼_뒤_처음으로_초안_있음(got) -> None: d = got["draft"] assert d["snapChanged"] == [60, 50, 60, 50] # 처음 노선(50)이어도 초안 assert d["same"] == [60, None, 60, None] and d["old"] == [60, None] edit = _read("B05_Profile_UI_RouteEdit.ts") assert "draftLink.watch(history, options.draft, snap.draft, otherChanged);" in edit assert "const dirty = lineChanged(history) || otherChanged();" in edit assert "changed: () => (!!history && lineChanged(history)) || otherChanged()," in edit