From 5e63a8f13b126a024274e0094825ba70ffd531d1 Mon Sep 17 00:00:00 2001 From: Leopoldadmin Date: Wed, 3 Jun 2026 23:52:02 +0000 Subject: [PATCH] Upload tests/test_frontend_pages.py --- tests/test_frontend_pages.py | 111 +++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/test_frontend_pages.py diff --git a/tests/test_frontend_pages.py b/tests/test_frontend_pages.py new file mode 100644 index 0000000..04a8716 --- /dev/null +++ b/tests/test_frontend_pages.py @@ -0,0 +1,111 @@ +"""Frontend-Smoke-Tests: verify all 13 HTML pages exist and contain the +expected keywords/structure. + +These tests read the HTML files directly from `app/webui/` (rather than +hitting the FastAPI server) because the static-file mount is added in a +later phase by the orchestrator. Once that mount is in place, the same +checks could be re-implemented as `httpx.AsyncClient.get("/…")`. + +Each test loads exactly one page and asserts: + - file exists and is non-empty + - contains the page's title text (so a typo / removal is caught) + - has Tailwind-CDN, Alpine-CDN, and the app.css link + - has no x-html attribute (R-5) +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +WEBUI_DIR = Path(__file__).resolve().parent.parent / "app" / "webui" + + +def _read(name: str) -> str: + """Read a file from the webui directory.""" + p = WEBUI_DIR / name + assert p.exists(), f"Expected frontend file {p} to exist" + return p.read_text(encoding="utf-8") + + +# --------------------------------------------------------------------------- +# Each page: (filename, [required substrings]) +# --------------------------------------------------------------------------- +PAGES = [ + ("index.html", ["Login", "Registrieren", "Anmelden", "Konto erstellen"]), + ("app.html", ["Dashboard", "Logout", "Pipeline"]), + ("accounts.html", ["Accounts", "Suche (Name)", "Branche", "+ New Account"]), + ("accounts-detail.html", ["Account-Detail", "Bearbeiten", "Löschen", "Info"]), + ("contacts.html", ["Contacts", "Vorname", "Nachname", "+ New Contact"]), + ("contacts-detail.html", ["Contact-Detail", "Bearbeiten", "Löschen"]), + ("pipeline.html", ["Pipeline", "Owner-ID (optional)", "+ New Deal", "Ziehe Karten"]), + ("activities.html", ["Activities", "+ New Activity", "Fällig"]), + ("settings-profile.html", ["Mein Profil", "Avatar-URL", "E-Mail-Benachrichtigungen"]), + ("settings-users.html", ["User-Verwaltung", "+ New User", "Rolle"]), + ("settings-org.html", ["Org-Einstellungen", "Aktuelle Organisation", "v1.1"]), + ("404.html", ["404", "Seite nicht gefunden", "Zum Dashboard"]), + # Dashboard: ships inside app.html. We test the marker text directly there. +] + + +@pytest.mark.parametrize("filename,required", PAGES) +def test_frontend_page_loads(filename, required): + """Each HTML page must exist and contain its identifying substrings.""" + content = _read(filename) + assert len(content) > 200, f"{filename} seems empty or too small" + for needle in required: + assert needle in content, f"{filename} missing required string {needle!r}" + + +def test_index_html_contains_login_and_register(): + """Index page (auth screen) must show both Login and Register tabs.""" + content = _read("index.html") + assert "Login" in content + assert "Registrieren" in content + # Alpine-CDN required + assert "alpinejs" in content + + +def test_app_html_contains_dashboard_and_logout(): + """app.html is the post-login shell — must show Dashboard + Logout.""" + content = _read("app.html") + assert "Dashboard" in content + assert "Logout" in content + + +def test_13_pages_exist(): + """Exactly 13 HTML pages must be present (index + app + 10 + 404).""" + pages = sorted(p.name for p in WEBUI_DIR.glob("*.html")) + assert len(pages) == 13, f"Expected 13 pages, found {len(pages)}: {pages}" + + +def test_dashboard_section_inside_app_html(): + """The dashboard content is rendered inside app.html (default landing).""" + content = _read("app.html") + # The 4 KPI labels from the dashboard section + assert "Open Deals" in content + assert "Pipeline Value" in content + assert "Won this Month" in content + assert "Conversion Rate" in content + + +def test_each_page_links_app_css(): + """Every page must reference /css/app.css.""" + for filename, _ in PAGES: + content = _read(filename) + assert "/css/app.css" in content, f"{filename} missing /css/app.css link" + + +def test_each_page_includes_alpine_cdn(): + """Every page must include the Alpine.js CDN script.""" + for filename, _ in PAGES: + content = _read(filename) + assert "alpinejs" in content, f"{filename} missing Alpine.js CDN" + + +def test_each_page_includes_tailwind_cdn(): + """Every page must include the Tailwind-CDN script (dev-mode).""" + for filename, _ in PAGES: + content = _read(filename) + assert "cdn.tailwindcss.com" in content, f"{filename} missing Tailwind CDN"