Files
Aislo/resources/tester/test_313_clear_all.py
T
eomsangdonandClaude Opus 5.5 f3c8436551 fix(b05,b06): [구조물 전체 삭제] 단추 높이 = 위 구조물 단추와 같게 — 공용 --panel-control-h 규칙에 목록 단추 보탬 (313-2)
- 위 [추가] · [삭제] · [리셋]만 205-1 높이 규칙(--b05-control-h)을 받고 목록 맨 아래 단추는 빠져 34px · 위 26px
- 같은 규칙 · 같은 변수에 `.b05-route__irregular-clear` 보탬(px 안 박음) · 위험 색 그대로
- 시험: test_313_clear_all 실제 브라우저 밝음 · 어두움 높이 같음(옛 26 · 34)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
2026-10-13 18:50:11 +09:00

143 lines
6.1 KiB
Python

"""313 B05 · B06 좌측 구조물 목록 맨 아래 [구조물 전체 삭제] — 목록 있음 · 없음 · 누름 뒤 0 · 취소 · B05 · B06.
목록 그리기 · 입력 배선은 진짜 TS 를 Node 로 돌려 보고(helper_313), B05 · B06 이 같은 목록 한 벌에
각자 관 빼기 길을 거는지는 배선 글로 본다.
"""
import json
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
HELPER = Path(__file__).with_name("helper_313_clear_all.cjs")
def _read(*parts: str) -> str:
return ROOT.joinpath(*parts).read_text(encoding="utf-8")
@pytest.fixture(scope="module")
def out() -> dict:
run = subprocess.run(
["node", str(HELPER)], capture_output=True, text=True, encoding="utf-8", cwd=ROOT
)
assert run.returncode == 0, run.stderr
return json.loads(run.stdout)
def test_목록_있음_맨아래_단추(out):
filled = out["listCases"]["filled"]
assert filled["rows"] == 3 # 구조물 1 + 관 1 + 단추 줄
assert filled["lastClass"] == "b05-route__irregular-clear"
assert filled["button"] == {
"text": "구조물 전체 삭제",
"className": "b05-route__irregular-btn is-danger", # 좌측 패널 위험 단추 꼴
"type": "button",
}
assert filled["cleared"] == 1
def test_목록_없음_단추_숨김(out):
empty = out["listCases"]["empty"]
assert empty == {
"rows": 1,
"lastClass": "b05-route__irregular-empty",
"button": None,
"cleared": 0,
}
# 단추를 안 건 목록(다른 쓰임)은 그대로
assert out["listCases"]["noHandler"]["button"] is None
def test_누름_확인_뒤_0(out):
done = out["confirmed"]
assert done["confirms"] == [["구조물 4개를 모두 지울까요?", "모두 삭제"]]
assert done["left"] == 0
# 하나씩 지우기와 같은 길 — 관은 관 빼기(자동 · 손 배치 모두) · 구조물은 비우고 알림 한 번
assert done["calls"] == {"reset": 1, "release": 1, "removed": [80, 160.37], "emit": 1}
pipes_only = out["pipesOnly"]
assert pipes_only["left"] == 0 and pipes_only["calls"]["emit"] == 0
def test_취소면_그대로(out):
cancelled = out["cancelled"]
assert cancelled["confirms"] == [["구조물 3개를 모두 지울까요?", "모두 삭제"]]
assert cancelled["left"] == 3
assert cancelled["calls"] == {"reset": 0, "release": 0, "removed": [], "emit": 0}
assert out["nothing"]["confirms"] == [] # 빈 목록 = 확인창도 안 뜸
def test_B05_B06_같은_목록_각자_관빼기():
panel = _read("B05_Profile", "B05_Profile_UI_Structures_Panel.ts")
assert "onClearAll: () => void clearAll()," in panel
assert "const { startNew, clearAll } = bindStructuresEvents(panelContext);" in panel
assert len(panel.splitlines()) <= 700
# 좌측 「구조물 배치」 폼 · 목록 = 두 보기 한 벌 · 관 빼기 알림은 지금 보기로
shared = _read("A00_Common", "design", "design_shared.ts")
assert "onPipeRemove: (chainageM) => on().onPipeRemove?.(chainageM)," in shared
b06 = _read("B06_Section", "B06_Section_UI_Page_Structures_Panel.ts")
assert "onPipeRemove: (chainageM) => removePipeAt(chainageM)," in b06 # B06 = 관 초안 캐시
b05 = _read("A00_Common", "design", "design_view_profile.ts")
assert "onPipeFacilityRemove: (chainage) => profilePanel.drainage.removePipe(chainage)," in b05
# 공용 확인창 · 저장 길(초안 → [저장])은 안 고침
events = _read("B05_Profile", "B05_Profile_UI_Structures_Panel_Events.ts")
assert 'import { showConfirmDialog } from "@ui/ui_template_elements";' in events
assert "ctx.emit();" in events
def test_CSS_단추_줄():
css = _read("B05_Profile", "B05_Profile_UI_Style.css")
assert ".b05-route__irregular-clear {" in css
assert ".b05-route__irregular-clear .b05-route__irregular-btn {" in css
# ── 313-2 실제 브라우저(정적 쪽 · 서버 불필요) — 위 [삭제] 단추와 같은 높이 · 같은 위험 색 ──
MARKUP = (
"<div style='width:320px'>"
"<section class='b05-route__panel-section b05-structure-section ui-collapsible"
" ui-sidebar-section ui-panel-form'><div class='b05-route__irregular-actions'>"
"<button class='b05-route__irregular-btn is-primary'>추가</button>"
"<button class='b05-route__irregular-btn is-danger' id='top'>삭제</button>"
"<button class='b05-route__irregular-btn'>리셋</button></div></section>"
"<div class='b05-route__dock ui-sidebar-actions'><ul class='b05-route__irregular-list'>"
"<li class='b05-route__irregular-item'><strong>NO.1</strong><span>배수관</span></li>"
"<li class='b05-route__irregular-clear'><button type='button'"
" class='b05-route__irregular-btn is-danger' id='clear'>구조물 전체 삭제</button></li>"
"</ul></div></div>"
)
@pytest.mark.parametrize("theme", ["light", "dark"])
def test_단추_높이_위_삭제와_같음(theme):
from playwright.sync_api import sync_playwright
css = "".join(
p.read_text("utf-8")
for folder in ("ui_template", "B05_Profile", "B06_Section")
for p in sorted((ROOT / folder).glob("*.css"))
)
html = (
f"<!doctype html><html data-theme='{theme}'><head><style>{css}</style></head>"
f"<body>{MARKUP}</body></html>"
)
with sync_playwright() as p:
browser = p.chromium.launch(channel="msedge", headless=True)
page = browser.new_page()
page.set_content(html)
out = page.evaluate(
"""() => ['top', 'clear'].map((id) => {
const el = document.getElementById(id);
return [el.getBoundingClientRect().height, getComputedStyle(el).color];
})"""
)
browser.close()
(top_h, top_color), (clear_h, clear_color) = out
assert top_h == clear_h, out # 두 단추 높이 px 같음(공용 --panel-control-h)
assert clear_color == top_color, out # 위험 색 꼴 그대로
css_rule = _read("B05_Profile", "B05_Profile_UI_Style_Structures.css")
assert ".b05-route__irregular-clear > button {" in css_rule
assert "px" not in css_rule.split(".b05-route__irregular-clear {")[-1].split("}")[0]