Initial commit

This commit is contained in:
ThePetrovich 2026-08-17 22:42:04 +08:00
commit 97e799fd52
61 changed files with 2252 additions and 0 deletions

145
tests/test_ui_kit.py Normal file
View file

@ -0,0 +1,145 @@
"""The kit's snippets, the chrome, and the rules the estate agreed to.
This module used to be copied into every service. It lives here now; a service
keeps only the part that lists its own pages.
"""
from __future__ import annotations
import re
from pathlib import Path
import pytest
from django.template.loader import render_to_string
from django.test import Client
from yksa_web.states import STATES
ROOT = Path(__file__).resolve().parent.parent / "yksa_web"
TEMPLATES = sorted((ROOT / "templates").rglob("*.html"))
STYLESHEETS = [ROOT / "static" / "yksa" / "css" / "kit.css"]
# --- the chrome -------------------------------------------------------------
@pytest.mark.django_db
def test_the_shared_pages_render():
client = Client()
for url in ("/preferences/timezone/", "/privacy/", "/cookies/"):
assert client.get(url).status_code == 200, url
@pytest.mark.django_db
def test_the_navbar_and_footer_are_on_every_page():
"""Both are stated requirements, and both were hand-copied before this."""
html = Client().get("/privacy/").content.decode()
assert "custom-navbar" in html
assert "yksa/img/logo-full-en.svg" in html
assert 'href="/cookies/"' in html # footer link
assert "yksa/css/kit.css" in html
@pytest.mark.django_db
def test_the_service_cannot_reorder_the_chrome():
"""navbar, then main, then footer — a service that wants otherwise has to
stop extending the kit, which is the point."""
html = Client().get("/privacy/").content.decode()
assert html.index("<nav") < html.index("<main") < html.index("<footer")
# --- the snippets -----------------------------------------------------------
def test_state_carries_a_colour_an_icon_and_a_word():
"""Colour is never the only signal: the badge has to survive a colour-blind
reader and a greyscale print."""
html = render_to_string("yksa/ui/_state.html", {"state": "failed"})
assert "yksa-state-failed" in html
assert "bi-x-lg" in html
assert "failed" in html
def test_every_state_in_the_vocabulary_renders():
for name in STATES:
assert f"yksa-state-{name}" in render_to_string(
"yksa/ui/_state.html", {"state": name}
)
def test_an_unknown_state_still_renders():
"""A status the reader can see beats one that silently disappears."""
html = render_to_string("yksa/ui/_state.html", {"state": "nonsense"})
assert "yksa-state-unknown" in html
def test_chip_is_colourless():
"""A chip is a fact, not a status. If it needs a colour it is a state."""
html = render_to_string("yksa/ui/_chip.html", {"text": "v3"})
for variant in ("success", "danger", "warning", "primary"):
assert variant not in html
def test_page_title_is_always_h1_h3():
"""Pages cannot drift apart visually if none of them picks its own size."""
html = render_to_string("yksa/ui/_page_title.html", {"title": "Widgets"})
assert '<h1 class="h3' in html
def test_page_title_links_its_parent():
html = render_to_string("yksa/ui/_page_title.html", {
"title": "W-1", "parent": "Widgets", "parent_url": "/widgets/",
})
assert 'href="/widgets/"' in html
assert "W-1" in html
# --- the estate-wide rules --------------------------------------------------
@pytest.mark.parametrize("banned", ["fw-semibold", "fw-medium", "fw-light", "fw-bolder"])
def test_no_banned_font_weights_in_templates(banned):
"""Weights are 400 and 700. Hierarchy comes from weight, colour and size."""
assert [str(p) for p in TEMPLATES if banned in p.read_text(encoding="utf-8")] == []
@pytest.mark.parametrize("banned", [r"font-weight:\s*[56]00", r"letter-spacing"])
def test_no_banned_typography_in_css(banned):
"""The template rule was enforced and the CSS rule never was, which is how
main.css came to carry font-weight: 500."""
offenders = [
str(p) for p in STYLESHEETS
if re.search(banned, _without_comments(p.read_text(encoding="utf-8")))
]
assert offenders == []
def _without_comments(css: str) -> str:
return re.sub(r"/\*.*?\*/", "", css, flags=re.S)
def test_no_legacy_text_muted():
"""Deprecated in Bootstrap 5.3. Muted text is text-body-secondary."""
assert [str(p) for p in TEMPLATES if "text-muted" in p.read_text(encoding="utf-8")] == []
def test_no_display_classes():
"""`.display-*` is a marketing scale; headings take `.h1`-`.h6`."""
offenders = [
str(p) for p in TEMPLATES
if re.search(r"\bdisplay-[1-6]\b", p.read_text(encoding="utf-8"))
]
assert offenders == []
def test_no_django_comment_syntax():
"""`{# #}` breaks across edits and leaks into rendered output."""
assert [str(p) for p in TEMPLATES if "{#" in p.read_text(encoding="utf-8")] == []
def test_bootstrap_is_at_least_5_3():
"""text-body-secondary and --bs-*-bg-subtle arrived in 5.3. On 5.2.3 every
rule above passes and the page still renders wrong, which is what happened
across the estate before this package owned the bundle."""
bundle = ROOT / "static" / "yksa" / "css" / "bootstrap.min.css"
assert "--bs-success-bg-subtle" in bundle.read_text(encoding="utf-8")