"""PLAN 323-6 바꿈 한 길 — 바뀜 신호 하나 · 종류 바꿈 표 규칙 · 그리기가 조정값을 안 만듦 · 옛 되얹기 걷음. - 구조물 초안도 설계 가게(`useDesignStore`)로 씀 = 관 초안과 같은 신호 · 칸은 그대로(`structures`) · 횡단 보기가 두 초안을 구독해 카드 · 그림을 다시(옛 되부름 `onStructuresChanged` 갈음). - 종류 바꿈 = 정본 같고 구조물은 자리꼴도 같아야 제자리(`swapsInPlace`) · 아니면 지우고 같은 기준 측점에 새로 (흐름 = test_319_kind_swap). - 카드 그리기의 적용값 되받기는 사용자가 조작한 세션이 있을 때만(자동 배치를 조정값으로 안 굳힘). TS 쪽 = `helper_323_6_change.cjs`(Node). """ from __future__ import annotations import json import subprocess from pathlib import Path import pytest HERE = Path(__file__).parent ROOT = HERE.parent.parent pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules").is_dir(), reason="프론트엔드 의존성 미설치" ) @pytest.fixture(scope="module") def out() -> dict: run = subprocess.run( ["node", str(HERE / "helper_323_6_change.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=120, check=True, ) return json.loads(run.stdout) def _src(*parts: str) -> str: return (ROOT.joinpath(*parts)).read_text(encoding="utf-8") def test_structure_draft_signals_through_store(out: dict) -> None: assert out["heard"] == [1, None, 1] and out["pipesHeard"] == 0 assert out["read"] == [{"structure_id": "w1", "type_id": "retaining_wall", "chainage_m": 10}] assert out["key"] is True # 칸 그대로 cross = _src("A00_Common", "design", "design_view_cross.ts") assert "watchDrafts(projectId," in cross and "onStructuresChanged" not in cross panel = _src("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts") assert "onStructuresChanged" not in panel # 옛 되부름 걷음 def test_change_signal_filters_option_only_pipe_edits(out: dict) -> None: # 관 놓기 · 옵션만 · 옮기기 · 종류 바꿈 · 구조물 · 끊은 뒤 = 1 · 0 · 1 · 1 · 1 · 0 assert out["watch"] == 4 def test_kind_swap_rule_from_table(out: dict) -> None: assert dict(out["swaps"]) == { "mirror>curb": True, "mirror>guardrail": False, "refuge>work_yard": True, "pipe>box_culvert": True, "pipe>revetment": True, "cross_underdrain>pipe": False, } def test_drawing_does_not_create_adjusts() -> None: controls = _src("B06_Section", "B06_Section_UI_Page_Station_Controls.ts") body = controls.split("syncApplied: (chainageM, role, applied) => {", 1)[1].split("},", 1)[0] assert "if (!stored || sameAdjust(stored, applied)) return;" in body def test_add_names_blocking_field() -> None: # [추가] 무반응 → 막힌 칸 이름 알림(323-6 고침 · 실시간 반영은 알림 없음) commit = _src("B05_Profile", "B05_Profile_UI_Structures_Panel_Commit.ts") assert "if (!live) showToast(" in commit assert "if (missing && !live) return stop(missing.input, labelOf(missing.key));" in commit assert 'return stop(input, labelOf("length_m"));' in commit def test_old_replay_removed() -> None: assert "replayDraftPipeOptions" not in _src( "B06_Section", "B06_Section_UI_Page_Pipe_Options.ts" )