Files
Aislo/resources/tester/test_m02_area_panel.py
T
eomsangdonandClaude Opus 5.5 ef24de8b63 feat(M02): 일위대가 수량산출 모달 하나 — 지금 수량 · 손 입력 · 연결 풀기 + 면적산출 시트를 모달 안에 바로(칸 누름 = 이음) · 넣을 값 모달에서 수량 칸 뺌(43-1 · 43-2)
- 새 Labor_QtyModal.ts(로직 줄 수량산출 칸 · 자재 줄 같음 · [확인] = 손 · 고른 칸 · 풀기 · [닫기] = 그대로) · 두 단계 모달([엑셀에서 고르기]) 없앰
- AreaCellPick: 시트 부분을 mountAreaSheet 로 뗌(읽기만 · 실제 값 · 이은 칸 색 · 함께 잇기 · 바꾸기 물음 그대로) · 모달 pickAreaCell 지움
- Labor_Detail: openQty · openMat → openQtyFor · linkCell · Labor_Input: 수량 칸 · openQtyModal 지움(입력값 · 메모만)
- 화면 판정 시나리오 resources/tester/ui_checks/43-1_수량산출_모달.js · 시험 test_m02_area_panel 부품 기대값

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
2026-10-05 00:35:03 +09:00

110 lines
5.9 KiB
Python

