- 서버: inputs · combo_logics · _num 몸을 M02_Labor_Inputs.py 로(logic_inputs = 로직 키들 입력 + 자동값) · M02_MasterTemplete_Inputs.py 는 그것을 부름 - 길: GET /api/m02/logic-lib/inputs?keys= (로그인 · 일위대가 입력 모달용) - 화면: 값 카드(createInputsValueCard) · 값 함수 → M02_Labor_Values.ts · M02_Labor_Values_Model.ts · 값 칸 하나(createValueControl)를 떼어 값 카드와 입력 모달이 같이 씀 · CSS 도 옮김 - 옛 자리(M02_MasterTemplete_Inputs.ts · _Inputs_Model.ts)는 새 파일을 다시 내보냄 — B05 고르기 모달 그대로 - 시험: 새 test_m02_labor_values.py · 옮긴 자리 따라 test_item_picker_detail · test_m02_card_shell · helper_m02_inputs 고침 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
62 lines
3.2 KiB
Python
62 lines
3.2 KiB
Python
"""M02 항목 카드 공용 틀(PLAN 31-7 · `M02_MasterTemplete_CardShell.ts`) — 네 카드가 틀 하나를 씀.
|
|
|
|
정함: 제목 줄(제목 · 점 ● · 오른쪽 단추) + 한 줄 부제 · 「〇〇 수정」 = 빈 단추 한 모양 ·
|
|
[저장] = 늘 보임 · 고쳐야 켜짐 · 카드 안 Ctrl+S · 알림 글 한 벌 · ? = 도면 · 엑셀 ·
|
|
불러오는 중 = 네 카드 · 실패 = 카드 안 글 + [다시 불러오기] · 물음 한 번. 화면 조작 판정은 ORCA.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
M02 = ROOT / "M02_MasterTemplete"
|
|
|
|
|
|
def _text(name: str) -> str:
|
|
return (M02 / name).read_text(encoding="utf-8")
|
|
|
|
|
|
def test_틀_제목_줄_부제_상태():
|
|
shell = _text("M02_MasterTemplete_CardShell.ts")
|
|
assert 'children: [el("span", { text: opt.title }), dot, tools],' in shell
|
|
assert 'tools.addEventListener("click", (event) => event.stopPropagation());' in shell
|
|
assert 'el("div", { className: "m02-struct__sub", children: opt.sub })' in shell
|
|
assert "loading: () => showLoading(host)," in shell
|
|
assert "fail: (reason, retry) => host.replaceChildren(loadingError(reason, retry))," in shell
|
|
assert "setDirty: (dirty) => (dot.hidden = !dirty)," in shell
|
|
assert 'event.key.toLowerCase() !== "s"' in shell # 카드 안 Ctrl+S
|
|
|
|
|
|
def test_저장_단추_알림_한_벌():
|
|
shell = _text("M02_MasterTemplete_CardShell.ts")
|
|
assert 'saved: "저장했음"' in shell and 'failed: "저장 못 함 — {value}"' in shell
|
|
assert 'stale: "그 사이 바뀜 — 다시 읽음"' in shell
|
|
assert "button.disabled = !dirty || saving;" in shell
|
|
assert "error instanceof StaleError ? CARD_TEXT.stale" in shell
|
|
assert "shell.onSave(() => void (dirty && run()));" in shell
|
|
|
|
|
|
def test_네_카드가_틀을_씀_수정_단추_한_모양():
|
|
cards = _text("M02_MasterTemplete_ItemCards.ts")
|
|
assert "const shell = cardShell({ title, body, sub: [no, name] });" in cards
|
|
assert "shell.tools.append(help, saver.button, edit);" in cards
|
|
assert 'variant: "filled"' not in cards # [수정] 은 모두 빈 단추(ghost)
|
|
assert "c.saver.button.hidden = c.help.hidden = !can;" in cards # [저장] · ? 늘 보임
|
|
assert "DRAWING_KEYS" in cards and "SHEET_KEYS" in cards
|
|
inputs = _text("M02_MasterTemplete_Inputs.ts") + _text("M02_Labor_Values.ts")
|
|
assert inputs.count("cardShell({") == 2 # 선택 입력 · 값 카드(39-3 에 `M02_Labor_Values.ts` 로)
|
|
assert "shell.fail(" in inputs and "shell.loading()" in inputs
|
|
assert "m02-struct__card ui-collapsible" not in inputs # 손으로 만든 겉 틀 없음
|
|
drawing = _text("M02_MasterTemplete_DrawingCard.ts")
|
|
assert "createButton" not in drawing and "showToast" not in drawing # 단추 · 알림은 틀
|
|
|
|
|
|
def test_실패는_카드_안_글과_다시_불러오기():
|
|
cards = _text("M02_MasterTemplete_ItemCards.ts")
|
|
assert "showToast" not in cards # 토스트 안 씀(저장 알림은 틀)
|
|
assert "c.shell.fail(" in cards and "reload" in cards
|
|
picker = (ROOT / "ui_template" / "ui_template_item_picker_detail.ts").read_text("utf-8")
|
|
assert "inputs.set(null, why(error), () => void paintInputs(row, seq));" in picker
|
|
assert "const stop = inputs.loading();" in picker
|