# -*- coding: utf-8 -*- """163 B08 구조물도 모달 — 연결 칩 · 접기(163-1) · 사본 고침(163-3) · [업데이트](163-4) · 콘크리트소요 줄(163-5). 화면 글 판정 — 서버 · 짝 계산(Material_Calc)은 안 고침 · 고르기 모달 편집 화면은 재사용만. """ import re from pathlib import Path ROOT = Path(__file__).resolve().parents[2] LINK = (ROOT / "B08_Quantity/B08_Quantity_UI_Link.ts").read_text(encoding="utf-8") DRAWING = (ROOT / "B08_Quantity/B08_Quantity_UI_Drawing.ts").read_text(encoding="utf-8") CSS = (ROOT / "B08_Quantity/B08_Quantity_UI_Drawing.css").read_text(encoding="utf-8") MATERIAL = (ROOT / "B08_Quantity/B08_Quantity_UI_Material.ts").read_text(encoding="utf-8") LOCALE = (ROOT / "ui_template/ui_template_locale_b4.ts").read_text(encoding="utf-8") def test_163_1_칩_한_줄_공용_접기(): assert 'line.className = "b08-link__row"' in LINK # 시설마다 한 줄 assert '"b08-link__chip is-linked"' in LINK and "chip.dataset.b08LinkSlot = slot.copy" in LINK # 모두 연결이면 접힘 · 미연결 있으면 펼침 assert 'ui-collapsible${missing ? "" : " is-collapsed"}' in LINK assert "ui-collapsible__title" in LINK and "attachCollapsible(section)" in LINK assert "state.title = state.textContent" in LINK # 긴 이름 = 툴팁 assert re.search(r"\.b08-link__row \{[^}]*flex-wrap: wrap", CSS) assert ".b08-link__slot" not in CSS + LINK # 옛 줄 꼴 없음 def test_163_3_수정_사본_편집_화면(): assert "editable: () => true" in DRAWING assert "onEdit: (kind) => openEdit(copy, name, kind, load)" in DRAWING assert 'labor: () => openEdit(copy, name, "inputs", load)' in DRAWING assert 'import("@ui/ui_template_item_picker_edit")' in DRAWING assert "createEditView(" in DRAWING and "items: projectItems(request.projectId)" in DRAWING assert "info: { 폴더: copy.폴더, 원본: copy.항목 }" in DRAWING # [뒤로] = 몸통 되돌림 · 저장했으면 카드 다시 읽음 · 닫을 때 집계표 다시 셈 assert "body.replaceChildren(...kept)" in DRAWING and "if (saved) reload()" in DRAWING assert "if (edited) request.onLinked()" in DRAWING assert "if (editView && !(await editView.leave())) return false" in DRAWING assert 'kind === "inputs" ? [note(L("B08_Quantity_Sheets_InputsOnly"))]' in DRAWING assert "saveTemplate" not in DRAWING # 층 쓰기 없음 — 사본 PUT 만(편집 화면 `items.write`) def test_163_4_배지_업데이트(): assert ".list(folder)" in LINK and "structureFolder(slot.copy)" in LINK for key in ("Edited", "Gone", "Changed"): assert f'badge("B08_Quantity_Link_{key}"' in LINK, key assert "button.disabled = !info.마스터바뀜 || !!info.원본없음" in LINK assert "updateButton.disabled = true" in LINK # 대조 받기 전 꺼짐 assert "projectItems(projectId).reapply(info)" in LINK assert 'showConfirmDialog(ask, L("B08_Quantity_Link_Update"))' in LINK assert 'info.고침 ? ` ${L("B08_Quantity_Link_UpdateEdited")}`' in LINK # 저장 뒤 = [선택]과 같은 흐름(onLinked) assert "saved\n ? onLinked()" in LINK def test_163_5_콘크리트_5줄_늘_까닭(): table = MATERIAL[ MATERIAL.index("function concreteTable") : MATERIAL.index("function totalTable") ] assert "const keep = rows.map((_row, i) => i)" in table assert 'editable: (_i, key) => key.startsWith("per:")' in table # 배합 늘 고침 assert "function concreteWhy(" in MATERIAL assert "matched(m.name, m.spec, m.unit)" in MATERIAL # 짝 계산 맞춤 그대로 assert "source.snapshot?.units?.[row.id]" in MATERIAL assert "concreteNote.textContent = concreteWhy(sheets, payload.source)" in MATERIAL assert "Material_Calc" in MATERIAL and "concreteWhy" not in ( ROOT / "B08_Quantity/B08_Quantity_Material_Calc.ts" ).read_text(encoding="utf-8") def test_locale_keys_exist(): for text in (LINK, DRAWING): for key in set(re.findall(r'L\("([A-Za-z0-9_]+)"\)', text)) | set( re.findall(r'badge\("([A-Za-z0-9_]+)"', text) ): assert f"{key}:" in LOCALE or key.startswith(("B08_Quantity_Summary_", "Common_")), key