feat(M02): 구조물 조합 표 — 머리 이름 고침 = 나무 이름 바꾸기 · 단위 줄 숨김 · 열 폭 자동 · 마지막 분류 칸 강조 · 안내글 없앰 (PLAN 31-1)
- 표 부품 combo 선택(구조물 조합 표만): 단위 줄 · 옛 안내글 없음 · 열 폭 = 머리 이름 · 일위대가 키 · 도번 등 번호가 한 줄에 들게(저장 폭 안 씀 · 번호 줄 줄바꿈 없음) · 고른 열의 가장 깊은 이름 칸 강조(나무에서 고를 때도) · 방향키가 숨은 단위 줄을 안 밟음 - 머리 이름 칸 두 번 누르기 · F2 · Enter → headRenameEdit(가장 깊은 칸 = 항목 · 위 칸 = 폴더) → 나무 editFromTable(메뉴 이름 바꾸기와 같은 길 — 저장 물음 · 같은 이름 막음 안내 · 다시 그림) · 쓸 수 있는 층만 - 시험 test_m02_combo_table 3 · test_m02_combo_screen 머리 잠금 기대값 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmELpdXFDRZHhfbGuRhSmL
This commit is contained in:
@@ -93,7 +93,9 @@ def test_참조표는_열_머리를_못_고침():
|
||||
assert "else if (layer && editCols) editLayer(layer);" in sheet
|
||||
assert 'ro || opts.lockHead ? { hidden: "" }' in sheet
|
||||
render = _text(SHEET / "ui_template_sheet_render.ts")
|
||||
assert 'const heads = mode === "master" && !state.headLocked;' in render
|
||||
assert (
|
||||
'const heads = mode === "master" && (!state.headLocked || !!state.headEditable);' in render
|
||||
) # 31-1 머리 이름은 나무로 고침
|
||||
main = _text(M02 / "M02_MasterTemplete_UI_Main.ts")
|
||||
assert "struct ? comboView(doc) : doc" in main
|
||||
assert "getDoc: () => comboMerge(loaded, shown.getDoc())" in main
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
"""구조물 조합 표(PLAN 31-1) — 머리 이름 칸 고침 = 나무 이름 바꾸기 · 단위 줄 숨김 · 열 폭 자동 ·
|
||||
고른 열의 마지막 분류 칸 강조 · 옛 안내글 없음.
|
||||
|
||||
① `headRenameEdit`(Node) — 가장 깊은 칸이면 항목(열 id) · 위 칸이면 그 폴더 경로.
|
||||
② 표 부품 `combo` 선택 — 단위 줄 · 안내 글 없음 · 번호 글 폭 · 가장 깊은 머리 칸 ·
|
||||
머리 고침은 부른 쪽에.
|
||||
③ 잇기 — 상세(Main)가 쓸 수 있을 때만 넘기고 페이지가 나무 고침(`editFromTable`)으로 보냄.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
M02 = ROOT / "M02_MasterTemplete"
|
||||
SHEET = ROOT / "ui_template" / "sheet"
|
||||
|
||||
|
||||
def _text(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
@pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음")
|
||||
def test_머리_칸_고침은_나무_이름_바꾸기():
|
||||
src = _text(M02 / "M02_MasterTemplete_Structure.ts")
|
||||
part = re.search(r"^export function headRenameEdit[\s\S]*?^}", src, re.M)
|
||||
assert part, "headRenameEdit 를 못 찾음"
|
||||
script = (
|
||||
"interface StructureColumn { id: string; 머리: (string | null)[] }\n"
|
||||
"interface TreeEdit { op: string; 경로?: string[]; 이름?: string; 키?: string }\n"
|
||||
+ part.group(0).replace("export ", "")
|
||||
+ """
|
||||
const col = { id: "item3", 머리: ["옹벽", "콘크리트", "L형", null] };
|
||||
const flat = { id: "item9", 머리: ["대피소", null, null, null] };
|
||||
console.log(JSON.stringify([
|
||||
headRenameEdit(col, 0, "옹벽공"), headRenameEdit(col, 1, "철근"),
|
||||
headRenameEdit(col, 2, "L자"), headRenameEdit(col, 3, "L자"), headRenameEdit(flat, 0, "쉼터"),
|
||||
]));
|
||||
"""
|
||||
)
|
||||
result = subprocess.run(
|
||||
["node", "--experimental-strip-types", "--no-warnings",
|
||||
"--input-type=module-typescript", "-e", script],
|
||||
capture_output=True, text=True, encoding="utf-8", timeout=60,
|
||||
) # fmt: skip
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert json.loads(result.stdout) == [
|
||||
{"op": "rename", "경로": ["옹벽"], "이름": "옹벽공"}, # 맨 위 폴더
|
||||
{"op": "rename", "경로": ["옹벽", "콘크리트"], "이름": "철근"}, # 가운데 폴더
|
||||
{"op": "rename", "경로": ["옹벽", "콘크리트"], "키": "item3", "이름": "L자"}, # 항목
|
||||
{"op": "rename", "경로": ["옹벽", "콘크리트"], "키": "item3", "이름": "L자"}, # 빈 아래 칸
|
||||
{"op": "rename", "경로": [], "키": "item9", "이름": "쉼터"}, # 깊이 1 항목
|
||||
]
|
||||
|
||||
|
||||
def test_표_부품_combo_선택():
|
||||
sheet = _text(SHEET / "ui_template_sheet.ts")
|
||||
assert "combo?: { onHeadEdit?: (colId: string, level: number, name: string) => void };" in sheet
|
||||
assert '...(ro || opts.combo ? [] : [el("p", { className: "ui-sheet__hint"' in sheet
|
||||
assert (
|
||||
"filter((k) => !opts.combo || k !== KEY_UNIT)" in sheet
|
||||
) # 방향키가 숨은 단위 줄을 안 밟음
|
||||
assert 'head?.classList.add("is-head-picked")' in sheet
|
||||
assert "if (th && opts.combo?.onHeadEdit) editComboHead(th);" in sheet
|
||||
assert "if (opts.combo && sel.r === KEY_UNIT)" in sheet # F2 · Enter = 머리 이름 고침
|
||||
render = _text(SHEET / "ui_template_sheet_render.ts")
|
||||
assert "children: state.combo ? rows : [...rows, unit]" in render # 단위 줄 없음
|
||||
assert "if (state.combo) fitMeta(state, cols, mins);" in render
|
||||
assert "열너비: {}" in render # 저장 폭 안 씀 — 자동
|
||||
css = _text(SHEET / "ui_template_sheet.css")
|
||||
assert ".ui-sheet--combo .ui-sheet__meta td" in css and "th.is-head-picked" in css
|
||||
|
||||
|
||||
def test_머리_고침은_쓸_수_있는_층만_나무로():
|
||||
main = _text(M02 / "M02_MasterTemplete_UI_Main.ts")
|
||||
assert "readOnly || !extras.onHeadRename" in main
|
||||
page = _text(M02 / "M02_MasterTemplete_UI_Page.ts")
|
||||
assert "tree.editFromTable(headRenameEdit(col, level, name), col.id)" in page
|
||||
assert page.index("...(canEdit(layer, isAdmin)\n ? {\n onHeadRename") > 0
|
||||
tree = _text(M02 / "M02_MasterTemplete_TreePanel.ts")
|
||||
assert "if (opt.canEdit && (await ready())) await edit(body, colId);" in tree
|
||||
Reference in New Issue
Block a user