Files
Aislo/resources/tester/test_399_plan_structure_marks.py
T
eomsangdonandClaude Opus 5.5 92e5157890 fix(453 B05 평면 편집): 노드 가운데만 노드 우선 · 손잡이 끌기 측점 맞춤 · 막힌 걸음 놓음 되돌림 · 스냅만 바꾼 초안
- 433-14 ③ · 433-21 ③ 누름 · 맴돔 · 커서 한 판정(pressWinner) — 노드 가운데 6 px = 노드 · 밖 = 마커 · 노드 · 손잡이 중 가까운 것
- 433-21 ① 손잡이 끌기 = 노드 갈래와 같게 — 맞추기 전 자리에서 셈 · 미리보기 맞춤 · 측점 밖이 늘면 그 걸음 되돌림
- 433-14 ① 막힌 걸음만 하고 놓으면 미리보기 맞춤을 누르기 전 자리로
- 433-14 ② 사진첩 다리도 스냅 · 분석 지형 바뀜을 봄 — 노선이 처음으로 돌아가도 초안
- 433-1 test_365 ⑧ 이름 = 노선 한 걸음 + 계획고 맞춤
- 시험 test_453_plan_pick_draft 새로 · 390_5 손잡이 훑기 · 381_3 · 399 · 409 · 430 배선 글 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:33:24 +09:00

