Files
Aislo/resources/tester/spreadsheet/test_spreadsheet_size.py
T

80 lines
3.0 KiB
Python

"""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 size["static"] == [], f"스프레드시트 조각을 정적으로 끌어옴 — {size['static']}"
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:
# 시험용 진입(`resources/tester/`)은 앱 번들 밖
if rel.startswith(("A00_Common/spreadsheet/", "resources/tester/")):
continue
if 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