"""740-2 · 738-2 상세 머리 [초기화] [삭제] · 출처 꼬리표 지킴 시험(서버 · 화면 없음).""" import json import re import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parents[2] M02 = ROOT / "M02_MasterTemplete" MAIN = (M02 / "M02_MasterTemplete_UI_Main.ts").read_text(encoding="utf-8") ACTIONS = (M02 / "M02_MasterTemplete_Main_Actions.ts").read_text(encoding="utf-8") HO = (ROOT / "M01_MasterData" / "M01_MasterData_UI_LogicLab_Ho.ts").read_text(encoding="utf-8") COVER = (M02 / "logic" / "M02_Sangeun_Cover_Model.ts").read_text(encoding="utf-8") def _born(expr: str): """순수 TS(`logic/M02_Born_Tag.ts`)를 Node 로 돌려 JSON 답을 받음.""" uri = (M02 / "logic" / "M02_Born_Tag.ts").as_uri() code = ( f"import {{ bornText, bornOfCid, bornNote }} from '{uri}';" f"console.log(JSON.stringify({expr}));" ) out = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", "--experimental-strip-types", "--no-warnings", "--input-type=module", "-e", code], capture_output=True, text=True, check=True, cwd=ROOT, ) return json.loads(out.stdout) BORN = { "층": "personal", "주인": "u1", "키": "SK-000012", "이름": "강관비계", "때": "2026-11-02T06:30:12Z", } def test_꼬리표_글_첫줄_짧게_둘째줄_풍선(): shown, tip = _born(f"bornText({json.dumps(BORN, ensure_ascii=False)})").split("\n") assert shown == "본뜬 SK-000012" assert "SK-000012 강관비계" in tip and "개인" in tip assert re.search(r"\d{4}-\d\d-\d\d \d\d:\d\d", tip) # 이 컴퓨터 시각 · 시간대 따라 값이 다름 def test_꼬리표_없으면_빈칸_기초번호_뒤에_붙음(): assert _born("bornText(null)") == "" assert _born("bornText(undefined, 'A1')") == "A1" got = _born(f"bornText({json.dumps(BORN, ensure_ascii=False)}, 'A1')") assert got.split("\n")[0] == "A1 · 본뜬 SK-000012" def test_줄_열쇠에서_그_더한줄_출처를_찾음(): adds = json.dumps([{}, {"본뜬": BORN}], ensure_ascii=False) assert _born(f"bornOfCid('add:#1', {adds})").startswith("본뜬 SK-000012") assert _born(f"bornOfCid('add:#1/add:#0', {adds})").startswith("본뜬 SK-000012") # 펼침 세부 assert _born(f"bornOfCid('add:#0', {adds})") == "" assert _born(f"bornOfCid('hopyo:X#3', {adds})") == "" def test_머리_단추_차례_초기화_삭제_저장(): kids = MAIN[MAIN.index('className: "m02-main__head"') :] kids = kids[: kids.index("]")] order = [kids.index(w) for w in ("reload,", "actions.reset,", "actions.del,", "save,")] assert order == sorted(order) assert "actions.update(" in MAIN # 쓰기 권한 없는 층 = 안 보임 def test_삭제는_735_경고_창을_그대로_씀(): assert "askLibraryDelete(" in ACTIONS and '"delete"' in ACTIONS assert "sure ? { 확인: true }" in ACTIONS.replace( "ans.sure", "sure" ) # 확인 몸 = 쓰는 곳 줄까지 assert "sangeunList(" in ACTIONS and "precomboList(" in ACTIONS # 지운 뒤 목록으로 def test_초기화는_미리보기_뒤_물음_뒤_씀(): assert ACTIONS.index("미리보기: true") < ACTIONS.index("미리보기: false") assert "ctx.confirmLeave()" in ACTIONS # 저장 안 한 고침 먼저 물음 assert "옵션 · 기본정보는 그대로" in ACTIONS def test_공용_꼬리표_칸은_첫줄만_보이고_풍선에_나머지(): assert 'text.split("\\n")' in HO assert "bornOfCid(" in COVER def test_격자_비고_칸은_첫줄만(): assert _born(f"bornNote({json.dumps(BORN, ensure_ascii=False)})") == "본뜬 SK-000012" assert _born("bornNote(null)") == ""