# -*- coding: utf-8 -*- """467 덧 (요구 272) — 횡단 고름을 되돌리면(↶) 다시 셈이 정본 값으로 돌아옴. 못박는 것 - 카드 단추(지반 · 단면 갈래 · 측구) · 노견 확장 · 소단 깊이 · 암 경계를 세션에 쓰고 다시 셈 → 세션 칸 지움(↶) → 설계 = 고르기 전(정본으로 셈) 설계와 글자까지 같음 · 다시 씀(↷) = 고른 값과 같음. - 다시 셈 입력 물러섬 = 저장 정본 설계(메모리 설계에 남은 앞 고름 · 결과 아님). - 고름 단추가 메모리 상세 설계를 덮지 않음(`handleDesignChange`). Node 헬퍼 `helper_272_choice_undo.mjs` 가 vite ssr 로 묶은 진짜 모듈을 부름. """ import json import shutil import subprocess import sys from pathlib import Path import pytest HERE = Path(__file__).resolve().parent ROOT = HERE.parents[1] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from config.config_system import ( # noqa: E402 STANDARD_CROSS_SECTION, STANDARD_ROCK_BOUNDARY_DEFAULT_OFFSET_M, ) GROUND = [ {"offset_m": o / 2, "elevation_m": round(100.0 + 0.35 * o / 2, 4), "valid": True} for o in range(-24, 25) ] @pytest.fixture(scope="module") def out(tmp_path_factory): work = tmp_path_factory.mktemp("b272undo") build = subprocess.run( # noqa: S603 — 고정 실행 파일 [ "node", str(ROOT / "config" / "node_modules" / "vite" / "bin" / "vite.js"), "build", "--configLoader", "runner", "--ssr", "../resources/tester/helper_272_choice_undo_entry.ts", "--outDir", str(work), "--logLevel", "error", ], cwd=ROOT, capture_output=True, text=True, encoding="utf-8", timeout=300, ) assert build.returncode == 0, build.stderr bundle = work / "bundle.mjs" shutil.copy(work / "helper_272_choice_undo_entry.js", bundle) job = work / "job.json" job.write_text( json.dumps( { "standard": STANDARD_CROSS_SECTION, "rockDefault": STANDARD_ROCK_BOUNDARY_DEFAULT_OFFSET_M, "ground": GROUND, } ), encoding="utf-8", ) proc = subprocess.run( # noqa: S603 ["node", str(HERE / "helper_272_choice_undo.mjs"), str(bundle), str(job)], cwd=ROOT, capture_output=True, text=True, encoding="utf-8", timeout=120, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_고르기_전_메모리_다시_셈_같음(out): assert out["pristineSame"] @pytest.mark.parametrize("name", ["choice", "shoulder", "bermDepth"]) def test_고름_되돌림_정본_다시_고름_같음(out, name): case = out["cases"][name] assert case["changed"], name # 고름이 실제로 설계를 바꿈 assert case["undoIsCanon"], name # ↶ = 정본 assert case["redoIsPicked"], name # ↷ = 고른 값 assert case["undoAgain"], name def test_암_경계_되돌림_정본(out): case = out["cases"]["rock"] assert case["undoIsCanon"] and case["redoIsPicked"] and case["undoAgain"] def test_단추가_메모리_설계를_안_덮음(): sync = (ROOT / "B06_Section" / "B06_Section_UI_Page_Design_Sync.ts").read_text(encoding="utf-8") body = sync[ sync.index("async function handleDesignChange") : sync.index("function recomputeIfRock") ] assert "target.design" not in body refresh = (ROOT / "B06_Section" / "B06_Section_Cross_Refresh.ts").read_text(encoding="utf-8") assert "savedDesigns(projectId, input.routeId)" in refresh