Files
Aislo/resources/tester/test_m02_card_sheet_edit.py
T
eomsangdonandClaude Opus 5.5 79e4bba1bb merge(M02): origin/dev(39 통합) 받음 — G1 · G2 지움과 부딪힌 곳 풂
- 남의 새 줄(labor · 일위대가번 SU · 실무문서 · 「전체 항목」 · 수평선 · 알약 켬끔 · 복사해 가져오기)은 살리고 material · 자재조합 · 재료번 · matset 줄만 뺌
- dev 쪽 새 시험(test_m02_item_labor · test_m02_card_sheet_edit)의 재료산출 · 자재조합 자리 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK
2026-10-04 19:22:22 +09:00

103 lines
5.3 KiB
Python

"""면적산출 · 재료산출 카드 미리보기 수정(PLAN 31-3) — 화면 조작은 ORCA.
· 스프레드시트 `preview` = 도구 모음 · 오른쪽 클릭 메뉴 없음 · 수식 입력 줄 · 칸 고침
(다른 화면 그대로)
· 카드 = `sheetEdit` 가 있을 때만 고침(M02 구조물 조합) · 고르기 모달은 보기만 그대로
· 알약 = 전체 편집기와 같은 부품 · 카드 [저장] = 같은 저장 길 · 저장 안 한 고침 물음
"""
from __future__ import annotations
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
M02 = ROOT / "M02_MasterTemplete"
def _text(path: Path) -> str:
return path.read_text(encoding="utf-8")
def test_스프레드시트_미리보기_수정_옵션():
src = _text(ROOT / "A00_Common" / "spreadsheet" / "spreadsheet.ts")
assert "preview?: boolean;" in src
assert "const bare = readOnly || !!opts.preview;" in src
assert "bare ? null : mountToolbar(ctx)" in src and "bare ? null : attachMenu(ctx)" in src
# 편집 · 수식 입력 줄은 readOnly 만 막음 — preview 는 고칠 수 있음
assert "const readOnly = !!opts.readOnly;" in src
assert re.search(r"for \(const node of \[toolbar\?\.root, ed\.bar, grid\.root", src)
def test_카드는_sheetEdit_있을_때만_고침():
cards = _text(M02 / "M02_MasterTemplete_ItemCards.ts")
assert "sheetEdit?: SheetEditOptions;" in cards
assert (
"if (opts.sheetEdit?.can()) return await paintEditable(c, mine, createSpreadsheet);"
in cards
)
body = cards.split("const paintEditable")[1].split("const paintSheet")[0]
assert "preview: true," in body and "links," in body
assert "c.host.append(extra.below)" in body # 재료산출 = 자재 조합 판
# 보기만 길 그대로(고르기 모달)
assert "createSpreadsheet(c.host, c.doc, { readOnly: true, tabs: false })" in cards
detail = _text(ROOT / "ui_template" / "ui_template_item_picker_detail.ts")
assert "sheetEdit" not in detail
def test_카드_저장은_읽은_문서에_시트를_덮음():
cards = _text(M02 / "M02_MasterTemplete_ItemCards.ts")
save = cards.split("async function saveSheet")[1].split("\n }\n")[0]
assert "...(c.doc as unknown as Record<string, unknown>), ...c.handle.getDoc()" in save
assert "c.version = await opts.sheetEdit.save(c.kind, at, next, c.version);" in save
assert 'c.version = String((got.value as { 판?: string | null }).판 ?? "");' in cards
struct = _text(M02 / "M02_MasterTemplete_Structure.ts")
assert "saveTemplate(getActiveLayer(), kind, at, null, version, doc)" in struct
def test_알약은_전체_편집기와_같은_부품():
struct = _text(M02 / "M02_MasterTemplete_Structure.ts")
links = struct.split("async function cardLinks")[1].split("export interface")[0]
assert "pillsFor(kind, ctl.column)" in links
assert "buildMaterialPanel" not in struct # 자재 조합 판은 없앰
assert "can: () => opts.isAdmin" in struct
def test_저장_안_한_카드_고침_물음():
struct = _text(M02 / "M02_MasterTemplete_Structure.ts")
show = struct.split("const show = ")[1].split("const pickPrice")[0]
assert "cards.dirty()" in show and "showConfirmDialog(TEXT.discardCards)" in show
assert "opts.keepColumn?.(from)" in show
main = _text(M02 / "M02_MasterTemplete_UI_Main.ts")
assert "const busy = (): boolean => dirty || !!panel?.dirty();" in main
assert main.count("busy()") >= 3 # 떠나기 · 새로고침 막기 · 나무 고침(settle)
assert main.index("await panel.saveCards();") < main.index("await panel.reload();")
assert "keepColumn: (colId) => sheet?.selectColumn(colId)" in main
def test_면적산출_카드_알약_줄_켬끔_기본_숨김():
cards = _text(M02 / "M02_MasterTemplete_ItemCards.ts")
assert 'paintPills(readStateRaw("m02-card-pills") === "true");' in cards # 없으면 숨김
assert 'writeStateRaw("m02-card-pills", String(shown));' in cards
assert 'sheets[0].host.classList.toggle("is-pills-off", !shown);' in cards
assert "pills.hidden = !sheetEdit;" in cards # 고칠 수 있는 카드만(보기만은 알약 줄 없음)
css = _text(M02 / "M02_MasterTemplete_Structure.css")
assert re.search(r"\.m02-struct__sheet\.is-pills-off \.ss-links \{\s*display: none;", css)
state = _text(ROOT / "A00_Common" / "b_page_state.ts")
assert '"m02-card-pills": { bucket: "pref", scope: "global" },' in state
# 상세(전체 편집기)는 켬끔 없음 — 늘 보임
assert "is-pills-off" not in _text(M02 / "M02_MasterTemplete_UI_Main.ts")
def test_면적산출_알약은_일위대가_pills_길():
"""39-4 D7 — 로직 물량 「이름|단위」 + 자재 「자재|MT키」 · 다 고정 · 선택 입력 알약 빠짐."""
struct = _text(M02 / "M02_MasterTemplete_Structure.ts")
pills = struct.split("export async function pillsFor")[1].split("async function cardLinks")[0]
area = pills # 재료산출 갈래는 없앰 — 몸통이 면적산출 알약
assert 'kind === "material"' not in pills
assert "await fetchLaborPills(column)" in area
assert "고정: true" in area and "...(p.자재 ? { 자재: p.자재 } : {})" in area
assert "inputPills" not in area and "fetchComboInputs" not in struct
api = _text(M02 / "M02_MasterTemplete_Api_Fetch.ts")
assert "/layers/${activeLayer}/labor/${enc(column)}/pills" in api