⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt` 가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는 시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음. - `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침** - `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시) - 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q` 옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0 ⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
65 lines
3.0 KiB
Python
65 lines
3.0 KiB
Python
"""저장된 표준 횡단면이 **브라우저까지 닿는지**.
|
|
|
|
왜 (2026-09-07 실측) — 표준단면 편집값은 sessionStorage 에만 살아서 **탭을 새로 열면**
|
|
사라졌다. 그때 브라우저는 config 기본값으로, 서버는 저장분으로 계산해 같은 측점이 갈렸다.
|
|
용화(route 169) 실측 — 저장분은 암반 횡단경사 **5%** · 측구 상단폭 **0.9m**,
|
|
config 기본값은 **3%** · **0.69m**. 표준단면은 모든 측점의 횡단 모양을 정하므로
|
|
면적·유토곡선·수량까지 그대로 흐른다.
|
|
|
|
고침은 두 줄이다 — `sections/context` 가 저장분을 **한 칸 더** 실어 보내고(기존 기본값 칸은
|
|
그대로), 브라우저가 **세션이 비었을 때만** 그 값으로 세운다. 이 시험은 그 두 성질을 지킨다.
|
|
"""
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
if str(PROJECT_ROOT) not in sys.path:
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
from B06_Section.B06_Section_Schema import SectionContextResponse # noqa: E402
|
|
|
|
_FETCH = PROJECT_ROOT / "B06_Section" / "B06_Section_Api_Fetch.ts"
|
|
_ROUTER = PROJECT_ROOT / "B06_Section" / "B06_Section_Router.py"
|
|
|
|
|
|
def test_응답에_저장분_칸이_따로_있다():
|
|
"""기존 기본값 칸은 그대로 두고 한 칸만 더한 것 — 옛 화면이 안 깨진다."""
|
|
fields = SectionContextResponse.model_fields
|
|
assert "standard_cross_section" in fields, "기본값 칸이 사라짐"
|
|
assert "stored_standard_cross_section" in fields, "저장분 칸이 없음"
|
|
# 저장분이 없는 프로젝트도 있다 — 그때는 None 이어야 기본값으로 선다.
|
|
empty = SectionContextResponse(project_id="x", defaults=_defaults())
|
|
assert empty.stored_standard_cross_section is None
|
|
|
|
|
|
def _defaults():
|
|
from B06_Section.B06_Section_Schema import SectionOptionDefaults
|
|
|
|
return SectionOptionDefaults(
|
|
station_interval_m=20.0,
|
|
cross_half_width_m=20.0,
|
|
cross_sample_interval_m=0.5,
|
|
long_sample_interval_m=1.0,
|
|
vertical_exaggeration=2.0,
|
|
)
|
|
|
|
|
|
def test_라우터가_저장분을_실어_보낸다():
|
|
source = _ROUTER.read_text(encoding="utf-8")
|
|
assert "stored_standard_cross_section=stored_standard" in source, "응답에 안 실림"
|
|
assert "_stored_standard_cross_section(longitudinal_row)" in source, "저장분을 안 읽음"
|
|
|
|
|
|
def test_브라우저는_세션이_빈_경우에만_저장분으로_선다():
|
|
"""사용자가 그 탭에서 고친 값이 있으면 건드리면 안 된다 — 초안이 언제나 우선."""
|
|
source = _FETCH.read_text(encoding="utf-8")
|
|
assert "function seedStandardCross(" in source, "세우는 자리가 없음"
|
|
guard = re.search(
|
|
r"if \(stored && readState<unknown>\(\"std-cross\", projectId\) === null\)", source
|
|
)
|
|
assert guard, "세션이 있어도 덮어쓰는 모양임"
|
|
# 두 갈래(캐시·새 조회) 모두 지나야 새 탭에서도 선다.
|
|
assert source.count("seedStandardCross(projectId,") >= 2, "한쪽 갈래만 세움"
|