Files
Aislo/resources/tester/test_m02_combo_screen.py
T
eomsangdonandClaude Opus 5.5 b981911755 feat(M02): 항목 추가 창 = 종류 + 이름 + 일위대가 · 카드 넷 2×2 · 표 접기 (PLAN 31-2)
- 항목 추가(나무 「항목 추가」 · 「새 항목」) — 구조물 종류(있는 것 고름 · 새 이름 · 폴더를 골라 두었으면 그 안) + 이름 + 일위대가(세 층 조합 고르기 창 · 찾기 AND · 비워도 됨) · 단위 칸 없앰 · 빈 칸 안내 · 서버 add-item 이 일위대가 받음
- 일위대가 고르기 창을 pickCombo 로 내보내 표 칸 고르기와 같이 씀
- 카드 넷(도면 정보 · 면적산출 · 재료산출 · 선택 입력) 2행 2열 · 높이 360px · 넘치면 카드 안 스크롤 · 상세 칸 전체 스크롤(좁으면 1열)
- 「구조물 조합」 제목을 누르면 표 접힘 · 펴짐
- 시험 — 항목 추가 서버 · 창 · 격자 · 접기 · 옛 단위 필수 시험을 31 정함으로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:19:11 +09:00

126 lines
5.4 KiB
Python

"""관리 화면 「구조물 조합」(PLAN 26-7a~d) — 이름 · 숨김(비고 · 전구간 · 합계) · 참조표 잠금 ·
나무 자리.
① `comboView` · `comboMerge`(Node) — 보일 문서에서 NO · 측점 · 비고 열 · 줄 · 합계 줄을
빼고(30-7), [저장] 때 저장본 것을 다시 끼움(열 차례 = 저장본 · 보인 고침은 받음).
② 표 부품 `lockHead` — 열 더하기 · 지우기 · 머리 · 층 이름 고치기 없음(단위 · 조회 후 선택은
그대로).
③ 나무는 좌측 패널 「구조물 조합」 줄 아래(층 단추 + 나무 · PLAN 29-2) · 상세 위쪽 찾기 칸은
「구조물 조합」일 때만.
"""
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"^const HIDDEN_COLUMNS[\s\S]*?^export function comboMerge[\s\S]*?^}", src, re.M
)
assert part, "comboView · comboMerge 를 못 찾음"
script = (
"interface StructureColumn { id: string; 머리: (string | null)[]; 꼴?: string | null;"
" 단위?: string }\n"
+ part.group(0).replace("export ", "")
+ """
const stored = {
열: [{ id: "no", 머리: ["NO"] }, { id: "sta", 머리: ["측점"] },
{ id: "a", 머리: ["가"], 꼴: "수" },
{ id: "b", 머리: ["나"], 꼴: "수" }, { id: "memo", 머리: ["비고"] }],
줄: [{ id: "all", 값: { memo: "x", sta: "전구간" } }], 합계줄: [{ id: "sum" }], 변수: { k: 1 },
보기: { 틀고정: { 열: 2 }, 열너비: { no: 40, a: 72 } },
};
const view = comboView(stored);
const edited = structuredClone(view);
edited.열[1].단위 = "m";
edited.보기.열너비.a = 90;
const saved = comboMerge(stored, edited);
console.log(JSON.stringify([
view.열.map((c) => c.id), view.줄, view.합계줄, view.보기.틀고정.열, stored.열.length,
stored.보기.틀고정.열, saved.열.map((c) => c.id), saved.열[3].단위, saved.줄, saved.합계줄,
saved.변수, saved.보기,
]));
"""
)
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) == [
["a", "b"], # NO · 측점 · 비고 숨김(30-7)
[],
[],
0, # 틀고정 2 열(NO · 측점)이 숨어 0
5, # 저장본은 안 바뀜
2,
["no", "sta", "a", "b", "memo"], # [저장] 때 저장본 차례 · 숨긴 열 되끼움
"m",
[{"id": "all", "값": {"memo": "x", "sta": "전구간"}}],
[{"id": "sum"}],
{"k": 1},
{
"틀고정": {"열": 2},
"열너비": {"no": 40, "a": 90},
}, # 틀고정은 저장본 · 열너비 고침은 받음
]
def test_참조표는_열_머리를_못_고침():
sheet = _text(SHEET / "ui_template_sheet.ts")
assert 'const editCols = opts.mode === "master" && !ro && !opts.lockHead;' in sheet
assert "if (editCols) toolbar.append(colDelete);" in sheet
assert "if (editCols) syncLevels(!!col);" in sheet
assert "if (th && editCols) editHead(th);" in sheet
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
main = _text(M02 / "M02_MasterTemplete_UI_Main.ts")
assert "struct ? comboView(doc) : doc" in main
assert "getDoc: () => comboMerge(loaded, shown.getDoc())" in main
def test_나무는_좌측_패널_찾기_칸은_상세_위쪽():
side = _text(M02 / "M02_MasterTemplete_UI_Side.ts")
assert "tree?: HTMLElement[];" in side and "children: opt.tree ?? []" in side
assert 'info.이름 === STRUCTURE_TABLE ? L("M02_KindTable")' in side # 좌측 줄 이름
page = _text(M02 / "M02_MasterTemplete_UI_Page.ts")
assert "createTreePanel({" in page and "tree.select(column)" in page
assert (
'layerBar("구조물조합", tree.add, () => void main.openTable(layer)),' in page
and "search: tree.search," in page
)
main = _text(M02 / "M02_MasterTemplete_UI_Main.ts")
assert 'at.kind === "table" && at.name === STRUCTURE_TABLE && at.layer !== "project"' in main
assert 'isCombo(next) ? L("M02_KindTable")' in main # 상세 제목
assert main.count("showAside();") == 3 # 열 때 · 양식 밖 화면 · 처음
assert "if (extras.search) extras.search.hidden = !combo;" in main
locale = _text(ROOT / "ui_template" / "ui_template_locale_m2.ts")
assert 'M02_KindTable: ["구조물 조합"' in locale
assert ".m02-shell" not in _text(
M02 / "M02_MasterTemplete_UI_Style.css"
) # 상세 왼쪽 나무 자리 없앰
tree = _text(M02 / "M02_MasterTemplete_TreePanel.ts")
assert (
'error instanceof StaleError && error.message === "HTTP 409"' in tree
) # 같은 이름 = 까닭 글