"""[저장]이 「행은 있는데 설계가 빈 측점」을 채우는지 (2026-09-09). 재생성이 `cross_sections` 행을 지우고 다시 쓰면 `data.design` 에 면적 4키만 남는다. `get_cross_section_designs` 는 `ground_type` 있는 줄만 담으므로 그 상태는 「설계 없음」이고, B08 토적표가 통째로 0 이 됐다(창 셋에서 같은 증상). 예전에는 체인이 뒤이어 부르는 [확정]이 그 자리를 채워 가려져 있었다. ⚠ **값이 있는 행은 안 건드린다**가 이 시험의 핵심이다 — 사용자 조작값·이월분이 거기 있다. """ from __future__ import annotations import asyncio import sys from pathlib import Path from typing import Any import pytest PROJECT_ROOT = Path(__file__).resolve().parents[2] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) import B06_Section.B06_Section_Router_Confirm as confirm # noqa: E402 class _Conn: async def begin(self) -> None: return None async def commit(self) -> None: return None async def rollback(self) -> None: return None class _Acquire: async def __aenter__(self) -> _Conn: return _Conn() async def __aexit__(self, *_: Any) -> None: return None class _Pool: def acquire(self) -> _Acquire: return _Acquire() def _async(value: Any): async def _inner(*_: Any, **__: Any) -> Any: return value return _inner def _run_save(monkeypatch: pytest.MonkeyPatch, missing: list[float]) -> list[float]: """`save_sections` 를 돌리고 **기본 설계를 계산하라고 넘긴 측점 목록**을 돌려준다.""" seen: list[float] = [] monkeypatch.setattr(confirm, "get_db_pool", lambda: _Pool()) monkeypatch.setattr( confirm, "get_longitudinal_section", _async({"longitudinal_file_path": "long.json"}) ) monkeypatch.setattr(confirm, "get_project_storage_relative_path", _async("1/3/proj")) monkeypatch.setattr(confirm, "get_cross_section_chainages", _async([0.0, 20.0, 40.0])) monkeypatch.setattr(confirm, "get_cross_sections_missing_design_chainages", _async(missing)) monkeypatch.setattr(confirm, "resolve_stored_project_path", lambda _p: str(PROJECT_ROOT)) # 행 자체가 없는 측점은 이 시험의 관심사가 아니다 — 빈 목록으로 고정한다. monkeypatch.setattr(confirm, "_rowless_station_chainages", lambda *_a, **_k: []) def _spy(_root, _path, chainages, _standard): seen.extend(chainages) return [(value, {"ground_type": "soil"}) for value in chainages] monkeypatch.setattr(confirm, "_compute_default_designs", _spy) monkeypatch.setattr(confirm, "_apply_section_edits", _async(None)) monkeypatch.setattr(confirm, "_recompute_stored_designs", _async(None)) from uuid import UUID response = asyncio.run( confirm.save_sections( project_id=UUID("fa76c162-71c7-46e5-a95d-fb3930665a45"), route_id=184, request=None ) ) assert getattr(response, "confirmed", None) is False, response return seen def test_설계가_빈_측점을_채운다(monkeypatch: pytest.MonkeyPatch) -> None: seen = _run_save(monkeypatch, [20.0, 40.0]) assert sorted(seen) == [20.0, 40.0] def test_값이_있는_행은_안_건드린다(monkeypatch: pytest.MonkeyPatch) -> None: """빈 측점이 없으면 기본 설계를 아예 계산하지 않는다 — 덮어쓸 일이 없다.""" seen = _run_save(monkeypatch, []) assert seen == [] def test_빈_설계의_뜻이_ground_type_없음이다() -> None: """판정은 `get_cross_sections_missing_design_chainages` 한 곳에서만 한다.""" import inspect from B06_Section.B06_Section_Repository import get_cross_sections_missing_design_chainages source = inspect.getsource(get_cross_sections_missing_design_chainages) assert 'design.get("ground_type")' in source def test_저장도_확정과_같은_판정을_쓴다() -> None: """두 갈래가 같은 조회를 써야 「저장했는데 확정과 다르다」가 안 생긴다.""" import inspect source = inspect.getsource(confirm.save_sections) assert "get_cross_sections_missing_design_chainages" in source