Files
Aislo/resources/tester/test_399_plan_structure_marks.py
T
eomsangdonandClaude Opus 5.5 c3efa6dd7e feat(B05 평면 구조물 마커): 구조물 측점 마커 · 고름 정보 창 · 20 m 법선 · 끌기 · 방향키 1 m (399)
- 마커 = 종단 알약과 같은 목록(laneStructures) · 노선 위 알약 꼴(종류 색) · 스냅 · 간격과 무관
- 고름 = 알약 고름과 같은 길(onStructureSelect · 공용 고름) · 알약 벌룬 그대로 · 좌우 20 m 법선
- 끌기 · 방향키 = 노선 따라 정수 m 1 m 씩 · 시점 · 종점 밖 안 감 · 놓을 때 알약 끌기와 같은 길로 한 번
- 집기 차례 = 교각점 · 곡선 손잡이 다음 · 옛 마름모 지움
- 시험 test_399_plan_structure_marks · test_391 마름모 줄 고침

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XWh5wNNycMkbwMpACz1rte
2026-10-17 21:43:51 +09:00

129 lines
5.3 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);\n drawStructureMarks")
nodes = render.index("scene.planned.forEach((vertex, index) => {")
assert labels < nodes # 라벨 위 · 교각점 아래
def test_집기_차례는_교각점_손잡이_다음() -> None:
pointer = _read("B05_Profile", "B05_Profile_UI_RouteEdit_Pointer.ts")
node = pointer.index("if (hitNode >= 0) {")
handle = pointer.index("} else if (dragHandle) {")
mark = pointer.index("} else if (marks.press(px, py)) {")
tick = pointer.index('if (!pick || !("chainage" in pick)) return false;')
assert node < handle < mark < tick
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 # 교각점 고름 = 교각점 방향키 몫
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