"""418 초기화 정리(요구 254-3 · 253-6). - 「노선 추천」 칸 [초기화] 없음 · 그 단추만 쓰던 길(편집기 handler · `initial_route`) 없음 - 좌측 아래 [초기화] — 저장 안 한 B08 · B09 초안 남김 · B05 · B06 초안만 지움(진짜 TS) - 추천 [적용] → 고쳐 저장 → 아래 [초기화] = [적용]한 노선(진짜 `refresh_initial_snapshot`) """ import asyncio import json import subprocess from contextlib import asynccontextmanager from pathlib import Path from uuid import uuid4 import pytest from common_util.common_util_initial_snapshot import ( restore_snapshot_files, save_initial_snapshot, ) ROOT = Path(__file__).resolve().parents[2] HELPER = Path(__file__).with_name("helper_418_reset_drafts.cjs") def _read(rel: str) -> str: return (ROOT / rel).read_text(encoding="utf-8") def test_노선_추천_칸에_초기화_단추_없음(): part = _read("B05_Profile/B05_Profile_UI_Panel_Recommend.ts") assert 'data-act="reset"' not in part and "resetButton" not in part assert part.count('data-act="recommend" disabled') == 1 initial = _read("B05_Profile/B05_Profile_UI_RouteEdit_Initial.ts") assert "resetButton" not in initial and "initialRouteSnapshot" not in initial assert "initial_route" not in _read("B05_Profile/B05_Profile_Api_Replan.ts") replan = _read("B05_Profile/B05_Profile_Router_Replan.py") assert '"initial_route"' not in replan and "_initial_shape" not in replan def test_아래_초기화는_B08_B09_초안_남김(): out = json.loads( subprocess.run( ["node", str(HELPER)], capture_output=True, text=True, encoding="utf-8", check=True ).stdout ) seed, left = out["seed"], out["left"] for name in ("b08-materials", "b08-hydro", "b08-options", "b08-milestone", "b09-estimation"): assert left[name] == seed[name], name # B05 · B06 초안(프로젝트 범위 · 노선 범위)은 지움 assert left["route-draft"] is None and left["std-cross"] is None assert left["crossdesign"] is None # 다른 프로젝트 초안은 안 건드림 assert out["other"] == seed assert [c[0] for c in out["calls"]] == ["resetRouteDesign", "toast", "reload"] class _Cursor: def __init__(self): self.lastrowid = 0 self._rows = [] async def __aenter__(self): return self async def __aexit__(self, *_): return False async def execute(self, sql, params=None): self._rows = [{"id": 7, "project_id": "p1"}] if "FROM routes" in sql else [] async def fetchone(self): return self._rows[0] if self._rows else None async def fetchall(self): return self._rows class _Connection: def cursor(self, *_args, **_kwargs): return _Cursor() class _Pool: @asynccontextmanager async def acquire(self): yield _Connection() @pytest.fixture def project(tmp_path: Path) -> Path: (tmp_path / "B05_Profile/route").mkdir(parents=True) return tmp_path def _write_route(root: Path, tag: str) -> None: (root / "B05_Profile/route/planned_route.csv").write_text(f"x,y\n{tag}\n", encoding="utf-8") def _route(root: Path) -> str: return (root / "B05_Profile/route/planned_route.csv").read_text(encoding="utf-8") def test_추천_적용_뒤_고쳐도_아래_초기화는_적용_노선(project, monkeypatch): from B05_Profile import B05_Profile_Router_RouteInitial as initial_router monkeypatch.setattr(initial_router, "get_db_pool", lambda: _Pool()) # ① 자동설계 체인 직후 초기값 _write_route(project, "auto") asyncio.run(save_initial_snapshot(_Connection(), project, 7)) # ② 추천 [적용](as_initial) — 그 노선으로 초기값 다시 뜸 _write_route(project, "applied") asyncio.run(initial_router.refresh_initial_snapshot(uuid4(), project, 7)) # ③ 손으로 고쳐 [저장] — 초기값 그대로(as_initial 아님 · 스냅샷 안 부름) _write_route(project, "edited") # ④ 아래 [초기화] = 초기값 파일 복원 restore_snapshot_files(project) assert _route(project) == "x,y\napplied\n" # ⑤ 다른 추천으로 바꿔 [적용] → 그것이 새 초기화 자리 _write_route(project, "applied2") asyncio.run(initial_router.refresh_initial_snapshot(uuid4(), project, 7)) _write_route(project, "edited2") restore_snapshot_files(project) assert _route(project) == "x,y\napplied2\n"