140 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""399 B05 평면 구조물 측점 마커(요구 250-2) — 알약과 같은 목록 · 고름 = 공용 고름 · 정보 창(알약 벌룬) ·
20 m 법선 · 끌기 · 방향키 = 노선 따라 정수 m 1 m 씩 · 시점 · 종점 밖 안 감 · 놓을 때 한 번 옮김(알약과 같은 길).
TS 셈은 `helper_399_plan_structure_marks.cjs`(Node · 노선 셈 · 법선 · 걸음은 진짜).
./venv/Scripts/python.exe -m pytest resources/tester/test_399_plan_structure_marks.py -q
"""
import json
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
HELPER = Path(__file__).with_name("helper_399_plan_structure_marks.cjs")
def _read(*parts: str) -> str:
return (ROOT.joinpath(*parts)).read_text(encoding="utf-8")
@pytest.fixture(scope="module")
def got() -> dict:
run = subprocess.run( # noqa: S603 — 고정 실행 파일
["node", str(HELPER)],
capture_output=True,
text=True,
encoding="utf-8",
timeout=120,
)
assert run.returncode == 0, run.stderr
return json.loads(run.stdout)
def test_마커_목록은_알약_목록(got) -> None:
assert got["laneGotSource"] is True # 알약 레인과 같은 `laneStructures`
assert got["plain"]["marks"] == [
{"color": "#e11d48", "at": [80, 0]}, # 40 m × 2 px · 종류 색
{"color": "#2563eb", "at": [160.34, 0]},
]
assert got["plain"]["normals"] == 0 and got["balloonsAfterPlain"] == 0
lane = _read("B05_Profile", "B05_Profile_UI_Structures_Marks.ts")
assert "const structures = laneStructures(options.structures);" in lane
marks = _read("B05_Profile", "B05_Profile_UI_RouteEdit_StructureMarks.ts")
assert "laneStructures(source.marks())" in marks
bridge = _read("B05_Profile", "B05_Profile_UI_Page_Structures.ts")
assert "setStructures([...ownStructures, ...pipeMarks]);" in bridge
assert "marks: (): StructureInstance[] => [...ownStructures, ...pipeMarks]," in bridge
assert "planMarksChanged(deps.projectId);" in bridge
def test_고름_정보_창_법선(got) -> None:
pipe = got["pickedPipe"]
assert pipe["ringAt"] == [[160.34, 0]] # 관 고름(누가거리만)도 그 마커
assert pipe["normal"] == [[160.34, -40], [160.34, 40]] # 좌우 20 m
assert pipe["balloon"]["lines"] == ["이름 pipe pos 80.17", "옵션 배수관"] # 알약 벌룬 줄
assert pipe["balloon"]["color"] == "#2563eb"
assert got["pickedStructureBalloon"] == ["이름 box pos 40", "옵션 BOX"]
assert got["balloonsAfterRelease"] == 0
def test_공용_고름과_같은_길() -> None:
view = _read("A00_Common", "design", "design_view_profile.ts")
assert " onStructureSelect,\n onStructureMarkMove,\n" in view # 알약 콜백 = 같은 함수
assert "select: onStructureSelect," in view and "move: onStructureMarkMove," in view
render = _read("B05_Profile", "B05_Profile_UI_RouteEdit_Render.ts")
labels = render.index("drawContourLabels(context, scene, band, style);")
nodes = render.index("scene.planned.forEach((vertex, index) => {")
hover = render.index("drawPickHover(context, scene, line, style, NODE_R);")
marks = render.index("drawStructureMarks(context, scene, line, style);")
turned = render.index("context.restore(); // 회전 끝")
assert labels < nodes < hover < marks < turned # 맨 위(409 — 교각점 · 손잡이 · 맴돔 위)
def test_집기_차례는_재기_다음_맨_앞() -> None:
pointer = _read("B05_Profile", "B05_Profile_UI_RouteEdit_Pointer.ts")
measure = pointer.index("void params.measure.pick(px, py);")
mark = pointer.index("if (choice.mark && marks.press(px, py)) {") # 433-21 ③ 가까운 것일 때
release = pointer.index("marks.deselect();")
node = pointer.index("if (hitNode >= 0) {")
handle = pointer.index("} else if (dragHandle) {")
tick = pointer.index('if (!pick || !("chainage" in pick)) return false;')
assert measure < mark < release < node < handle < tick # 409
def test_끌기_1m_정수_놓을_때_한_번(got) -> None:
assert got["pressMiss"] is False and got["pressA"] is True
assert got["selects"] == ["A"]
assert got["movesBeforeRelease"] == 0 # 끄는 동안은 미리보기만
assert got["dragMove"] == ["A", 43] # 3 m
assert "2+0 → 2+3(+3 m) 옮김" in got["dragDoneStatus"]
assert got["oldDecimalStay"] is True # 옛 소수 자리 눌렀다 떼기 = 안 옮김
assert got["oldDecimalMoved"] == ["pipe-80.17", 81]
def test_노선_밖_안_감(got) -> None:
assert got["pastEnd"] == ["A", 200]
assert got["beforeStart"] == ["A", 0]
assert got["logic"]["clamp"] == [0, 199] # 종점 199.6 → 199(정수 m 안쪽)
assert got["logic"]["step"] == [81, 0, 199]
def test_방향키_노선_따라_1m(got) -> None:
assert got["keyRight"] == ["A", 41]
assert got["keyLeft"] == ["A", 39]
assert got["keyUpPerpendicular"] == ["A", 41] # 직각 = → · ↑ 가 +
assert got["keyRightWestward"] == ["A", 39] # 노선이 서쪽으로 가면 → = 뒤로
assert got["keyWithNodePicked"] == 0 # 교각점 고름 = 교각점 방향키 몫
def test_관_목록이_늦게_와도_연달아_두_걸음(got) -> None:
assert got["lagHeldAt"] == [[162, 0]] # 옮긴 자리 · 고름 그대로(목록은 아직 80.17)
assert got["lagTwoSteps"] == [["pipe-80.17", 81], ["pipe-80.17", 82]]
assert got["lagCaught"] == [[164, 0]] # 목록이 따라오면 목록 자리
assert got["keyNoPick"] == 0
def test_고른_마커_찾기(got) -> None:
logic = got["logic"]
assert logic["round"] == [41, 42]
assert (logic["pickId"], logic["pickNear"], logic["pickFar"], logic["pickOther"]) == (
"A",
"A",
None,
None,
)
assert got["redrawnOnChange"] == 1
def test_편집기_줄_수_그대로() -> None:
edit = _read("B05_Profile", "B05_Profile_UI_RouteEdit.ts")
assert edit.count("\n") <= 695
for name in (
"B05_Profile_UI_RouteEdit_StructureMarks.ts",
"B05_Profile_UI_RouteEdit_Render.ts",
"B05_Profile_UI_RouteEdit_Pointer.ts",
):
assert _read("B05_Profile", name).count("\n") <= 700