"""552-3 부품 「카드」 지킴 시험 + 묶음 부품 공용 규칙(`check_part` — 552-3 시험 파일들이 가져다 씀). 공용 규칙 = 파일 머리(꼴 · 크기 · 상태 · 쓰는 법 · 대신하는) · 만들기 함수 · 클래스 이름 · 날 색 · `--b01-*` · `--draw-*` 없음 · font-family 없음 · 마우스 · 눌림 = `:is(:hover, [data-state="hover"])` 꼴 · 부품 모음 줄(file · demo) · 700 줄. """ from __future__ import annotations import re from pathlib import Path ROOT = Path(__file__).resolve().parents[2] UI = ROOT / "ui_template" RAW_COLOR = re.compile(r"#[0-9a-fA-F]{3,8}\b|rgba?\(|hsla?\(") def _text(name: str) -> str: return (UI / name).read_text(encoding="utf-8") def kit_line(key: str) -> str: """부품 모음 목록의 그 부품 줄(이어지는 demo 줄까지).""" src = _text("ui_template_ui_kit_parts.ts") m = re.search(r' \{ key: "%s",[^\n]*\n(?: [^\n]*\n)*' % re.escape(key), src) assert m, key return m.group(0) def check_part(key: str, ts: str, css: list[str], create: list[str], classes: list[str]) -> None: head = _text(ts).split("*/", 1)[0] for word in ("꼴", "크기", "상태", "쓰는 법", "대신하는"): assert word in head, (ts, word) body = _text(ts) for fn in create: assert re.search(rf"export function {fn}\b", body), fn for cls in classes: assert cls in body + "".join(_text(c) for c in css), cls for name in [ts, *css]: text = _text(name) assert len(text.splitlines()) <= 700, name # 옛 파일에 덧붙인 CSS 는 「(552-3)」 표 뒤만 · 주석(머리 설명 · 옛 변종 이름)은 빼고 봄 if name.endswith(".css") and "(552-3)" in text: text = text[text.index("(552-3)") :] code = re.sub(r"/\*[\s\S]*?\*/", "", text) assert not RAW_COLOR.search(code), (name, RAW_COLOR.search(code)) assert "--b01-" not in code and "--draw-" not in code, name if name.endswith(".css"): assert "font-family" not in code, name for m in re.finditer(r":(hover|active)\b", code): around = code[max(0, m.start() - 4) : m.end() + 30] assert f'[data-state="{m.group(1)}"]' in around, (name, around) line = kit_line(key) assert f'file: "{ts}"' in line and "demo:" in line, key assert "legacy: true" not in line, key def test_card(): check_part( "card", "ui_template_card.ts", ["ui_template_card.css"], ["createCard", "setCardSelected"], ["ui-card", "ui-card--raised", "ui-card__title", "ui-card__body", "ui-card--select"], ) css = _text("ui_template_card.css") assert '.ui-card[data-pad="12"]' in css and '.ui-card[data-pad="16"]' in css assert '[aria-pressed="true"]' in css and ":disabled" in css # 옛 부름 꼴 그대로 — 본체가 다시 내보냄 · 선 카드 그림자 0 elements = _text("ui_template_elements.ts") assert ( 'export { createCard, setCardSelected, type CardOptions } from "./ui_template_card"' in elements ) assert "box-shadow: none; /* 선 카드(552-3)" in _text("ui_template_elements_styles.ts")