"""면적산출 상세 오른쪽 일위대가 패널 · 칸 지정 모달(PLAN 39-4 D2 · D5 · D6) — 화면 조작은 ORCA.
· 패널 = 그 열 일위대가 보기 갈래(`Labor_View`) · 조합 목록 · 찾기 · [이 열에 쓰기] · [조합 고치기] 없음
· 줄 누름 = 칸 지정 모달 → 스프레드시트 `setLink`(면적 문서 `연결` 한 곳 · 알약과 같은 길)
· 시트 칸 값 · 연결이 바뀌면 `setQty` 로 바로 곱함(서버 안 부름)
"""
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_면적_길은_일위대가_패널():
main = _text("M02_MasterTemplete_UI_Main.ts")
body = main.split("async function mountSheet")[1].split("async function remount")[0]
area = body.split('if (kind === "area") {')[1].split("\n }\n")[0]
assert "apanel = buildAreaPanel({" in area and "host.append(apanel.root);" in area
assert "picked: () => picked," in area and "pills: () => links.항목," in area
assert "apanel?.refresh();" in body and "onSelect: (s) => (picked = s.칸)," in body
assert "buildComboBar" not in main # 조합 줄 · [조합 고치기] 지움
assert body.index('if (at.layer === "project") return;') < body.index("buildAreaPanel")
assert "apanel?.destroy();\n apanel = null;" in main # drop
def test_패널_몸은_보기_갈래_줄_누름은_칸_지정():
panel = _text("M02_MasterTemplete_AreaPanel.ts")
assert "createLaborView(openLink)" in panel
assert "void view.show(opts.layer, opts.column, quantities(opts.sheet()));" in panel
assert "view.setQty(quantities(opts.sheet()), cellsOf(opts.sheet()))" in panel
assert panel.index("void view.show(") < panel.index("refresh(); // 칸 주소")
assert "openAreaLink({" in panel and "if (!row.pill) return showToast(TEXT.noPill" in panel
for gone in ("fetchUsableCombos", "setColumnCombo", "branchCombo"):
assert gone not in panel
def test_칸_지정_모달은_setLink_만():
link = _text("M02_MasterTemplete_AreaLink.ts")
assert 'opts.sheet.setLink(opts.key, a1, opts.info, choice === "바꾸기")' in link
assert (
"linksAt(book, sheetId, a1, opts.key)" in link and "askShare(" in link
) # 칸 하나 알약 여럿
assert "done(here)" in link and "done(address.input.value)" in link and "done(null)" in link
assert "address.setError(TEXT.bad)" in link # 틀린 · 빈 주소는 모달 그대로
assert "pick.disabled = link.disabled = address.input.disabled = opts.readOnly;" in link
assert "saveTemplate" not in link # 저장은 [저장]
def test_빈_칸은_수량_없음_서버와_같음():
"""39-8 ② — 빈 칸에 이은 알약 = 수량 없음(반영 「—」 · 「수량 A1 = 빈 칸」) · 0 칸 = 0 · 값 칸 = 값."""
from M02_MasterTemplete import M02_Labor_Doc as labor
doc = {
"시트": [
{
"id": "s1",
"칸": {"A2": {"값": 0}, "A3": {"값": "1,250"}, "A4": {"값": "글"}},
"연결": [
{"키": k, "칸": c}
for k, c in (("빈", "A1"), ("영", "A2"), ("값", "A3"), ("글", "A4"))
],
}
]
}
assert {k: float(v) for k, v in labor.area_values(doc).items()} == {"영": 0, "값": 1250}
panel = _text("M02_MasterTemplete_AreaPanel.ts")
body = panel.split("function quantities")[1].split("\n}\n")[0]
assert 'toNumber(cell?.식 !== undefined ? (v && "수" in v ? v.수 : null) : cell?.값)' in body
assert 'String(raw).replace(/,/g, "").trim()' in panel and 'typeof raw === "boolean"' in panel
sheet = (ROOT / "A00_Common" / "spreadsheet" / "spreadsheet.ts").read_text(encoding="utf-8")
assert 'const empty = !cell || (cell.식 === undefined && (cell.값 ?? "") === "");' in sheet
rows = _text("M02_MasterTemplete_Labor_Rows.ts")
assert '${tc("Labor_Qty")} ${at} = ${tc("In_QtyEmpty")}' in rows
assert "if (!value) return `${link.칸} = ${TEXT.empty}`;" in _text(
"M02_MasterTemplete_AreaLink.ts"
)
def test_카드_알약_취향은_계정_받은_뒤_올림():
"""39-8 ③ — 화면이 뜰 때 브라우저 옛 값이 계정 값을 덮지 않게 · 카드는 열 때마다 취향을 다시 읽음."""
state = (ROOT / "A00_Common" / "b_page_state.ts").read_text(encoding="utf-8")
push = state.split("function pushUiPrefs")[1].split("export function syncUiPrefs")[0]
assert "void (prefsPull ?? Promise.resolve())" in push and "prefs: localPrefs()" in push
assert "prefsPull = pullUiPrefs();" in state
cards = _text("M02_MasterTemplete_ItemCards.ts")
load = cards.split("async function load(")[1]
assert 'paintPills(readStateRaw("m02-card-pills") === "true");' in load
def test_엑셀_칸_고르기_모달_부품():
"""40-3 ① · 43-1 — 읽기만 시트(수량산출 모달 안에 바로 · `mountAreaSheet`) · 칸 누름 = 주소 ·
풀기 · 손 · 확인 · 닫기는 일위대가 수량산출 모달(`Labor_QtyModal`) · 저장 안 함."""
pick = _text("M02_MasterTemplete_AreaCellPick.ts")
assert 'export { linkAreaCell } from "../A00_Common/spreadsheet/spreadsheet_link_set";' in pick
assert "export function mountAreaSheet(" in pick and "readOnly: true," in pick
assert 'opts.onPick(choice === "바꾸기" ? { 칸: at, 바꾸기: true } : { 칸: at });' in pick
qty = _text("M02_MasterTemplete_Labor_QtyModal.ts")
assert "sheet = mountAreaSheet(host, {" in qty and 'pending = { kind: "unlink" };' in qty
assert "엑셀에서 고르기" not in qty # 두 단계 모달 없앰(43-1)
assert "linksAt(book, sheetId, at, opts.pill)" in pick and "askShare(" in pick
assert "if ((e as MouseEvent).button === 0 && moved) void choose();" in pick
assert "handle?.destroy();" in pick
assert "saveTemplate" not in pick