"""796-2 수식 탭 화면 지킴(정적 · 서버 · 브라우저 없이) — 부품 상자만 · 수식 탭 첫 탭 · 아이콘 숨김 · 변수 고침 창 · 옵션 가로. 화면 동작(분수 · 변수 풀이 · 고침 → 금액 · 변수 더함 · 지움 · 저장)은 ORCA 사용자 길로 확인 — 서버 모델은 `test_796_1_formula_model.py`. """ from __future__ import annotations import re from pathlib import Path ROOT = Path(__file__).resolve().parents[2] M01 = ROOT / "M01_MasterData" UI = ROOT / "ui_template" PARTS = [UI / "ui_template_equation.ts", UI / "ui_template_equation_line.ts"] PAGE = [ M01 / "M01_MasterData_UI_LogicLab_Equation.ts", M01 / "M01_MasterData_UI_LogicLab_EquationVar.ts", ] MODEL = M01 / "logic" / "M01_Logic_Equation_Model.ts" CSS = [UI / "ui_template_equation.css", M01 / "M01_MasterData_UI_LogicLab_Equation.css"] RAW = re.compile(r" str: return path.read_text(encoding="utf-8").replace("\r\n", "\n") def test_부품_상자만_날_단추_입력_없음(): for path in [*PARTS, *PAGE, MODEL]: src = _text(path) assert not RAW.search(src), f"{path.name} — 날 button · input" # 수식 칩 = 글 속 부품(span role) · 단추 · 입력 · 고르기는 부품 상자 것 page = _text(PAGE[0]) + _text(PAGE[1]) for part in ( "createIconButton", "createButton", "createToolbar", "createFormulaCell", "openModal", ): assert part in page, part assert "createValueControl" in page # 옵션 값 칸 = 기존 값 칸 한 벌(M02_Labor_Values) def test_색은_공통_값만_700줄_안(): for path in CSS: css = _text(path) assert not re.search(r"#[0-9a-fA-F]{3,8}\b|rgba?\(", css), path.name assert "var(--color-" in css for path in [*PARTS, *PAGE, MODEL, *CSS, M01 / "M01_MasterData_UI_LogicLab.ts"]: assert len(_text(path).splitlines()) <= 700, path.name assert len(_text(M01 / "M01_MasterData_UI_LogicLab_Ho.ts").splitlines()) <= 700 def test_계산_자리_화면은_모양만(): model = _text(MODEL) assert "fetch(" not in model and "document." not in model # logic/ = 화면 · fetch 없음 for path in PARTS: assert "fetch(" not in _text(path) # 부품은 그리기만 page = _text(PAGE[0]) assert page.count("fetch(") == 1 # 서버 길 한 곳 — 계산은 서버 한 벌(③) for route in ('"/logic/equation"', '"/logic/equation/preview"', '"/logic/equation/save"'): assert route in page, route assert "saveRevised(" in page and "개정확인" in page # [저장] = 개정 확인 길 assert "edits" in page and "sessionStorage" in page # 고침 목록 = 캐시 → [저장] 한 번 assert "ctl?.abort()" in page # 옛 요청 끊음 assert "setInterval" not in page and "autosave" not in page.lower() # 자동저장 없음 def test_수식_탭이_첫_탭_단가산출_상세는_그대로(): view = _text(M01 / "M01_MasterData_UI_LogicLab_View.ts") labels = re.findall(r'\{ value: "(\w+)", label: tl\("(\w+)"\) \}', view) assert [v for v, _ in labels] == ["equation", "ho", "sheet", "est", "calc", "formula"] assert 'host.dataset.view = "equation";' in view and 'value: "equation",\n size: 32' in view detail = _text(M01 / "M01_MasterData_UI_LogicLab_Detail.ts") assert 'block(ctx.equation, "equation")' in detail assert 'block(section(tl("Ho_Title"), [formula]), "formula")' in detail # 옛 탭은 걷지 않음 css = _text(M01 / "M01_MasterData_UI_LogicLab_Style.css") assert '[data-view="equation"] [data-block]:not([data-block="equation"])' in css lab = _text(M01 / "M01_MasterData_UI_LogicLab.ts") assert "createLabEquation({" in lab and "equation: equation.root," in lab assert "equation.canLeave()" in lab # 저장 전 떠나면 버림 물음 def test_아이콘_줄은_고른_줄에만_고침은_관리자만(): line = _text(PARTS[1]) assert "o.selected === id ? o.slot?.(line, id) : null" in line # 고른 줄에만 식 칸 · 아이콘 줄 page = _text(PAGE[0]) for icon in ('"frac"', '"paren"', '"sub"', '"sup"', '"percent"'): assert icon in page, icon # 분수 · 괄호 · 첨자 · % assert 'label: t("Add")' in page # 변수 더함 assert "opt.admin && !opt.blocked()" in page # 관리자 + 시트 쪽 저장 안 한 고침 없을 때만 assert "onSelect: edit" in page and "onVar: edit" in page and "slot: edit" in page assert "createFormulaCell" in page and "../A00_Common/sheet_formula_cell" in page def test_변수_고침_창_칸과_지움_막힘(): var = _text(PAGE[1]) for label in ( 'Name: ["이름"', 'Sign: ["기호"', 'Up: ["위첨자"', 'Down: ["아래첨자"', 'Unit: ["단위"', 'Digits: ["보이는 자리', "Value:", ): assert label in var, label assert '할일: "지움"' in var and "why.set(bad)" in var # 쓰는 곳 목록 = 서버 까닭 그대로 띠에 assert "commit(" in var or "o.commit(" in var assert "openAddDialog" in var and 'value: "중간"' in var # 입력 · 중간 더함 model = _text(MODEL) for job in ('"식"', '"더함"', '"지움"', '"변수"'): assert job in model, job def test_옵션_가로_찾기형_말줄임(): page = _text(PAGE[0]) assert "createToolbar({" in page and "optionNode(" in page assert "BIG = 12" in page and "datalist" in page # 고르기 많으면 찾기형 assert "title" in page # 마우스 올림 전체 글 css = _text(CSS[1]) assert "text-overflow: ellipsis" in css and "max-width: 14rem" in css assert "askAgain" in page # 옵션 바꾸면 다시 셈 def test_부품_모음_견본_한_줄(): src = _text(UI / "ui_template_ui_kit_parts.ts") rows = re.findall( r'\{ key: "([^"]+)", name: "[^"]+", group: "(\w+)",[^\n]*file: "([^"]+)"', src ) assert ("equation", "compound", "ui_template_equation.ts") in rows assert len(src.splitlines()) <= 700 head = _text(PARTS[0]) for word in ("분수", "첨자", "조건 칩", "크기", "상태", "쓰는 법"): assert word in head, word