- 서버: sections save · confirm 이 최신 아닌 노선 id 를 409 로 거절(옛 노선 재계산 없음) - 화면: [저장] · [확정] 앞에서 서버 노선과 대조 · 다르면 아무것도 안 보내고 페이지 새로 세움 - 화면: 종단 보기 신선도 확인에서 노선이 바뀌면 선만 다시 그리지 않고 페이지 새로 세움 - 시험: test_76_stale_route_save · 기존 저장 시험에 최신 노선 조회 가짜값 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYJJRCfHfdCGNhmXTjQKV7
121 lines
4.3 KiB
Python
121 lines
4.3 KiB
Python
"""[저장]이 「행은 있는데 설계가 빈 측점」을 채우는지 (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"))
|
|
# 화면이 쥔 노선 = 최신 노선(옛 노선 저장 거절은 `test_76_stale_route_save`).
|
|
monkeypatch.setattr(confirm, "get_workflow_route_context", _async({"route_id": 184}))
|
|
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
|