"""440 구조물 횡단 · 내부 구조물 하이라이트(요구 267). ① 노선 초안 동안 B06 카드(묶음 새 상세) 번호 = 저장 카드 번호(같은 측점 열쇠 · 옮긴 관도) — 찾기 상세 (갈아끼운 캐시)에 모든 카드 번호가 있음 · 찾기 넷(카드 고름 · 목록 → 카드 · 넘김 · 풀기)은 지금 그린 상세. ② 평면 패널 빈 곳 누름 = 평면 마커가 고른 것만 풂(`test_409` 의 deselectOther · deselectOwn). ③ 바뀜 신호에서 B06 목록도 자리가 바뀌었으면 다시 실음. ④ 암 경계선 판정(굵은 투명 선)은 구조물 판정면 아래 — 구조물 아랫부분 누름이 구조물을 고름. TS 셈은 `helper_440_draft_card_ids.cjs`. ./venv/Scripts/python.exe -m pytest resources/tester/test_440_cross_draft_pick.py -q """ import json import subprocess from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] HELPER = Path(__file__).with_name("helper_440_draft_card_ids.cjs") SAVED_PIPE = "station_000000351000" 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["allFoundInSwapped"] is True assert got["sameOrder"] is True def test_옮긴_관_카드는_저장_번호_새_자리(got) -> None: assert got["pipeCard"] == [SAVED_PIPE, 354, 354] assert got["longIds"] == got["draftIds"] # 종단 측점 머리도 같은 번호 def test_초안_새_측점은_누가거리_번호(got) -> None: assert got["addedId"] == "station_000000380000" def test_찾기_넷은_지금_그린_상세() -> None: cross = _read("A00_Common", "design", "design_view_cross.ts") assert "drawnDetail = shownDetail(projectId, sectionDetail);" in cross focus = cross[cross.index("const focusStationAt") : cross.index("const ownerAt")] assert "drawnDetail?.cross_sections" in focus and "sectionDetail" not in focus pick = cross[cross.index("sectionView.setStationSelectListener") :] assert "drawnDetail?.cross_sections.find" in pick[: pick.index("if (!target)")] restore = cross[cross.index("function restoreStructurePick") : cross.index("// 횡단 보기 강조")] assert "sectionDetail" not in restore and "drawnDetail," in restore assert "sections: () => drawnDetail?.cross_sections ?? []," in cross def test_바뀜_신호에서_목록_다시_실음() -> None: cross = _read("A00_Common", "design", "design_view_cross.ts") watch = cross[cross.index("watchDrafts(projectId, () => {") :] watch = watch[: watch.index("}),")] assert "if (structuresPanel.listStale()) reloadPanel();" in watch panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts") assert "readPendingStructures(deps.projectId) ?? storedStructures" in panel assert "readPendingPipes(deps.projectId) ?? storedPipes" in panel def test_평면_빈_곳_누름은_마커_고름만() -> None: marks = _read("B05_Profile", "B05_Profile_UI_RouteEdit_StructureMarks.ts") assert "deselect: () => planMarks(canvas)?.picked === ownPick && deselect()," in marks assert "ownPick = mark.id;" in marks def test_암_경계_판정은_구조물_판정면_아래() -> None: order = _read("B06_Section", "B06_Section_UI_Cross_Pick_Order.ts") assert "layer.append(...rocks, ...surfaces, ...edges, ...lines, ...centers);" in order lines = order[order.index("const lines = kids.filter(") :] assert "!el.classList.contains(ROCK_HIT_CLASS)" in lines[: lines.index(");")] pick = _read("B06_Section", "B06_Section_UI_Cross_Design_Pick.ts") assert 'export const ROCK_HIT_CLASS = "b06-chart__rock-hit";' in pick