"""Cache-busting plików statycznych (PRE-26). Po deployu przeglądarka trzymała stare styles.css / *.js (ten sam URL). Doklejamy hash treści → zmiana pliku zmienia URL. Regresja byłaby CICHA (użytkownik widzi stary interfejs), więc pilnujemy strukturalnie. """ import os import pathlib import re os.environ.pop("APP_PASSWORD", None) # import app.main bez bramki logowania from app.main import _asset_version, static_url TEMPLATES = pathlib.Path(__file__).resolve().parents[1] / "app" / "templates" def test_static_url_carries_content_hash(): assert re.fullmatch(r"/static/base\.css\?v=[0-9a-f]{8}", static_url("base.css")) def test_version_is_content_based_so_differs_between_files(): assert _asset_version("base.css") != _asset_version("formsync.js") def test_missing_file_does_not_crash(): assert static_url("nie-ma-takiego.js").endswith("?v=0") def test_no_template_serves_raw_static_paths(): """Żaden href/src nie może iść na surowe /static/... — omijałoby cache-busting.""" for f in TEMPLATES.glob("*.html"): txt = f.read_text(encoding="utf-8") assert 'src="/static/' not in txt, f"{f.name}: surowy src bez cache-bustingu" assert 'href="/static/' not in txt, f"{f.name}: surowy href bez cache-bustingu" def test_base_uses_helper_for_the_shared_stylesheet(): base = (TEMPLATES / "base.html").read_text(encoding="utf-8") assert "static('base.css')" in base def test_version_follows_what_is_sent_not_what_is_on_disk(): """Adres niesie hash treści WYSYŁANEJ, bo komentarze są przy serwowaniu usuwane. Gdyby hash szedł z pliku na dysku, poprawka w samym komentarzu podbijałaby adres i kasowała cache przeglądarki bez żadnej zmiany dla niej.""" import hashlib from app.main import _asset_body assert _asset_version("base.css") == hashlib.md5(_asset_body("base.css")).hexdigest()[:8]