- ② 카드 안 노면공 포장층 누름 = 목록 고름과 같은 길(범위 카드 전부 · 포장층 강조) — 카드 고름보다 먼저 가로챔 - ③ 카드 하나 누름 = 연 노면공 · 범위 강조 풂 · 그 카드 하나(165-1 노면공 지킴 · 167-3 재누름 그대로 없앰) - 카드 고름 세션 = 그 측점(구조물 id 는 목록 · 알약 · 넘김이 고른 것만) - 종단: 구조물 넘김이면 측점선 · 3D 띠 안 켬 - 새 시험 test_189_1_pave_pick · test_165 · test_188_1 기대값 41번 규칙으로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
131 lines
4.2 KiB
Python
131 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""PLAN 189-1 — 노면공(여러 측점 구간) 고름 세 갈래 · 종단 측점선(사용자 41번).
|
|
|
|
못박는 것
|
|
① 좌측 목록 노면공 = 범위 카드 전부 테두리 + 포장층 강조 · 카드 하나 안 고름 · 종단 측점선 없음.
|
|
② 카드 안 노면공 형상 누름 = ① 과 같음(고른 카드도 풂 · 카드 고름 리스너 안 돎).
|
|
③ 카드 하나 누름(형상 밖) = 목록 고름 · 범위 강조 풂 · 그 카드 하나 · 종단 측점선 = 그 카드 · 세션 sid 없음.
|
|
같은 카드 재누름 = 풂 · 관 자리 카드 = 관.
|
|
|
|
상태는 `helper_165_pavement_flow.cjs`(진짜 SPN) · 형상 → 노면공 찾기는 `helper_189_1_pave_shape.cjs`.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
ROOT = os.path.abspath(os.path.join(HERE, "..", ".."))
|
|
|
|
pytestmark = pytest.mark.skipif(
|
|
not os.path.isdir(os.path.join(ROOT, "config", "node_modules")),
|
|
reason="프론트엔드 의존성 미설치",
|
|
)
|
|
|
|
|
|
def _node(name: str) -> dict:
|
|
proc = subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
["node", os.path.join(HERE, name)],
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=60,
|
|
)
|
|
assert proc.returncode == 0, proc.stderr
|
|
return json.loads(proc.stdout)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def flow() -> dict:
|
|
return _node("helper_165_pavement_flow.cjs")
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def shape() -> dict:
|
|
return _node("helper_189_1_pave_shape.cjs")
|
|
|
|
|
|
def _read(*parts: str) -> str:
|
|
with open(os.path.join(ROOT, *parts), encoding="utf-8") as handle:
|
|
return handle.read()
|
|
|
|
|
|
PAVE = {
|
|
"form": "pave",
|
|
"pill": "pave",
|
|
"paveLayer": "pave",
|
|
"paveCards": 12,
|
|
"card": None,
|
|
"sid": "pave",
|
|
"line": None,
|
|
}
|
|
|
|
|
|
def _card(at):
|
|
return {
|
|
"form": None,
|
|
"pill": None,
|
|
"paveLayer": None,
|
|
"paveCards": 0,
|
|
"card": at,
|
|
"sid": None,
|
|
"line": None if at is None else f"s{at}",
|
|
}
|
|
|
|
|
|
def test_1_목록_고름은_범위_카드_전부_종단_선_없음(flow) -> None:
|
|
assert flow["r1"] == PAVE
|
|
|
|
|
|
def test_2_형상_누름은_목록_고름과_같음(flow) -> None:
|
|
assert flow["r2first"] == PAVE # 처음부터 형상
|
|
assert flow["r2"] == PAVE # 카드 하나 고른 뒤 형상 = 옛 카드 풂
|
|
assert flow["r2reveal"] == "s40"
|
|
|
|
|
|
def test_3_카드_하나는_목록_고름과_범위_강조를_풂(flow) -> None:
|
|
assert flow["r3"] == _card(140)
|
|
assert flow["r3b"] == _card(100)
|
|
assert flow["r3re"] == _card(None) # 같은 카드 재누름 = 풂
|
|
pipe = flow["r3pipe"]
|
|
assert (pipe["form"], pipe["pill"], pipe["paveCards"], pipe["sid"]) == (
|
|
"pipe-80.17",
|
|
"pipe-80.17",
|
|
0,
|
|
None,
|
|
)
|
|
|
|
|
|
def test_누른_포장층은_범위_표식으로_그_노면공(shape) -> None:
|
|
assert shape["pave"] == "pave"
|
|
assert shape["pave2"] == "pave2" # 겹친 노면공 = 누른 층
|
|
for key in ("plainLayer", "outside", "noTarget", "unknown"):
|
|
assert shape[key] is None, key
|
|
|
|
|
|
def test_배선() -> None:
|
|
view = _read("B06_Section", "B06_Section_UI_Section_View.ts")
|
|
# 형상 누름은 카드 고름보다 먼저 가로챔(잡기 단계 · 전파 멈춤)
|
|
body = re.search(
|
|
r"const pave = pavementAt\(event\.target, spanMarks\);(.*?)true,\n", view, re.S
|
|
)
|
|
assert body, "형상 누름 배선 없음"
|
|
assert "event.stopPropagation();" in body.group(1)
|
|
assert "pavementSelectListener?.(pave.structure_id);" in body.group(1)
|
|
cross = _read("A00_Common", "design", "design_view_cross.ts")
|
|
assert (
|
|
"sectionView.setPavementSelectListener((id) => structuresPanel.selectStructure(id));"
|
|
in cross
|
|
)
|
|
# 카드 하나 고름 = 그 측점(구조물 id 는 목록 · 알약 · 넘김만)
|
|
assert "const preferred = structuresPanel.preferred() !== null;" in cross
|
|
assert (
|
|
"const picked = preferred ? opened : { chainageM: opened.chainageM, structureId: null };"
|
|
in cross
|
|
)
|
|
profile = _read("A00_Common", "design", "design_view_profile.ts")
|
|
assert "const structurePick = !!readSelection(activeProjectId)?.structureId;" in profile
|