Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
96 lines
4.7 KiB
Python
96 lines
4.7 KiB
Python
"""356 B06 횡단 카드 — 키 강조 · 중심점 좌우(요구 235-17 · 18).
|
|
|
|
못박는 것
|
|
- 356-2 카드 초점 없음 — 마우스로 고른 뒤 키를 눌러도 초점 테두리(다른 색) 안 뜸 · ▲▼ 계획고는 창 듣개.
|
|
- 356-3 중심점 = 보라 선 고름 끝 조각(판정 원 · 노면 판정보다 위 · 다른 고름과 하나만) · ▲▼ = 종단 계획고 ·
|
|
◀▶ · 가로 끌기 = 그 측점 노선 좌우(0.5 m 안 노드 옮김 · 곡선 안 = 교각점 · 아니면 끼움 · 고정 노드 안 옮김) ·
|
|
놓을 때 한 번 · 뒤 측점은 묶음이 다시 셈(바뀐 범위 = 앞 노드 ~ 끝) · 노면 그대로(364-7 · 모든 측점 계획고 ·
|
|
기울기 · R 그대로) · 되돌리기 한 걸음 ·
|
|
B06 을 바로 열어 편집기가 없으면 종단 보기를 숨긴 채 세움.
|
|
|
|
진짜 TS 는 `helper_356_center.cjs` 가 Node 로 돌림.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
B06 = ROOT / "B06_Section"
|
|
|
|
|
|
def test_카드_초점_없음():
|
|
view = (B06 / "B06_Section_UI_Cross_View.ts").read_text(encoding="utf-8")
|
|
assert "card.tabIndex" not in view
|
|
assert 'card.addEventListener("keydown"' not in view
|
|
assert 'card.addEventListener("click", () => onSelect(section.station_id));' in view
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def ts() -> dict:
|
|
proc = subprocess.run(
|
|
["node", str(HERE / "helper_356_center.cjs")],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
def test_노드_고름_끼움_옮김_고정_교각점(ts):
|
|
assert ts["insert"] == {
|
|
"kind": "insert",
|
|
"index": 1,
|
|
"at": [40, 1],
|
|
} # 직선 = 측점 자리 + 좌 1 m 끼움
|
|
assert ts["near"] == {"kind": "move", "index": 1, "to": [40.3, -0.5]} # 0.5 m 안 노드 = 옮김
|
|
assert ts["nearLocked"] == {"kind": "locked", "index": 1} # 고정 노드 = 안 옮김
|
|
hit = ts["curveHit"]
|
|
assert hit["kind"] == "move" and hit["index"] == 1 # 곡선 안 = 그 교각점
|
|
ax, ay = ts["curveApex"]
|
|
assert ((hit["to"][0] - ax) ** 2 + (hit["to"][1] - ay) ** 2) ** 0.5 == pytest.approx(1.0)
|
|
|
|
|
|
def test_뒤_측점은_묶음이_다시_셈(ts):
|
|
assert ts["range"] == {"fromM": 0, "toM": None} # 앞 노드 ~ 끝(Infinity)
|
|
|
|
|
|
def test_높이_그대로_되돌리기_한_걸음_바로_열기(ts):
|
|
assert ts["opened"] == 1 and ts["moved"] is True # 편집기 없음 → 종단 보기 숨긴 채 세움
|
|
assert ts["planned"] == [[0, 0], [40, 1], [100, 0]]
|
|
assert len(ts["applied"]) == 1 # 편집기 한 걸음
|
|
assert ts["zRefit"] != pytest.approx(ts["zBefore"], abs=1e-3) # 묶음 다시 맞춤이면 쓸림
|
|
assert ts["graded"] == 1 and ts["zAfter"] == pytest.approx(ts["zBefore"], abs=1e-3)
|
|
# 364-7 노면 그대로 — 바뀐 구간 모든 측점 계획고 · 최대 기울기 · 종단곡선 R 그대로
|
|
assert ts["heightsAfter"] == pytest.approx(ts["heightsBefore"], abs=1e-3)
|
|
assert ts["gradeAfter"] == pytest.approx(ts["gradeBefore"], abs=1e-6)
|
|
assert sum(ts["curvesAfter"], []) == pytest.approx(sum(ts["curvesBefore"], []))
|
|
assert ts["canUndo"] and ts["undoOne"] and not ts["canUndoAfter"] # 노선 + 계획고 = 한 걸음
|
|
locked = ts["locked"]
|
|
assert locked["moved"] is False and locked["toast"][1] == "info"
|
|
assert locked["planned"] == [[0, 0], [40.3, 0], [100, 0]]
|
|
|
|
|
|
def test_배선():
|
|
pick = (B06 / "B06_Section_UI_Cross_Design_Pick.ts").read_text(encoding="utf-8")
|
|
assert "center: section.chainage_m," in pick # designLineMoves → 카드 고름 끝 조각
|
|
assert 'if (axis === "center") return centerShift?.step(dir);' in pick
|
|
# 364-7 덧 — 중심점 ◀▶ 툴팁 = 노선 좌우 · ↺ · 소단 ▲▼ 숨김
|
|
assert "`이 측점 노선을 화면 ${screen}으로 0.1 m`" in pick
|
|
assert '[toLeft.title, toRight.title] = [stepTitle("왼쪽"), stepTitle("오른쪽")];' in pick
|
|
assert 'move.controls.children[1]?.classList.toggle("is-hidden", axis === "center");' in pick
|
|
assert 'lift.row.classList.toggle("is-hidden", axis !== "depth");' in pick
|
|
order = (B06 / "B06_Section_UI_Cross_Pick_Order.ts").read_text(encoding="utf-8")
|
|
assert "layer.append(...surfaces, ...edges, ...lines, ...centers);" in order
|
|
edit = (ROOT / "B05_Profile" / "B05_Profile_UI_RouteEdit.ts").read_text(encoding="utf-8")
|
|
assert "bindRouteShift(host, projectId, snapshotNow, applyEdit," in edit
|
|
page = (ROOT / "A00_Common" / "design" / "design_page.ts").read_text(encoding="utf-8")
|
|
assert 'setRouteShiftOpener(() => shared.ensureView("profile"), showToast);' in page
|