from pathlib import Path import re ROOT = Path(__file__).resolve().parents[1] STATIC_DIR = ROOT / "static" def test_base_template_owns_sidebar_and_user_shell(): forbidden_patterns = [ (r'id=["\']sidebar["\']', "sidebar element"), (r'class=["\']sidebar["\']', "sidebar class"), (r"\bsidebar-user\b", "sidebar user trigger"), (r"\buserDropdown\b", "user dropdown"), (r"\buserInitial\b", "user initial"), (r"\buserEmailShort\b", "user email"), (r"\bddEmail\b", "dropdown email"), (r"\bfunction\s+toggleUserMenu\s*\(", "toggleUserMenu"), (r"\basync\s+function\s+loadUser\s*\(", "loadUser"), (r"\bfunction\s+showChangePwd\s*\(", "showChangePwd"), (r"\bfunction\s+closePwdModal\s*\(", "closePwdModal"), (r"\basync\s+function\s+changePwd\s*\(", "changePwd"), (r"\basync\s+function\s+doLogout\s*\(", "doLogout"), ] for path in STATIC_DIR.glob("*.html"): if path.name in {"base.html", "index.html"}: continue text = path.read_text(encoding="utf-8") if "extends \"base.html\"" not in text and "extends 'base.html'" not in text: continue for pattern, label in forbidden_patterns: assert not re.search(pattern, text), f"{path.name} should inherit shell behavior from base.html, found {label}" def test_base_template_owns_shared_app_tab_style(): base = (STATIC_DIR / "base.html").read_text(encoding="utf-8") assert "Shared App Tabs" in base assert ".main-content :is(.tabs, .tabbar, .admin-tabs, .user-tabs)" in base assert ":is(.tab-btn, .tab, .admin-tab-btn)" in base app_pages_with_tabs = [ "app.html", "paper_trading.html", "live_trading.html", "logs.html", "onchain.html", "admin.html", "iteration.html", ] for name in app_pages_with_tabs: text = (STATIC_DIR / name).read_text(encoding="utf-8") assert "extends \"base.html\"" in text or "extends 'base.html'" in text def test_opportunity_overview_direction_filter_is_client_side_only(): text = (STATIC_DIR / "app.html").read_text(encoding="utf-8") assert "机会状态" in text assert "交易方向" in text assert "全部机会" in text assert "全部方向" in text assert "liveCount" not in text assert "histCount" not in text assert "stat-chip" not in text assert "tab-count" in text assert "数字展示当前加载机会的分布" in text assert "side='+encodeURIComponent(currentSideFilter)" not in text assert 'side="+encodeURIComponent(currentSideFilter)' not in text