- createSectionFrame 횡단 칸 틀에 .ui-panel-form · 칸 · 라벨 · 단추 = 「구조물 배치」 기준 - B06 덧칠(칸 글자 · 색 · 오류 칸 접기) 걷음 · 줄 배치만 남김 - 시험 test_269_panel_form B06 항목 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QND7Co43B24zK2P937rdxt
125 lines
6.1 KiB
Python
125 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""269 좌측 패널 컨테이너 공용 양식 — 기준 = B05/B06 「구조물 배치」.
|
|
|
|
못박는 것
|
|
- 공용 양식 = ui_template 한 곳(`.ui-panel-form` · `.ui-panel-btn` · 카드 `createPanelCard`) ·
|
|
칸 높이 · 라벨 틈 토큰 = theme 한 곳 · 「구조물 배치」도 같은 토큰.
|
|
- B07 컨테이너 = 공용 카드 · 도면 단추 = `.ui-panel-btn` · 페이지 덧칠(크기 · 글자 · 바탕) 없음.
|
|
- B06 컨테이너(횡단 보기 설정 · 표준 횡단면 설정) = 칸 틀 `createSectionFrame` 이 공용 양식을 붙임 ·
|
|
단추 · 입력칸 = 공용 함수(createButton · createInputField · createSelectField) · B06 덧칠 없음.
|
|
"""
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def _read(rel: str) -> str:
|
|
return (ROOT / rel).read_text(encoding="utf-8")
|
|
|
|
|
|
THEME = _read("ui_template/ui_template_theme.css")
|
|
OVERLAY = _read("ui_template/ui_template_overlay.css")
|
|
COLLAPSIBLE = _read("ui_template/ui_template_collapsible.ts")
|
|
B05_STRUCT_CSS = _read("B05_Profile/B05_Profile_UI_Style_Structures.css")
|
|
B07_CSS = _read("B07_DesignDetail/B07_DesignDetail_UI_Style.css")
|
|
B07_PANELS = _read("B07_DesignDetail/B07_DesignDetail_UI_Panels.ts")
|
|
B07_PLAN = _read("B07_DesignDetail/B07_DesignDetail_UI_PlanKinds.ts")
|
|
DESIGN_PANEL = _read("A00_Common/design/design_panel.ts")
|
|
B06_CSS = _read("B06_Section/B06_Section_UI_Style.css")
|
|
B06_PANEL = _read("B06_Section/B06_Section_UI_Page_Panel.ts")
|
|
B06_STD = _read("B06_Section/B06_Section_UI_Standard_Panel.ts")
|
|
|
|
|
|
def _block(css: str, selector: str) -> str:
|
|
m = re.search(r"(?:^|\n)" + re.escape(selector) + r"\s*\{([^}]*)\}", css)
|
|
assert m, selector
|
|
return m.group(1)
|
|
|
|
|
|
def test_공용_양식_토큰은_theme_한_곳_구조물_배치도_같은_토큰():
|
|
assert "--panel-control-h: 26px;" in THEME
|
|
assert "--panel-label-gap: 2px;" in THEME
|
|
assert "--b05-control-h: var(--panel-control-h);" in B05_STRUCT_CSS
|
|
assert "--b05-label-gap: var(--panel-label-gap);" in B05_STRUCT_CSS
|
|
|
|
|
|
def test_공용_양식_칸_라벨_단추_규칙():
|
|
field = _block(
|
|
OVERLAY,
|
|
'.ui-panel-form input:not([type="checkbox"], [type="radio"], [type="range"]),\n'
|
|
".ui-panel-form select",
|
|
)
|
|
assert "height: var(--panel-control-h);" in field
|
|
assert "padding: 0 6px;" in field
|
|
assert "font-size: var(--text-caption);" in field
|
|
label = _block(OVERLAY, ".ui-panel-form .ui-field,\n.ui-panel-form .b05-route__field")
|
|
assert "gap: var(--panel-label-gap);" in label
|
|
assert "display: none;" in _block(OVERLAY, ".ui-panel-form .ui-field__error:not(.is-visible)")
|
|
button = _block(OVERLAY, ".ui-panel-form .ui-btn:not(.ui-help-btn)")
|
|
# 「구조물 배치」 단추(b05-route__irregular-btn)와 같은 크기
|
|
assert "padding: var(--spacing-8);" in button
|
|
assert "font-size: var(--text-caption);" in button
|
|
assert "border-radius: var(--radius-inputs);" in button
|
|
raw = _block(OVERLAY, ":where(.ui-panel-btn)")
|
|
for decl in (
|
|
"padding: var(--spacing-8);",
|
|
"border-radius: var(--radius-inputs);",
|
|
"background: var(--color-surface);",
|
|
"font-size: var(--text-caption);",
|
|
):
|
|
assert decl in raw, decl
|
|
# 아래 단추 묶음은 컨테이너 밖 — 공용 양식이 `.ui-sidebar-actions` 를 겨누지 않음
|
|
form_rules = OVERLAY[OVERLAY.index("좌측 패널 컨테이너 공용 양식(269)") :]
|
|
form_rules = form_rules[: form_rules.index("/* 카드 안에 다시 카드")]
|
|
assert "ui-sidebar-actions {" not in form_rules and "ui-sidebar-actions ." not in form_rules
|
|
|
|
|
|
def test_공용_카드_함수():
|
|
assert "export function createPanelCard(" in COLLAPSIBLE
|
|
assert "ui-collapsible ui-sidebar-section ui-sidebar-card ui-panel-form" in COLLAPSIBLE
|
|
|
|
|
|
def test_B07_컨테이너_공용_카드_도면_단추_공용_꼴():
|
|
assert "createPanelCard(`${group.label} ${items.length}`)" in B07_PANELS
|
|
assert "createPanelCard(`평면도 ${items.length}`)" in B07_PLAN
|
|
for src in (B07_PANELS, B07_PLAN):
|
|
assert "ui-collapsible ui-sidebar-section" not in src # 손으로 짠 카드 없음
|
|
assert B07_PANELS.count('"b07-drawing-button ui-panel-btn"') == 2
|
|
assert '"ui-panel-btn b07-plan-manage-open"' in B07_PLAN
|
|
|
|
|
|
def test_B07_페이지_덧칠_없음():
|
|
assert not re.search(r"(?:^|\n)\.b07-drawing-group\s*\{", B07_CSS)
|
|
assert ".b07-drawing-group h3 {" not in B07_CSS
|
|
assert ".b07-plan-manage-open {" not in B07_CSS
|
|
button = _block(B07_CSS, ".b07-drawing-button")
|
|
for prop in ("min-height", "padding", "border-radius", "background", "font-size"):
|
|
assert not re.search(r"(?:^|\s)" + prop + r"\s*:", button), prop
|
|
assert "font-size" not in _block(B07_CSS, ".b07-drawing-button__name")
|
|
assert ".b07-cross-layout .ui-btn" not in B07_CSS
|
|
assert ".b07-cross-layout .ui-field__error" not in B07_CSS
|
|
|
|
|
|
def test_B06_컨테이너_공용_양식():
|
|
frame = DESIGN_PANEL[DESIGN_PANEL.index("export function createSectionFrame(") :]
|
|
frame = frame[: frame.index("\n}\n")]
|
|
cross = frame[frame.index("b06-profile__group ui-collapsible") :]
|
|
assert "ui-panel-form" in cross.splitlines()[0]
|
|
for src in (B06_PANEL, B06_STD):
|
|
assert "createSectionFrame(" in src or "createButton(" in src
|
|
assert "<button" not in src and 'createElement("button")' not in src
|
|
assert 'createElement("input")' not in src and 'createElement("select")' not in src
|
|
assert "createInputField(" in B06_PANEL and "createButton(" in B06_PANEL
|
|
# 덧칠 없음 — 칸 글자 · 오류 칸 접기는 공용 양식 몫
|
|
group = _block(B06_CSS, ".b06-profile__group")
|
|
assert "font-size" not in group and not re.search(r"(?:^|\s)color\s*:", group)
|
|
assert ".b06-profile__field-row .ui-field__error" not in B06_CSS
|
|
for sel in (".ui-btn {", ".ui-input {", ".ui-select {"):
|
|
for line in B06_CSS.splitlines():
|
|
if line.endswith(sel) and line.startswith(".b06-profile"):
|
|
rule = _block(B06_CSS, line[:-2])
|
|
for prop in ("height", "padding", "font-size"):
|
|
assert not re.search(r"(?:^|\s)" + prop + r"\s*:", rule), (line, prop)
|