Files
Aislo/resources/tester/test_ui_loading.py
T
eomsangdonandClaude Opus 5.5 1cce06780e refactor(M02): 옛 일위대가 조합 상세 Labor_Edit.ts 지움 — 그것만 쓰던 조합 길 함수(newCombo · editCombo · deleteCombo · fetchComboInputs · fetchLibLogic · fetchLibAuto) · 죽은 글 17 · CSS(미리 보기 · 조합 목록 · flash)도
- 쓰는 곳 0 은 grep 으로 확인한 것만 · Labor_Pick · View · Detail · Rows · Input · Diagram 은 남김
- 시험: test_ui_loading 의 Labor_Edit 줄 → 실무문서 상세 줄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
2026-10-04 20:47:42 +09:00

87 lines
4.0 KiB
Python

"""컨테이너 안 「불러오는 중」(PLAN 30-6 · `ui_template_loading.ts`) — 0.3초 · 실패 글 · M02 자리.
① `delayedShow` 를 Node 로 가짜 시계로 돌림 — 0.3초 전에 끝나면 안 보임(깜빡임 없음) · 넘으면 보이고
끝나면 걷힘 · 끝낸 뒤 시계가 와도 안 보임.
② 실패 자리 = 까닭 글(「불러오지 못함 — 까닭」) + [다시 불러오기] · 화면 전체 잠금 안 씀.
③ M02 나무 · 상세(표 · 도면) · 조합 목록 · 조합 상세 · 항목 카드가 이 부품을 씀.
"""
from __future__ import annotations
import json
import re
import shutil
import subprocess
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
LOADING = ROOT / "ui_template" / "ui_template_loading.ts"
M02 = ROOT / "M02_MasterTemplete"
def _text(path: Path) -> str:
return path.read_text(encoding="utf-8")
@pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음")
def test_0점3초_넘을_때만_보임():
found = re.search(r"^export function delayedShow[\s\S]*?^}", _text(LOADING), re.M)
assert found, "delayedShow 를 못 찾음"
script = (
"const LOADING_DELAY_MS = 300;\n"
+ found.group(0).replace("export ", "")
+ """
let now = 0; const jobs = [];
const timer = {
set: (fn, ms) => { jobs.push({ at: now + ms, fn, live: true }); return jobs.length - 1; },
clear: (id) => { if (jobs[id]) jobs[id].live = false; },
};
const tick = (ms) => {
now += ms;
for (const j of jobs) if (j.live && j.at <= now) { j.live = false; j.fn(); }
};
const log = [];
const on = (n) => () => log.push(n + ":show"); const off = (n) => () => log.push(n + ":hide");
const fast = delayedShow(on("fast"), off("fast"), undefined, timer);
tick(200); fast(); tick(500);
const slow = delayedShow(on("slow"), off("slow"), undefined, timer);
tick(299); log.push("299"); tick(1); slow(); tick(500);
console.log(JSON.stringify(log));
"""
)
result = subprocess.run(
["node", "--experimental-strip-types", "--no-warnings",
"--input-type=module-typescript", "-e", script],
capture_output=True, text=True, encoding="utf-8", timeout=60,
) # fmt: skip
assert result.returncode == 0, result.stderr
assert json.loads(result.stdout) == ["299", "slow:show", "slow:hide"]
def test_실패_글과_다시_불러오기_M02_자리():
src = _text(LOADING)
assert 'reason ? `${t("Common_Load_Failed")} — ${reason}` : t("Common_Load_Failed")' in src
assert 'createButton({ label: t("Common_Reload")' in src and 'role: "alert"' in src
assert "showLoadingOverlay()" not in src # 칸 안만(화면 전체 잠금 안 부름)
# 브라우저 setTimeout 을 객체 메서드로 부르면 Illegal invocation — 감싼 기본값(ORCA 흠)
assert "set: (fn, ms) => setTimeout(fn, ms)," in src
assert "clear: (id) => clearTimeout(id)," in src
locale = _text(ROOT / "ui_template" / "ui_template_locale_common.ts")
assert 'Common_Load_Failed: ["불러오지 못함"' in locale
assert 'Common_Reload: ["다시 불러오기"' in locale
tree = _text(M02 / "M02_MasterTemplete_TreePanel.ts")
assert "const stop = showLoading(body);" in tree
assert "loadingError(why(error), () => void refresh())" in tree
main = _text(M02 / "M02_MasterTemplete_UI_Main.ts")
assert "const stop = showLoading(host);" in main
assert "loadingError(why, () => void open(next))" in main
# 옛 조합 나무 · 상세(Labor.ts · Labor_Edit.ts)는 39 에 지움 — 그 자리는 실무문서(같은 꼴)
practice = _text(M02 / "M02_MasterTemplete_Practice.ts")
assert "const stop = showLoading(view);" in practice
assert "loadingError(why(error), () => void drawList())" in practice
assert "loadingError(why(error), () => void drawOne(key))" in practice
assert "cards.map((c) => c.shell.loading())" in _text(M02 / "M02_MasterTemplete_ItemCards.ts")
assert "loading: () => showLoading(host)," in _text(M02 / "M02_MasterTemplete_CardShell.ts")