"""F — 스프레드시트 크기 예산 · M02 만 늦게 불러옴(계약 `spreadsheet_types.ts` 머리). 예산(압축 gzip 뒤) — 엔진 A+B 22 KB · 화면 C+D+E 28 KB · css 4 KB · 합 54 KB. 엔진은 파일마다 따로 묶어 더하므로 실제보다 조금 크게 잼(넘치면 넘친 것). """ import json import re import shutil import subprocess from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[3] SCRIPT = Path(__file__).with_name("spreadsheet_size.mjs") KB = 1024 BUDGET = {"engine": 22 * KB, "view": 28 * KB, "css": 4 * KB, "total": 54 * KB} pytestmark = pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음") def test_크기_예산(): out = subprocess.run( ["node", str(SCRIPT), str(ROOT)], cwd=ROOT, capture_output=True, text=True, encoding="utf-8", timeout=300, check=True, ) size = json.loads(out.stdout.strip().splitlines()[-1]) engine, total = size["engine"]["js"], size["total"] view = max(0, total["js"] - engine) print( f"gzip — 엔진 {engine} · 화면 {view} · css {total['css']} · 합 {total['js'] + total['css']}" ) assert engine <= BUDGET["engine"], f"엔진 {engine} B > {BUDGET['engine']}" assert view <= BUDGET["view"], f"화면 {view} B > {BUDGET['view']}" assert total["css"] <= BUDGET["css"], f"css {total['css']} B > {BUDGET['css']}" assert total["js"] + total["css"] <= BUDGET["total"] # 정적 import 금지 — 타입만(`import type`) · 늦게(`import(`) 는 됨 _STATIC = re.compile( r"^\s*import\s+(?!type\b)[^;]*?from\s+[\"'][^\"']*spreadsheet/spreadsheet", re.M ) _SIDE = re.compile(r"^\s*import\s+[\"'][^\"']*spreadsheet/spreadsheet", re.M) def test_M02_만_늦게_불러옴(): offenders, users = [], [] listed = subprocess.run( ["git", "ls-files", "--cached", "--others", "--exclude-standard", "*.ts"], cwd=ROOT, capture_output=True, text=True, encoding="utf-8", check=True, ).stdout.splitlines() for rel in listed: if rel.startswith("A00_Common/spreadsheet/") or not (ROOT / rel).is_file(): continue text = (ROOT / rel).read_text(encoding="utf-8", errors="replace") if "spreadsheet/spreadsheet" not in text: continue if _STATIC.search(text) or _SIDE.search(text): offenders.append(rel) if "import(" in text: users.append(rel) # 서버 Node 진입만 정적(브라우저 번들 밖) assert offenders == ["common_util/common_util_spreadsheet_node.ts"], offenders assert users and all(u.startswith("M02_MasterTemplete/") for u in users), users