- 「일위대가 라이브러리」 · 「구조물 조합」 줄 아래 층 단추 셋(마스터 · 회사 · 개인 · 권한 없으면 「읽기」) → 고른 층의 나무를 좌측 패널에 · 상세는 표 · 편집만 - 찾기 칸은 상세 위쪽(구조물 조합일 때 · 일위대가 화면 맨 위) - 회사 → 사람 펼침 없앰 · 「사람 고르기」 select(같은 줄 · 회사 관리자 · 시스템 관리자) → 해시 owner - 시스템 관리자 볼 회사 = 해시 company · sessionStorage aislo.adminCompany · 자기 회사(viewCompany) - 공용 나무(ui_template_tree) — 들여쓰기 안내선 · 폴더 · 항목 아이콘 · 폴더 굵게(M01 · 고르기 모달도 같이) - 시험 — combo_screen · labor_tree · layer_screen 새 배치 · viewCompany Node 시험 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
113 lines
4.8 KiB
Python
113 lines
4.8 KiB
Python
"""관리 화면 「구조물 조합」(PLAN 26-7a~d) — 이름 · 숨김(비고 · 전구간 · 합계) · 참조표 잠금 ·
|
|
나무 자리.
|
|
|
|
① `comboView` · `comboMerge`(Node) — 보일 문서에서 비고 열 · 줄 · 합계 줄을 빼고, [저장] 때
|
|
저장본 것을 다시 끼움(열 차례 = 저장본 · 보인 고침은 받음).
|
|
② 표 부품 `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: "a", 머리: ["가"], 꼴: "수" },
|
|
{ id: "b", 머리: ["나"], 꼴: "수" }, { id: "memo", 머리: ["비고"] }],
|
|
줄: [{ id: "all", 값: { memo: "x" } }], 합계줄: [{ id: "sum" }], 변수: { k: 1 },
|
|
};
|
|
const view = comboView(stored);
|
|
const edited = structuredClone(view);
|
|
edited.열[2].단위 = "m";
|
|
const saved = comboMerge(stored, edited);
|
|
console.log(JSON.stringify([
|
|
view.열.map((c) => c.id), view.줄, view.합계줄, stored.열.length,
|
|
saved.열.map((c) => c.id), saved.열[2].단위, 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) == [
|
|
["no", "a", "b"],
|
|
[],
|
|
[],
|
|
4, # 저장본은 안 바뀜
|
|
["no", "a", "b", "memo"],
|
|
"m",
|
|
[{"id": "all", "값": {"memo": "x"}}],
|
|
[{"id": "sum"}],
|
|
{"k": 1},
|
|
]
|
|
|
|
|
|
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 "...(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 'tree: [layerBar("구조물조합"), tree.root],' 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 = !isCombo(sel);" 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
|
|
) # 같은 이름 = 까닭 글
|