"""다단 흙막이 ↔ 흙막이 컨테이너 (PLAN 54-10). 짝: `B06_Section/B06_Section_UI_Page_Pipe_Options.ts`(컨테이너 값 → 다단 조정값 · 단별 구간값) · `A00_Common/design/design_structure_form.ts`(개수보다 많은 컨테이너는 가리기만 · 값은 남김) · `B06_Section/B06_Section_UI_Adjust_Dock.ts`(다단 벽 고르기 → 그 단의 흙막이 컨테이너). 실제 TS 를 `helper_54_10_soil_tiers.cjs` 가 Node 로 돌린다. """ from __future__ import annotations import json import os import subprocess from pathlib import Path import pytest HERE = os.path.dirname(__file__) ROOT = Path(HERE).resolve().parents[1] @pytest.fixture(scope="module") def out() -> dict: proc = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", os.path.join(HERE, "helper_54_10_soil_tiers.cjs")], capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def extras(updates: list[dict]) -> list[dict]: return [u for u in updates if u["role"].startswith("extra")] def test_컨테이너_형태_높이가_그_단_조정값으로(out) -> None: assert extras(out["filled"]["updates"]) == [ {"role": "extra0", "h": 1.8, "m": "콘크리트"}, {"role": "extra1", "h": 2.5, "m": "돌쌓기(메)"}, # 형태별 높이 한도 없음(54-42) ] def test_지형이_못_세운_단은_그림에_안_감(out) -> None: roles = {u["role"] for u in out["filled"]["updates"]} assert "extra2" not in roles def test_높이는_입력_그대로_0_이하만_하한으로_폼에_되돌림(out) -> None: """54-42 형태별 한도 삭제 · 54-51 높이 제약 풀기 — 하한은 그림이 서는 0.1 하나 · 토스트 없음.""" assert out["filled"]["overrides"] == [] assert extras(out["floor"]["updates"]) == [{"role": "extra0", "h": 0.1, "m": "콘크리트"}] assert out["floor"]["overrides"] == [{"soil_add_1_height": 0.1}] assert out["toasts"] == [] def test_길이_전_후는_단별_구간값(out) -> None: assert out["filled"]["tiers"] == [{"key": "extra0", "lengthM": 8, "beforeM": 3, "afterM": 5}] def test_같은_값은_다시_그리지_않음(out) -> None: assert extras(out["same"]["updates"]) == [] assert out["same"]["tiers"] == [] def test_비운_칸은_자동_구간값은_그대로(out) -> None: assert extras(out["cleared"]["updates"]) == [ {"role": "extra0", "h": None, "m": None}, {"role": "extra1", "h": None, "m": None}, ] assert out["cleared"]["tiers"] == [] def test_독립_기슭막이는_다단을_안_만짐(out) -> None: assert extras(out["hidden"]) == [] def test_개수보다_많은_컨테이너는_가리고_값은_남김(out) -> None: form = out["form"] kept = ["soil_add_1_form", "soil_add_2_form", "soil_add_2_height"] assert (form["shown1"], form["keys1"]) == (1, kept) assert (form["shown0"], form["keys0"]) == (0, kept) # 단 수 0 저장에도 남음 assert form["shown3"] == 3 and form["keys3"][:3] == kept def test_다단_벽_고르기는_흙막이_컨테이너로() -> None: dock = (ROOT / "B06_Section" / "B06_Section_UI_Adjust_Dock.ts").read_text(encoding="utf-8") assert 'fieldset[data-spec-container="soil_add"]' in dock assert "panelRoot.dataset.extraIndex" in dock # 세월교 · 박스 유출 다단도 그 상자로(90-1 · 유출 자리 = 날개벽 칸) assert "ownerSlot === sideSlots.outlet || ownerSlot === sideSlots.wingOutlet" in dock panel = (ROOT / "B06_Section" / "B06_Section_UI_Cross_Structure_Panel.ts").read_text( encoding="utf-8" ) assert "root.dataset.extraIndex" in panel