"""PLAN 472-5 5-D (요구 273) — B06 조정창 값 주인 = 세션 칸 하나 · 메모리 맵 걷음(N5). 못박는 것 - 조정창(반폭 · 흙막이 4축 · 유입 형식 · 연동 · 단 수 · 세월교)을 고친 뒤 ↶ 하고 다른 측점을 고쳐도 되돌린 값이 되살아나지 않음 — 옛 코드는 메모리 맵이 옛 값을 쥐고 다음 조작이 칸을 통째로 다시 써 ↶ 를 덮었음(옛 코드 실패). - ↶ 뒤 조정창 읽기 · 캐시 설계 칸(상세 가게 얹기 뒤) = 조작 전 값(저장분은 그대로) · ↷ = 다시 그 값. - 저장 묶음(횡단 patch 재료)도 세션 칸 그대로. ./venv/Scripts/python.exe -m pytest resources/tester/test_472_5d_adjust_owner.py -q """ from __future__ import annotations import json import shutil import subprocess from pathlib import Path import pytest HERE = Path(__file__).resolve().parent ROOT = HERE.parents[1] pytestmark = pytest.mark.skipif( not (ROOT / "config" / "node_modules" / "vite").is_dir(), reason="프론트엔드 의존성 미설치", ) SAVED_OUTLET = {"x": 2, "d": None, "h": None, "m": None} @pytest.fixture(scope="module") def out(tmp_path_factory) -> dict: work = tmp_path_factory.mktemp("s4725d") subprocess.run( # noqa: S603 — 고정 실행 파일 [ "node", str(ROOT / "config" / "node_modules" / "vite" / "bin" / "vite.js"), "build", "--configLoader", "runner", "--ssr", "../resources/tester/helper_472_5d_adjust_entry.ts", "--outDir", str(work), "--logLevel", "error", ], cwd=ROOT, check=True, capture_output=True, timeout=300, ) bundle = work / "bundle.mjs" shutil.copy(work / "helper_472_5d_adjust_entry.js", bundle) proc = subprocess.run( # noqa: S603 ["node", str(HERE / "helper_472_5d_adjust.mjs"), str(bundle)], 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_조작_A_는_세션_칸에(out) -> None: a = out["afterA"] assert a["revetx"]["100.00:inlet"]["x"] == 3 assert a["crossw"] == {"100.00": 6} assert a["inletstruct"] == {"100.00": "L"} assert a["revetlink"]["detached"] == {"120.00": True} assert a["extrawall"] == {"120.00": 2} assert a["fordadjust"]["140.00"]["inlet"]["lateralM"] == 2 def test_되돌리면_칸이_비고_조정창도_조작_전(out) -> None: assert out["afterUndo"] == {name: None for name in out["afterUndo"]} r = out["readsUndo"] assert r["inlet"]["x"] == 0 assert r["outlet"] == SAVED_OUTLET # 저장분 그대로 assert r["width100"] is None assert r["struct100"] == "auto" assert r["linked120"] is True assert r["extra120"] == 0 assert r["ford140"] == 0 def test_되돌린_뒤_캐시_설계_칸도_조작_전(out) -> None: """옛 코드 = 조정창이 캐시(section.design)에 실은 값이 ↶ 뒤에도 남아 그림 · [저장] 바탕으로 나감.""" d100, d120, d140 = out["designsUndo"] assert d100 == {"revet_adjust": {"outlet": SAVED_OUTLET}} assert d120 == {} assert d140 == {} def test_되돌린_뒤_다른_조작이_되돌림을_안_덮음(out) -> None: """N5 — 옛 코드는 메모리 맵이 A 값을 쥐고 B 를 쓸 때 통째로 다시 씀(옛 코드 실패).""" b = out["afterB"] assert set(b["revetx"]) == {"100.00:outlet"} assert b["revetx"]["100.00:outlet"]["x"] == 1 assert b["crossw"] == {"120.00": 8} assert b["inletstruct"] == {"120.00": "I"} assert b["revetlink"]["detached"] == {"140.00": True} assert b["extrawall"] == {"140.00": 1} assert set(b["fordadjust"]) == {"100.00"} p = out["payloadB"] assert set(p["revet"]) == {"100"} and set(p["revet"]["100"]) == {"outlet"} assert set(p["link"]) == {"140"} assert p["extra"] == {"140": {"outlet": 1}} assert p["ford"] == [100] def test_다시하기_뒤_값_같음(out) -> None: assert out["afterUndo2"] == {name: None for name in out["afterUndo2"]} assert out["afterRedo"] == out["afterB"] d100, d120, d140 = out["designsRedo"] assert d100["revet_adjust"] == {"outlet": {"x": 1, "d": None, "h": None, "m": None}} assert "inlet_structure" not in d100 assert d120["inlet_structure"] == "I" assert d140["revet_link_detached"] is True assert d140["extra_wall_counts"] == {"outlet": 1, "basin": 0} assert d100["ford_adjust"]["outlet"]["lateralM"] == 1 r = out["readsRedo"] assert r["outlet"]["x"] == 1 and r["inlet"]["x"] == 0 assert r["width100"] is None and r["ford140"] == 0