- 관 목록 받기(followPipeList)가 「고른 관 사라짐」으로 먼저 고름을 풀어 폼 다시 엶이 안 돎 → 사라진 관 하나 · 새로 선 관 하나면 그 관으로 고름을 옮긴 뒤 목록을 받음 · 폼 다시 엶 · 알약 고름도 따라감 - 시험 test_472_5_shop_owner 배선 단언 글을 새 줄로(옛 줄 글 그대로 단언 · 동작 같음 + 따라감) - 위키 rules · operations_b05 줄(관 자리 읽기 한 벌 · 관 지움 ↶ 정본 설계 · 폼 따라감) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
129 lines
5.0 KiB
Python
129 lines
5.0 KiB
Python
"""PLAN 472-5 5-A (요구 273) — 관 · 구조물 값 주인 하나(설계 가게) · 사본 갈림 막음.
|
|
|
|
못박는 것
|
|
- 되돌리기 · 다시하기(세션 직접 되씀)가 가게 듣는 쪽을 되돌린 값으로 한 번씩 부름(5-C 훅 · 묶음과
|
|
안 겹침) — 옛 코드는 안 불러 종단 목록 · 횡단 판 · 배수 편집기가 옛 값을 쥐고 다음 조작이
|
|
되돌림을 덮었음(옛 코드 실패).
|
|
- 배수 편집기 받기 — 제 쓰기 메아리는 안 받음 · 남이 고친 옵션 · 차례도 받음 · 고른 관(id) 유지.
|
|
- 배선 — 종단 보기 = 관(숨어도) · 구조물(보일 때) 구독 · 횡단 보기 = 남 고침(옵션만도) 다시 실음 ·
|
|
횡단 판은 쓰기 전에 제 값을 적음(메아리 가름).
|
|
|
|
./venv/Scripts/python.exe -m pytest resources/tester/test_472_5_shop_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="프론트엔드 의존성 미설치",
|
|
)
|
|
|
|
|
|
def _read(*parts: str) -> str:
|
|
return (ROOT.joinpath(*parts)).read_text(encoding="utf-8")
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def out(tmp_path_factory) -> dict:
|
|
work = tmp_path_factory.mktemp("s4725")
|
|
subprocess.run( # noqa: S603 — 고정 실행 파일
|
|
[
|
|
"node",
|
|
str(ROOT / "config" / "node_modules" / "vite" / "bin" / "vite.js"),
|
|
"build",
|
|
"--configLoader",
|
|
"runner",
|
|
"--ssr",
|
|
"../resources/tester/helper_472_5_shop_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_5_shop_entry.js", bundle)
|
|
proc = subprocess.run( # noqa: S603
|
|
["node", str(HERE / "helper_472_5_shop.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_되돌리기가_가게_듣는_쪽을_부름(out) -> None:
|
|
assert [s["structure_id"] for s in out["afterUndo"]["structures"]] == ["a"]
|
|
assert out["afterUndo"]["pipes"][0]["options"] == {"diameter_mm": 800}
|
|
assert [s["structure_id"] for s in out["afterRedo"]["structures"]] == ["a", "b"]
|
|
assert out["afterRedo"]["pipes"][0]["options"] == {"diameter_mm": 1000}
|
|
|
|
|
|
def test_되돌리기_알림은_한_번씩(out) -> None:
|
|
"""겹침 정리 — 관 · 구조물 = 가게 알림 한 번 · 추가 측점 = 자기 훅 · 묶음 = 출처마다 한 번."""
|
|
assert out["counts"] == {
|
|
"structures": 1,
|
|
"pipes": 1,
|
|
"plusStations": 1,
|
|
"fed": ["pipe", "plus", "structure"],
|
|
}
|
|
|
|
|
|
def test_배수_편집기_남_고침만_받음(out) -> None:
|
|
assert out["echo"] is False
|
|
assert out["adopted"] is True
|
|
assert out["options"] == {"diameter_mm": 1200}
|
|
assert out["picked"] == "k1"
|
|
|
|
|
|
def test_배선() -> None:
|
|
profile = _read("A00_Common", "design", "design_view_profile.ts")
|
|
assert (
|
|
'designStore.subscribe("pipes", (next) => next && profilePanel.drainage.adoptPipes(next))'
|
|
in profile
|
|
)
|
|
assert (
|
|
'designStore.subscribe("structures", (next) => host.visible() && '
|
|
"bridge.takeStructures(next))" in profile
|
|
)
|
|
cross = _read("A00_Common", "design", "design_view_cross.ts")
|
|
assert "structuresPanel.foreign() && reloadPanel()" in cross
|
|
assert (
|
|
'shop.subscribe("pipes", onShop)' in cross
|
|
and 'shop.subscribe("structures", onShop)' in cross
|
|
)
|
|
panel = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts")
|
|
assert panel.index("seen.pipes = JSON.stringify(next);") < panel.index(
|
|
"writePendingPipes(deps.projectId, next);"
|
|
)
|
|
assert panel.index("seen.structures = JSON.stringify(structures);") < panel.index(
|
|
"writePendingStructures(deps.projectId, structures);"
|
|
)
|
|
# 열린 관 폼 — 밖에서 바뀐 값(되돌리기 · 다른 보기)으로 다시 엶(옛 칸 값 되쓰던 흠)
|
|
form = _read("B05_Profile", "B05_Profile_UI_Structures_Panel.ts")
|
|
assert "if (at === null || applyingLive || tempPipeChainage !== null) return;" in form
|
|
assert "if (now && JSON.stringify(now) !== JSON.stringify(was)) loadPipeForm(now);" in form
|
|
# 고른 관이 그 자리를 떠남(폼 옮김 ↶ ↷) = 새로 선 관 하나로 따라감 — 목록 받기(고름 풂) 앞(472 덧)
|
|
assert form.index("if (moved) selectedPipeChainage = moved.chainage_m;") < form.index(
|
|
"followPipeList(panelContext, pipeFacilities);"
|
|
)
|
|
history = _read("B05_Profile", "B05_Profile_UI_Profile_History.ts")
|
|
assert "announceDesignStore(projectId);" in history
|